openapi: 3.0.3
info:
  title: PUP - Public Player API v1
  description: >
    Public, unauthenticated API for accessing player profiles that have been
    set to "public" visibility. Rate-limited by IP address.
  version: 1.0.0

servers:
  - url: https://api.gopup.app/
    description: Production server

x-tagGroups:
  - name: Public
    tags:
      - public

tags:
  - name: public
    x-displayName: "Public"
    description: Unauthenticated operations for public player profiles

paths:
  /public/v1/player/{username}:
    get:
      deprecated: true
      tags:
        - public
      summary: Get public player profile
      description: >
        Returns the public profile for a player identified by username.
        Deprecated in favor of the authenticated player API. Only returns
        profiles where visibility is set to "public". Returns 404 for
        non-public or non-existent profiles.
      operationId: getPublicPlayer
      parameters:
        - in: path
          name: username
          required: true
          schema:
            type: string
          description: The player's username
          example: "alice123"
      responses:
        "200":
          description: Player profile found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PlayerResponse"
        "404":
          description: Player not found or profile is not public
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "429":
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

components:
  schemas:
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          description: Human-readable error message

    PlayerResponse:
      type: object
      required:
        - player
      properties:
        player:
          $ref: "#/components/schemas/Player"

    Player:
      type: object
      required:
        - username
        - first_name
        - last_name
        - pup_score
      properties:
        username:
          type: string
          example: "alice123"
        first_name:
          type: string
          example: "Alice"
        last_name:
          type: string
          example: "Johnson"
        country_code:
          type: string
          description: "Country code (ISO 3166-1 alpha-2)"
          example: "NL"
        bio:
          type: string
          nullable: true
          example: "Passionate padel player"
        club:
          type: string
          nullable: true
          example: "Home padel"
        knltb_profile_url:
          type: string
          nullable: true
          format: uri
          example: "https://mijnknltb.toernooi.nl/player-profile/e52a3bc3-9ccc-4ed1-be66-de7510a61f86"
        best_hand:
          type: string
          nullable: true
          enum: ["left", "right", "both"]
        position_on_court:
          type: string
          nullable: true
          enum: ["left", "right", "both"]
        skills:
          type: object
          additionalProperties:
            type: integer
        picture_url:
          type: string
          nullable: true
          format: uri
          description: "URL to profile picture"
        card_image_url:
          type: string
          nullable: true
          format: uri
          description: "URL to pre-rendered player card image"
        ratings:
          type: array
          items:
            $ref: "#/components/schemas/Rating"
        pup_score:
          type: integer
          minimum: 0
          example: 67
        age:
          type: integer
          nullable: true
          minimum: 0
          example: 28
        completed_challenges:
          type: integer
          minimum: 0
          example: 3
          description: "Number of challenges the player has completed and had verified"
        active_participations:
          type: integer
          minimum: 0
          example: 1
          description: "Number of challenges the player is currently participating in (active or pending review)"
        recent_completions:
          type: array
          description: "The 5 most recently verified challenge completions"
          items:
            $ref: "#/components/schemas/ChallengeCompletion"

    Rating:
      type: object
      required:
        - provider
        - rating
      properties:
        provider:
          type: string
          example: "KNLTB"
        rating:
          type: string
          example: "5.12345"
          pattern: '^\d+(\.\d+)?$'

    ChallengeCompletion:
      type: object
      required:
        - challenge_id
        - challenge_title
        - verified_at
      properties:
        challenge_id:
          type: string
          description: "Challenge identifier"
          example: "155eb3b5-30f8-4ff5-ae74-4f9570c28ebe"
        challenge_title:
          type: string
          description: "Challenge title"
          example: "5km Run"
        challenge_club_name:
          type: string
          nullable: true
          description: "Name of the club that issued the challenge"
          example: "Home Padel"
        verified_at:
          type: string
          format: date-time
          description: "Timestamp when the completion was verified"
