Lichess Puzzles API

Fetch and solve [puzzles](https://lichess.org/training), view your puzzle history and dashboard. Our collection of puzzles is in the public domain, you can [download it here](https://database.lichess.org/#puzzles). For a list of our [puzzle themes](https://lichess.org/training/themes) with their description, check out the [theme translation file](https://github.com/ornicar/lila/blob/master/translation/source/puzzleTheme.xml).

OpenAPI Specification

lichess-puzzles-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  version: 2.0.144
  title: Lichess.org API reference Account Puzzles API
  contact:
    name: Lichess.org API
    url: https://lichess.org/api
    email: contact@lichess.org
  x-logo:
    url: https://lichess1.org/assets/logo/lichess-pad12.svg
  license:
    name: AGPL-3.0-or-later
    url: https://www.gnu.org/licenses/agpl-3.0.txt
  description: '# Introduction

    Welcome to the reference for the Lichess API! Lichess is free/libre,

    open-source chess server powered by volunteers and donations.

    - Get help in the [Lichess Discord channel](https://discord.gg/lichess)

    - API demo app with OAuth2 login and gameplay: [source](https://github.com/lichess-org/api-demo) / [demo](https://lichess-org.github.io/api-demo/)

    - API UI app with OAuth2 login and endpoint forms: [source](https://github.com/lichess-org/api-ui) / [website](https://lichess.org/api/ui)

    - [Contribute to this documentation on Github](https://github.com/lichess-org/api)

    - Check out [Lichess widgets to embed in your website](https://lichess.org/developers)

    - [Download all Lichess rated games](https://database.lichess.org/)

    - [Download all Lichess puzzles with themes, ratings and votes](https://database.lichess.org/#puzzles)

    - [Download all evaluated positions](https://database.lichess.org/#evals)


    ## Endpoint

    All requests go to `https://lichess.org` (unless otherwise specified).


    ## Clients

    - [Python general API](https://github.com/lichess-org/berserk)

    - [MicroPython general API](https://github.com/mkomon/uberserk)

    - [Python general API - async](https://pypi.org/project/async-lichess-sdk)

    - [Python Lichess Bot](https://github.com/lichess-bot-devs/lichess-bot)

    - [Python Board API for Certabo](https://github.com/haklein/certabo-lichess)

    - [Java general API](https://github.com/tors42/chariot)

    - [JavaScript & TypeScript general API](https://github.com/devjiwonchoi/equine)

    - [LichessNET - C# API Wrapper](https://github.com/Rabergsel/LichessNET)

    - [.NET general API](https://github.com/Dblike/LichessSharp)


    ## Rate limiting

    All requests are rate limited using various strategies,

    to ensure the API remains responsive for everyone.

    Only make one request at a time.

    If you receive an HTTP response with a [429 status](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#429),

    you have exceded one of the rate limits.

    In most cases, waiting one minute before retrying will be sufficient, but some limits may require longer.

    Reduce your request frequency before retrying.


    ## Streaming with ND-JSON

    Some API endpoints stream their responses as [Newline Delimited JSON a.k.a. **nd-json**](https://github.com/ndjson/ndjson-spec), with one JSON object per line.


    Here''s a [JavaScript utility function](https://gist.github.com/ornicar/a097406810939cf7be1df8ea30e94f3e) to help reading NDJSON streamed responses.


    ## Authentication

    ### Which authentication method is right for me?

    [Read about the Lichess API authentication methods and code examples](https://github.com/lichess-org/api/blob/master/example/README.md)


    ### Personal Access Token

    Personal API access tokens allow you to quickly interact with Lichess API without going through an OAuth flow.

    - [Generate a personal access token](https://lichess.org/account/oauth/token)

    - `curl https://lichess.org/api/account -H "Authorization: Bearer {token}"`

    - [NodeJS example](https://github.com/lichess-org/api/tree/master/example/oauth-personal-token)


    ### Token Security

    - Keep your tokens secret. Do not share them in public repositories or public forums.

    - Your tokens can be used to make your account perform arbitrary actions (within the limits of the tokens'' scope). You remain responsible for all activities on your account.

    - Do not hardcode tokens in your application''s code. Use environment variables or a secure storage and ensure they are not shipped/exposed to users. Be especially careful that they are not included in frontend bundles or apps that are shipped to users.

    - If you suspect a token has been compromised, revoke it immediately.


    To see your active tokens or revoke them, see [your Personal API access tokens](https://lichess.org/account/oauth/token).


    ### Authorization Code Flow with PKCE

    The authorization code flow with PKCE allows your users to **login with Lichess**.

    Lichess supports unregistered and public clients (no client authentication, choose any unique client id).

    The only accepted code challenge method is `S256`.

    Access tokens are long-lived (expect one year), unless they are revoked.

    Refresh tokens are not supported.


    See the [documentation for the OAuth endpoints](#tag/OAuth) or

    the [PKCE RFC](https://datatracker.ietf.org/doc/html/rfc7636#section-4) for a precise protocol description.


    - [Demo app](https://lichess-org.github.io/api-demo/)

    - [Minimal client-side example](https://github.com/lichess-org/api/tree/master/example/oauth-app)

    - [Flask/Python example](https://github.com/lakinwecker/lichess-oauth-flask)

    - [Java example](https://github.com/tors42/lichess-oauth-pkce-app)

    - [NodeJS Passport strategy to login with Lichess OAuth2](https://www.npmjs.com/package/passport-lichess)


    #### Real life examples

    - [PyChess](https://github.com/gbtami/pychess-variants) ([source code](https://github.com/gbtami/pychess-variants))

    - [Lichess4545](https://www.lichess4545.com/) ([source code](https://github.com/cyanfish/heltour))

    - [English Chess Federation](https://ecf.octoknight.com/)

    - [Rotherham Online Chess](https://rotherhamonlinechess.azurewebsites.net/tournaments)


    ### Token format

    Access tokens and authorization codes match `^[A-Za-z0-9_]+$`.

    The length of tokens can be increased without notice. Make sure your application can handle at least 512 characters.

    By convention tokens have a recognizable prefix, but do not rely on this.

    '
servers:
- url: https://lichess.org
- url: https://lichess.dev
- url: http://localhost:{port}
  variables:
    port:
      default: '8080'
- url: http://l.org
tags:
- name: Puzzles
  description: 'Fetch and solve [puzzles](https://lichess.org/training), view your puzzle history and dashboard.


    Our collection of puzzles is in the public domain, you can [download it here](https://database.lichess.org/#puzzles).

    For a list of our [puzzle themes](https://lichess.org/training/themes) with their description, check out the [theme translation file](https://github.com/ornicar/lila/blob/master/translation/source/puzzleTheme.xml).

    '
paths:
  /api/puzzle/daily:
    get:
      operationId: apiPuzzleDaily
      summary: Get the daily puzzle
      description: 'Get the daily Lichess puzzle in JSON format.

        '
      tags:
      - Puzzles
      security: []
      responses:
        '200':
          description: The daily puzzle.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PuzzleAndGame'
              examples:
                default:
                  $ref: '#/components/examples/puzzles-getDailyPuzzle.json'
  /api/puzzle/{id}:
    get:
      operationId: apiPuzzleId
      summary: Get a puzzle by its ID
      description: Get a single Lichess puzzle in JSON format.
      tags:
      - Puzzles
      security: []
      parameters:
      - in: path
        name: id
        required: true
        description: The puzzle ID
        schema:
          type: string
      responses:
        '200':
          description: The requested puzzle.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PuzzleAndGame'
              examples:
                default:
                  $ref: '#/components/examples/puzzles-getPuzzleById.json'
  /api/puzzle/next:
    get:
      operationId: apiPuzzleNext
      summary: Get a new puzzle
      description: 'Get a random Lichess puzzle in JSON format.


        If authenticated, only returns puzzles that the user has never seen before.


        **DO NOT** use this endpoint to enumerate puzzles for mass download. Instead, download the [full public puzzle database](https://database.lichess.org/#puzzles).

        '
      tags:
      - Puzzles
      security:
      - OAuth2:
        - puzzle:read
      parameters:
      - in: query
        name: angle
        required: false
        description: 'The theme or opening to filter puzzles with.


          Available themes are listed in [the lichess source code](https://github.com/ornicar/lila/blob/master/translation/source/puzzleTheme.xml) and [the lichess training themes hyperlinks](https://lichess.org/training/themes).

          '
        schema:
          type: string
      - in: query
        name: difficulty
        required: false
        description: The desired puzzle difficulty, relative to the authenticated user puzzle rating, or 1500 if anonymous.
        schema:
          type: string
          enum:
          - easiest
          - easier
          - normal
          - harder
          - hardest
      - in: query
        name: color
        required: false
        description: The color to play. Better left empty to automatically get 50% white.
        schema:
          type: string
          enum:
          - white
          - black
      responses:
        '200':
          description: The requested puzzle.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PuzzleAndGame'
              examples:
                default:
                  $ref: '#/components/examples/puzzles-getNewPuzzle.json'
  /api/puzzle/batch/{angle}:
    get:
      operationId: apiPuzzleBatchSelect
      summary: Get multiple puzzles at once
      description: 'Get a batch of random Lichess puzzles in JSON format.


        If authenticated, only returns puzzles that the user has never seen before.


        **DO NOT** use this endpoint to enumerate puzzles for mass download. Instead, download the [full public puzzle database](https://database.lichess.org/#puzzles).

        '
      tags:
      - Puzzles
      security:
      - OAuth2:
        - puzzle:read
      parameters:
      - in: path
        name: angle
        schema:
          type: string
          example: mix
        required: true
        description: 'The theme or opening to filter puzzles with. Recommended: `mix`.


          Available themes are listed in [the lichess source code](https://github.com/ornicar/lila/blob/master/translation/source/puzzleTheme.xml) and [the lichess training themes hyperlinks](https://lichess.org/training/themes).

          '
      - in: query
        name: difficulty
        required: false
        description: The desired puzzle difficulty, relative to the authenticated user puzzle rating, or 1500 if anonymous.
        schema:
          type: string
          enum:
          - easiest
          - easier
          - normal
          - harder
          - hardest
      - in: query
        name: nb
        description: 'How many puzzles to fetch. Just set it to `1` if you only need one puzzle.

          '
        schema:
          type: integer
          minimum: 1
          maximum: 50
          example: 10
          default: 15
        required: false
      - in: query
        name: color
        required: false
        description: 'The color to play. Better left empty to automatically get 50% white.

          Currently only works when `nb=1`.

          '
        schema:
          type: string
          enum:
          - white
          - black
      responses:
        '200':
          description: The requested puzzles.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PuzzleBatchSelect'
              examples:
                default:
                  $ref: '#/components/examples/puzzles-getMultiplePuzzlesAtOnce.json'
    post:
      operationId: apiPuzzleBatchSolve
      summary: Solve multiple puzzles at once
      description: 'Set puzzles as solved and update ratings.

        '
      tags:
      - Puzzles
      security:
      - OAuth2:
        - puzzle:write
      parameters:
      - in: path
        name: angle
        schema:
          type: string
          example: mix
        required: true
        description: 'The theme or opening of the solved puzzles.


          Available themes are listed in [the lichess source code](https://github.com/ornicar/lila/blob/master/translation/source/puzzleTheme.xml) and [the lichess training themes hyperlinks](https://lichess.org/training/themes).

          '
      - in: query
        name: nb
        description: 'When > 0, the response includes a new puzzle batch with that many puzzles.


          This is equivalent to calling [/api/puzzle/batch/{angle}](#tag/puzzles/GET/api/puzzle/batch/{angle}),

          and can sometimes save a request.

          '
        schema:
          type: integer
          minimum: 0
          maximum: 50
          example: 1
          default: 0
        required: false
      requestBody:
        description: List of solved puzzles
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PuzzleBatchSolveRequest'
      responses:
        '200':
          description: The solved puzzles, named `rounds`, and a new puzzle batch named `puzzles`.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PuzzleBatchSolveResponse'
              examples:
                default:
                  $ref: '#/components/examples/puzzles-solveMultiplePuzzlesAtOnce.json'
  /api/puzzle/activity:
    get:
      operationId: apiPuzzleActivity
      summary: Get your puzzle activity
      description: 'Download your puzzle activity in [ndjson](#description/streaming-with-nd-json) format.

        Puzzle activity is sorted by reverse chronological order (most recent first)

        We recommend streaming the response, for it can be very long.

        '
      tags:
      - Puzzles
      security:
      - OAuth2:
        - puzzle:read
      parameters:
      - in: query
        name: max
        description: How many entries to download. Leave empty to download all activity.
        schema:
          type: integer
          minimum: 1
      - in: query
        name: before
        description: Download entries before this timestamp. Defaults to now. Use `before` and `max` for pagination.
        schema:
          type: integer
          minimum: 1356998400070
      - in: query
        name: since
        description: Download entries since this timestamp. Defaults to account creation date.
        schema:
          type: integer
          minimum: 1356998400070
      responses:
        '200':
          description: The puzzle activity of the logged in user.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/x-ndjson:
              schema:
                $ref: '#/components/schemas/PuzzleActivity'
              examples:
                default:
                  $ref: '#/components/examples/puzzles-getYourPuzzleActivity.json'
  /api/puzzle/replay/{days}/{theme}:
    get:
      operationId: apiPuzzleReplay
      summary: Get puzzles to replay
      description: Gets the puzzle IDs of remaining puzzles to re-attempt in JSON format.
      tags:
      - Puzzles
      security:
      - OAuth2:
        - puzzle:read
      parameters:
      - in: path
        name: days
        required: true
        description: How many days to look back when aggregating puzzle results. 30 is sensible.
        schema:
          type: integer
      - in: path
        name: theme
        required: true
        description: The theme or opening to filter puzzles with.
        schema:
          type: string
      responses:
        '200':
          description: The requested puzzles to replay.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PuzzleReplay'
              examples:
                default:
                  $ref: '#/components/examples/puzzles-getPuzzlesToReplay.json'
        '404':
          description: No puzzles to replay were found
          content:
            application/json:
              schema:
                properties:
                  error:
                    type: string
                    example: No puzzles to replay
  /api/puzzle/dashboard/{days}:
    get:
      operationId: apiPuzzleDashboard
      summary: Get your puzzle dashboard
      description: 'Download your [puzzle dashboard](https://lichess.org/training/dashboard/30/dashboard) as JSON.

        Also includes all puzzle themes played, with aggregated results.

        Allows re-creating the [improvement/strengths](https://lichess.org/training/dashboard/30/improvementAreas) interfaces.

        '
      tags:
      - Puzzles
      security:
      - OAuth2:
        - puzzle:read
      parameters:
      - in: path
        name: days
        required: true
        description: How many days to look back when aggregating puzzle results. 30 is sensible.
        schema:
          type: integer
          minimum: 1
      responses:
        '200':
          description: The puzzle dashboard of the logged in user.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PuzzleDashboard'
              examples:
                default:
                  $ref: '#/components/examples/puzzles-getYourPuzzleDashboard.json'
  /api/storm/dashboard/{username}:
    get:
      operationId: apiStormDashboard
      summary: Get the storm dashboard of a player
      description: 'Download the [storm dashboard](https://lichess.org/storm/dashboard/mrbasso) of any player as JSON.

        Contains the aggregated highscores, and the history of storm runs aggregated by days.

        Use `?days=0` if you only care about the highscores.

        '
      tags:
      - Puzzles
      security: []
      parameters:
      - in: path
        name: username
        description: Username of the player
        schema:
          type: string
        required: true
      - in: query
        name: days
        description: How many days of history to return
        schema:
          type: integer
          minimum: 0
          maximum: 365
          default: 30
      responses:
        '200':
          description: The storm dashboard of a player.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PuzzleStormDashboard'
              examples:
                default:
                  $ref: '#/components/examples/puzzles-getStormDashboardOfPlayer.json'
  /api/racer:
    post:
      operationId: racerPost
      summary: Create and join a puzzle race
      description: 'Create a new private [puzzle race](https://lichess.org/racer).

        The Lichess user who creates the race must join the race page,

        and manually start the race when enough players have joined.

        - <https://lichess.org/racer>

        '
      tags:
      - Puzzles
      security:
      - OAuth2:
        - racer:write
      responses:
        '200':
          description: The new puzzle race.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PuzzleRacer'
              examples:
                default:
                  $ref: '#/components/examples/puzzles-createAndJoinPuzzleRace.json'
  /api/racer/{id}:
    get:
      operationId: racerGet
      summary: Get puzzle race results
      description: 'Get the results of a [puzzle race](https://lichess.org/racer).

        Returns information about players, puzzles, and the current status of the race.

        - <https://lichess.org/racer>


        Note that Lichess puzzle races are not persisted, and are only available

        for 30 minutes. After that delay, they are permanently deleted.

        '
      tags:
      - Puzzles
      security:
      - OAuth2: []
      parameters:
      - in: path
        name: id
        description: The puzzle race ID
        schema:
          type: string
        required: true
      responses:
        '200':
          description: The puzzle race results.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PuzzleRaceResults'
              examples:
                default:
                  $ref: '#/components/examples/puzzles-getRaceResults.json'
        '404':
          description: The puzzle race was not found, or is no longer available.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFound'
components:
  schemas:
    PuzzleBatchSolveRequest:
      type: object
      properties:
        solutions:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              win:
                type: boolean
              rated:
                type: boolean
    PuzzleDashboard:
      type: object
      properties:
        days:
          type: integer
        global:
          $ref: '#/components/schemas/PuzzlePerformance'
        themes:
          type: object
          additionalProperties:
            type: object
            properties:
              results:
                $ref: '#/components/schemas/PuzzlePerformance'
              theme:
                type: string
            required:
            - results
            - theme
      required:
      - days
      - global
      - themes
    PuzzleAndGame:
      type: object
      properties:
        game:
          type: object
          properties:
            clock:
              type: string
            id:
              type: string
            perf:
              type: object
              properties:
                key:
                  $ref: '#/components/schemas/PerfType'
                name:
                  type: string
              required:
              - key
              - name
            pgn:
              type: string
            players:
              type: array
              items:
                type: object
                properties:
                  color:
                    $ref: '#/components/schemas/GameColor'
                  flair:
                    $ref: '#/components/schemas/Flair'
                  id:
                    type: string
                  name:
                    type: string
                  patron:
                    $ref: '#/components/schemas/Patron'
                  patronColor:
                    $ref: '#/components/schemas/PatronColor'
                  rating:
                    type: integer
                  title:
                    $ref: '#/components/schemas/Title'
                required:
                - color
                - id
                - name
                - rating
              minItems: 2
              maxItems: 2
            rated:
              type: boolean
          required:
          - clock
          - id
          - perf
          - pgn
          - players
          - rated
          additionalProperties: false
        puzzle:
          type: object
          properties:
            id:
              type: string
            initialPly:
              type: integer
            plays:
              type: integer
            rating:
              type: integer
            fen:
              type: string
            lastMove:
              type: string
              description: In UCI format, e.g. "e2e4"
            solution:
              type: array
              items:
                type: string
            themes:
              type: array
              items:
                type: string
          required:
          - id
          - initialPly
          - plays
          - rating
          - solution
          - themes
          additionalProperties: false
      required:
      - game
      - puzzle
    PatronColor:
      type: integer
      description: 'Players can choose a color for their Patron wings.

        See [here for the color mappings](https://github.com/lichess-org/lila/blob/master/ui/lib/css/abstract/_patron-colors.scss).


        The presence of this field indicates the player is an active Patron.

        '
      minimum: 1
      maximum: 10
    PuzzleBatchSolveResponse:
      type: object
      properties:
        puzzles:
          type: array
          items:
            $ref: '#/components/schemas/PuzzleAndGame'
        glicko:
          $ref: '#/components/schemas/PuzzleGlicko'
        rounds:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              win:
                type: boolean
              ratingDiff:
                type: integer
    PuzzleRacer:
      type: object
      properties:
        id:
          type: string
        url:
          type: string
          format: uri
      required:
      - id
      - url
    PuzzlePerformance:
      type: object
      properties:
        firstWins:
          type: integer
        nb:
          type: integer
        performance:
          type: integer
        puzzleRatingAvg:
          type: integer
        replayWins:
          type: integer
      required:
      - firstWins
      - nb
      - performance
      - puzzleRatingAvg
      - replayWins
    Patron:
      type: boolean
      deprecated: true
      description: 'Use patronColor value instead to determine if player is a patron.

        '
    GameColor:
      type: string
      enum:
      - white
      - black
    NotFound:
      properties:
        error:
          type: string
      required:
      - error
      example:
        error: Not found.
    PuzzleBatchSelect:
      type: object
      properties:
        puzzles:
          type: array
          items:
            $ref: '#/components/schemas/PuzzleAndGame'
        glicko:
          $ref: '#/components/schemas/PuzzleGlicko'
    PerfType:
      type: string
      enum:
      - ultraBullet
      - bullet
      - blitz
      - rapid
      - classical
      - correspondence
      - chess960
      - crazyhouse
      - antichess
      - atomic
      - horde
      - kingOfTheHill
      - racingKings
      - threeCheck
    PuzzleStormDashboard:
      type: object
      properties:
        days:
          type: array
          items:
            type: object
            properties:
              _id:
                type: string
              combo:
                type: integer
              errors:
                type: integer
              highest:
                type: integer
              moves:
                type: integer
              runs:
                type: integer
              score:
                type: integer
              time:
                type: integer
            required:
            - _id
            - combo
            - errors
            - highest
            - moves
            - runs
            - score
            - time
        high:
          type: object
          properties:
            allTime:
              type: integer
            day:
              type: integer
            month:
              type: integer
            week:
              type: integer
          required:
          - allTime
          - day
          - month
          - week
      required:
      - days
      - high
    Flair:
      type: string
      description: See [available flair list and images](https://github.com/lichess-org/lila/tree/master/public/flair)
    PuzzleGlicko:
      type: object
      properties:
        rating:
          type: number
        deviation:
          type: number
        provisional:
          type: boolean
    PuzzleReplay:
      type: object
      properties:
        replay:
          type: object
          properties:
            days:
              type: integer
            theme:
              type: string
            nb:
              type: integer
            remaining:
              type: array
              items:
                type: string
          required:
          - days
          - theme
          - nb
          - remaining
        angle:
          type: object
          properties:
            key:
              type: string
            name:
              type: string
            desc:
              type: string
          required:
          - key
          - name
          - desc
      required:
      - replay
      - angle
    PuzzleActivity:
      type: object
      properties:
        date:
          type: integer
        puzzle:
          type: object
          properties:
            fen:
              type: string
            id:
              type: string
            lastMove:
              type: string
            plays:
              type: integer
            rating:
              type: integer
            solution:
              type: array
              items:
                type: string
            themes:
              type: array
              items:
                type: string
          required:
          - fen
          - id
          - lastMove
          - plays
          - rating
          - solution
          - themes
        win:
          type: boolean
      required:
      - date
      - puzzle
      - win
    Title:
      type: string
      enum:
      - GM
      - WGM
      - IM
      - WIM
      - FM
      - WFM
      - NM
      - CM
      - WCM
      - WNM
      - LM
      - BOT
      description: only appears if the user is a titled player or a bot user
    PuzzleRaceResults:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier of the puzzle race
        owner:
          type: string
          description: Owner of the puzzle race
        players:
          type: array
          description: List of players participating in the race
          items:
            type: object
            properties:
              name:
                type: string
                description: Player username
              score:
                type: integer
                description: Player's current score in the race
              id:
                type: string
                description: User ID. Missing if player is anonymous.
              flair:
                type: string
                description: User's flair icon
              patron:
                $ref: '#/components/schemas/Patron'
              patronColor:
                $ref: '#/components/schemas/PatronColor'
            required:
            - name
            - score
        puzzles:
          type: array
          description: List of puzzles in the race
          items:
            type: object

# --- truncated at 32 KB (56 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/lichess/refs/heads/main/openapi/lichess-puzzles-api-openapi.yml