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)