Lichess External engine API

**This API is in alpha and subject to change.** Use or provide external engine analysis. External engines can provide analysis on pages like the [analysis board](https://lichess.org/analysis), running as a service outside of the browser, or even on a different machine.

OpenAPI Specification

lichess-external-engine-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  version: 2.0.144
  title: Lichess.org API reference Account External engine 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: External engine
  description: '**This API is in alpha and subject to change.**


    Use or provide external engine analysis.


    External engines can provide analysis on pages like the

    [analysis board](https://lichess.org/analysis), running as a service

    outside of the browser, or even on a different machine.

    '
paths:
  /api/external-engine:
    get:
      operationId: apiExternalEngineList
      summary: List external engines
      tags:
      - External engine
      security:
      - OAuth2:
        - engine:read
      description: 'Lists all external engines that have been registered for the user,

        and the credentials required to use them.

        '
      responses:
        '200':
          description: A list of external engines.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ExternalEngine'
              examples:
                default:
                  $ref: '#/components/examples/externalEngine-listExternalEngines.json'
    post:
      operationId: apiExternalEngineCreate
      summary: Create external engine
      tags:
      - External engine
      security:
      - OAuth2:
        - engine:write
      description: 'Registers a new external engine for the user. It can then be selected

        and used on the analysis board.

        After registering, the provider should start waiting for analyis requests.

        '
      requestBody:
        description: A new external engine registration.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExternalEngineRegistration'
      responses:
        '200':
          description: The registered engine.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExternalEngine'
              examples:
                default:
                  $ref: '#/components/examples/externalEngine-createExternalEngine.json'
  /api/external-engine/{id}:
    parameters:
    - in: path
      name: id
      required: true
      description: The external engine id.
      schema:
        type: string
      example: eei_aTKImBJOnv6j
    get:
      operationId: apiExternalEngineGet
      summary: Get external engine
      tags:
      - External engine
      security:
      - OAuth2:
        - engine:read
      description: 'Get properties and credentials of an external engine.

        '
      responses:
        '200':
          description: A registered engine.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExternalEngine'
              examples:
                default:
                  $ref: '#/components/examples/externalEngine-getExternalEngine.json'
    put:
      operationId: apiExternalEnginePut
      summary: Update external engine
      tags:
      - External engine
      security:
      - OAuth2:
        - engine:write
      description: 'Updates the properties of an external engine.

        '
      requestBody:
        description: A modified engine registration.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExternalEngineRegistration'
      responses:
        '200':
          description: A registered engine.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExternalEngine'
              examples:
                default:
                  $ref: '#/components/examples/externalEngine-updateExternalEngine.json'
    delete:
      operationId: apiExternalEngineDelete
      summary: Delete external engine
      tags:
      - External engine
      security:
      - OAuth2:
        - engine:write
      description: 'Unregisters an external engine.

        '
      responses:
        '200':
          description: Engine successfully deleted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Ok'
              examples:
                default:
                  $ref: '#/components/examples/externalEngine-deleteExternalEngine.json'
  /api/external-engine/{id}/analyse:
    parameters:
    - in: path
      name: id
      required: true
      description: The external engine id.
      schema:
        type: string
      example: eei_aTKImBJOnv6j
    post:
      operationId: apiExternalEngineAnalyse
      summary: Analyse with external engine
      tags:
      - External engine
      servers:
      - url: https://engine.lichess.ovh
      - url: http://localhost:{port}
        variables:
          port:
            default: '9666'
      security: []
      description: '**Endpoint: `https://engine.lichess.ovh/api/external-engine/{id}/analyse`**

        Request analysis from an external engine.

        Response content is streamed as [newline delimited JSON](#description/streaming-with-nd-json).

        The properties are based on the [UCI specification](https://backscattering.de/chess/uci/#engine).

        Analysis stops when the client goes away, the requested limit

        is reached, or the provider goes away.

        '
      requestBody:
        description: Engine credentials and analysis request.
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                clientSecret:
                  type: string
                  example: ees_mdF2hK0hlKGSPeC6
                work:
                  $ref: '#/components/schemas/ExternalEngineWork'
              required:
              - clientSecret
              - work
      responses:
        '200':
          description: Stream of analysis output
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/x-ndjson:
              schema:
                type: object
                properties:
                  time:
                    type: integer
                    description: Number of milliseconds the search has been going on
                    minimum: 0
                  depth:
                    type: integer
                    description: Current search depth
                    minimum: 0
                  nodes:
                    type: integer
                    description: Number of nodes visited so far
                    minimum: 0
                  pvs:
                    type: array
                    description: Information about up to 5 pvs, with the primary pv at index 0.
                    items:
                      type: object
                      properties:
                        depth:
                          type: integer
                          description: Current search depth of the pv
                          minimum: 0
                        cp:
                          type: integer
                          description: Evaluation in centi-pawns, from White's point of view
                        mate:
                          type: integer
                          description: Evaluation in signed moves to mate, from White's point of view
                        moves:
                          type: array
                          description: Variation in UCI notation
                          items:
                            type: string
                      required:
                      - depth
                      - moves
                required:
                - time
                - depth
                - nodes
                - pvs
              examples:
                default:
                  $ref: '#/components/examples/externalEngine-analyseWithExternalEngine.json'
  /api/external-engine/work:
    post:
      operationId: apiExternalEngineAcquire
      summary: Acquire analysis request
      tags:
      - External engine
      servers:
      - url: https://engine.lichess.ovh
      - url: http://localhost:{port}
        variables:
          port:
            default: '9666'
      security: []
      description: '**Endpoint: `https://engine.lichess.ovh/api/external-engine/work`**

        Wait for an analysis requests to any of the external engines that

        have been registered with the given `secret`.

        Uses long polling.

        After acquiring a request, the provider should immediately

        [start streaming the results](#tag/external-engine/POST/api/external-engine/work/{id}).

        '
      requestBody:
        description: Provider credentials.
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                providerSecret:
                  type: string
                  example: Dee3uwieZei9ahpaici9bee2yahsai0K
              required:
              - providerSecret
      responses:
        '200':
          description: Analysis has been requested
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    example: aingoohiJee2sius
                  work:
                    $ref: '#/components/schemas/ExternalEngineWork'
                  engine:
                    $ref: '#/components/schemas/ExternalEngine'
                required:
                - id
                - engine
                - work
              examples:
                default:
                  $ref: '#/components/examples/externalEngine-acquireAnalysisRequest.json'
        '204':
          description: No pending analysis
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
  /api/external-engine/work/{id}:
    parameters:
    - in: path
      name: id
      required: true
      schema:
        type: string
        example: aingoohiJee2sius
    post:
      operationId: apiExternalEngineSubmit
      summary: Answer analysis request
      tags:
      - External engine
      servers:
      - url: https://engine.lichess.ovh
      - url: http://localhost:{port}
        variables:
          port:
            default: '9666'
      security: []
      description: "**Endpoint: `https://engine.lichess.ovh/api/external-engine/work/{id}`**\nSubmit a stream of analysis as [UCI output](https://backscattering.de/chess/uci/#engine-info).\n* The engine should always be in `UCI_Chess960` mode.\n* `UCI_AnalyseMode` enabled if available.\n* It produces `info` with at least:\n  - `depth`\n  - `multipv` (between 1 and 5)\n  - `score`\n  - `nodes`\n  - `time`\n  - `pv`\nThe server may close the connection at any time, indicating that\nthe requester has gone away and analysis should be stopped.\n"
      requestBody:
        description: Analysis results
        required: true
        content:
          text/plain:
            schema:
              type: string
            example: info multipv 1 depth 20 seldepth 30 time 1373 nodes 1494341 score cp 47 hashfull 594 nps 1088376 tbhits 0 pv d2d4 d7d5 c2c4 e7e6 b1c3 f8b4 c4d5 e6d5 g1f3 g8f6 c1g5 h7h6 g5f6 d8f6 d1b3 c7c5 e2e3 b8c6 d4c5 e8g8 f1d3
      responses:
        '200':
          description: Thanks
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
components:
  examples:
    externalEngine-listExternalEngines.json:
      value:
      - id: eei_NU53ONEmZqij
        name: Stockfish 17
        userId: bobby
        maxThreads: 8
        maxHash: 2048
        variants:
        - chess
        providerData: null
        clientSecret: ees_K6cAs9Fo2kblqep4
    externalEngine-createExternalEngine.json:
      value:
        id: eei_NU53ONEmZqij
        name: Stockfish 17
        userId: bobby
        maxThreads: 8
        maxHash: 2048
        variants:
        - chess
        providerData: null
        clientSecret: ees_K6cAs9Fo2kblqep4
    externalEngine-getExternalEngine.json:
      value:
        id: eei_NU53ONEmZqij
        name: Stockfish 17
        userId: bobby
        maxThreads: 8
        maxHash: 2048
        variants:
        - chess
        providerData: null
        clientSecret: ees_K6cAs9Fo2kblqep4
    externalEngine-analyseWithExternalEngine.json:
      value:
        time: 2
        depth: 1
        nodes: 20
        pvs:
        - moves: []
          cp: 13
          depth: 1
    externalEngine-deleteExternalEngine.json:
      value:
        ok: true
    externalEngine-acquireAnalysisRequest.json:
      value:
        id: ygxzCoNU0wUXodLm
        work:
          sessionId: '1'
          threads: 1
          hash: 2048
          depth: 1
          multiPv: 1
          variant: chess
          initialFen: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
          moves:
          - e2e4
          - g8f6
        engine:
          id: eei_dw2szwYp76C9
          name: Stockfish 17.1
          clientSecret: ees_EjQe0iSY6TGhsvCW
          userId: bobby
          maxThreads: 8
          maxHash: 2048
          variants:
          - chess
          providerData: null
    externalEngine-updateExternalEngine.json:
      value:
        id: eei_NU53ONEmZqij
        name: Stockfish 17.1
        userId: bobby
        maxThreads: 8
        maxHash: 2048
        variants:
        - chess
        providerData: null
        clientSecret: ees_K6cAs9Fo2kblqep4
  schemas:
    UciVariant:
      type: string
      enum:
      - chess
      - crazyhouse
      - antichess
      - atomic
      - horde
      - kingofthehill
      - racingkings
      - 3check
      example: chess
      default: chess
    Ok:
      properties:
        ok:
          type: boolean
      required:
      - ok
    ExternalEngine:
      type: object
      properties:
        id:
          type: string
          description: Unique engine registration ID.
        name:
          type: string
          description: Display name of the engine.
          minLength: 3
          maxLength: 200
        clientSecret:
          type: string
          description: 'A secret token that can be used to

            [*request* analysis](#tag/external-engine/POST/api/external-engine/{id}/analyse)

            from this external engine.

            '
        userId:
          type: string
          description: The user this engine has been registered for.
        maxThreads:
          type: integer
          description: Maximum number of available threads.
          minimum: 1
          maximum: 65536
        maxHash:
          type: integer
          description: Maximum available hash table size, in MiB.
          minimum: 1
          maximum: 1048576
        variants:
          type: array
          description: List of supported chess variants.
          items:
            $ref: '#/components/schemas/UciVariant'
        providerData:
          type:
          - string
          - 'null'
          description: 'Arbitrary data that the engine provider can use for identification

            or bookkeeping.


            Users can read this information, but updating it requires knowing

            or changing the `providerSecret`.

            '
      required:
      - id
      - clientSecret
      - userId
      - name
      - maxThreads
      - maxHash
      - variants
    ExternalEngineWorkCommon:
      type: object
      properties:
        sessionId:
          type: string
          description: 'Arbitary string that identifies the analysis session.

            Providers may wish to clear the hash table between sessions.

            '
        threads:
          type: integer
          minimum: 1
          description: Number of threads to use for analysis.
        hash:
          type: integer
          minimum: 1
          description: Hash table size to use for analysis, in MiB.
        multiPv:
          type: integer
          minimum: 1
          maximum: 5
          description: Requested number of principal variations.
        variant:
          $ref: '#/components/schemas/UciVariant'
        initialFen:
          type: string
          description: Initial position of the game.
        moves:
          type: array
          description: List of moves played from the initial position, in UCI notation.
          items:
            type: string
      required:
      - sessionId
      - threads
      - hash
      - multiPv
      - variant
      - initialFen
      - moves
    ExternalEngineRegistration:
      type: object
      properties:
        name:
          type: string
          description: Display name of the engine.
          example: Stockfish 15
          minLength: 3
          maxLength: 200
        maxThreads:
          type: integer
          description: Maximum number of available threads.
          example: 8
          minimum: 1
          maximum: 65536
        maxHash:
          type: integer
          description: Maximum available hash table size, in MiB.
          example: 2048
          minimum: 1
          maximum: 1048576
        variants:
          type: array
          description: Optional list of supported chess variants.
          items:
            $ref: '#/components/schemas/UciVariant'
        providerSecret:
          type: string
          description: 'A random token that can be used to

            [wait for analysis requests](#tag/external-engine/POST/api/external-engine/work)

            and provide analysis.


            The engine provider should securely generate a random string.


            The token will not be readable again, even by the user.


            The analysis provider can register multiple engines with the same

            token, even for different users, and wait for analysis requests

            from any of them. In this case, the request must not be made via

            CORS, so that the token is not revealed to any of the users.

            '
          example: Dee3uwieZei9ahpaici9bee2yahsai0K
          minLength: 16
          maxLength: 1024
        providerData:
          type: string
          description: 'Arbitrary data that the engine provider can use for identification

            or bookkeeping.


            Users can read this information, but updating it requires knowing

            or changing the `providerSecret`.

            '
      required:
      - name
      - maxThreads
      - maxHash
      - providerSecret
    ExternalEngineWork:
      oneOf:
      - allOf:
        - type: object
          title: Search by movetime
          properties:
            movetime:
              type: integer
              description: Amount of time to analyse the position, in milliseconds.
              minimum: 1
          required:
          - movetime
        - $ref: '#/components/schemas/ExternalEngineWorkCommon'
      - allOf:
        - type: object
          title: Search by depth
          properties:
            depth:
              type: integer
              description: Analysis target depth
              minimum: 1
          required:
          - depth
        - $ref: '#/components/schemas/ExternalEngineWorkCommon'
      - allOf:
        - type: object
          title: Search by nodes
          properties:
            nodes:
              type: integer
              description: Number of nodes to analyse in the position
              minimum: 1
          required:
          - nodes
        - $ref: '#/components/schemas/ExternalEngineWorkCommon'
  securitySchemes:
    OAuth2:
      type: oauth2
      description: 'Read [the introduction for how to make authenticated requests](#description/authentication).

        '
      flows:
        authorizationCode:
          authorizationUrl: https://lichess.org/oauth
          tokenUrl: https://lichess.org/api/token
          scopes:
            preference:read: Read your preferences
            preference:write: Write your preferences
            email:read: Read your email address
            engine:read: Read your external engines
            engine:write: Create, update, delete your external engines
            challenge:read: Read incoming challenges
            challenge:write: Create, accept, decline challenges
            challenge:bulk: Create, delete, query bulk pairings
            study:read: Read private studies and broadcasts
            study:write: Create, update, delete studies and broadcasts
            tournament:write: Create tournaments
            racer:write: Create and join puzzle races
            puzzle:read: Read puzzle activity
            puzzle:write: Write puzzle activity
            team:read: Read private team information
            team:write: Join, leave teams
            team:lead: Manage teams (kick members, send PMs)
            follow:read: Read followed players
            follow:write: Follow and unfollow other players
            msg:write: Send private messages to other players
            board:play: Play with the Board API
            bot:play: Play with the Bot API. Only for [Bot accounts](#tag/bot/POST/api/bot/account/upgrade)
            web:mod: Use moderator tools (within the bounds of your permissions)