openapi: 3.1.0 info: version: 2.0.144 title: Lichess.org API reference Account Studies 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: Studies description: 'Access Lichess studies. ' paths: /api/study/{studyId}/{chapterId}.pgn: get: operationId: studyChapterPgn summary: Export one study chapter description: 'Download one study chapter in PGN format. If authenticated, then all public, unlisted, and private study chapters are read. If not, only public (non-unlisted) study chapters are read. ' tags: - Studies security: - OAuth2: - study:read parameters: - in: path name: studyId description: The study ID required: true schema: type: string minLength: 8 maxLength: 8 - in: path name: chapterId description: The chapter ID required: true schema: type: string minLength: 8 maxLength: 8 - in: query name: clocks description: 'Include clock comments in the PGN moves, when available. Example: `2. exd5 { [%clk 1:01:27] } e5 { [%clk 1:01:28] }` ' schema: type: boolean default: true - in: query name: comments description: 'Include analysis and annotator comments in the PGN moves, when available. Example: `12. Bxf6 { [%eval 0.23] } a3 { White is in a pickle. }` ' schema: type: boolean default: true - in: query name: variations description: 'Include non-mainline moves, when available. Example: `4. d4 Bb4+ (4... Nc6 5. Nf3 Bb4+ 6. Bd2 (6. Nbd2 O-O 7. O-O) 6... Bd6) 5. Nd2` ' schema: type: boolean default: true - in: query name: orientation description: 'Add a `Orientation` PGN tag with the chapter predefined orientation. Example: `[Orientation "white"]` ' schema: type: boolean default: false responses: '200': description: The chapter of the study. content: application/x-chess-pgn: schema: $ref: '#/components/schemas/StudyPgn' /api/study/{studyId}.pgn: get: operationId: studyAllChaptersPgn summary: Export all chapters description: 'Download all chapters of a study in PGN format. If authenticated, then all public, unlisted, and private study chapters are read. If not, only public (non-unlisted) study chapters are read. ' tags: - Studies security: - OAuth2: - study:read parameters: - in: path name: studyId description: The study ID required: true schema: type: string minLength: 8 maxLength: 8 - in: query name: clocks description: 'Include clock comments in the PGN moves, when available. Example: `2. exd5 { [%clk 1:01:27] } e5 { [%clk 1:01:28] }` ' schema: type: boolean default: true - in: query name: comments description: 'Include analysis and annotator comments in the PGN moves, when available. Example: `12. Bxf6 { [%eval 0.23] } a3 { White is in a pickle. }` ' schema: type: boolean default: true - in: query name: variations description: 'Include non-mainline moves, when available. Example: `4. d4 Bb4+ (4... Nc6 5. Nf3 Bb4+ 6. Bd2 (6. Nbd2 O-O 7. O-O) 6... Bd6) 5. Nd2` ' schema: type: boolean default: true - in: query name: orientation description: 'Add a `Orientation` PGN tag with the chapter predefined orientation. Example: `[Orientation "white"]` ' schema: type: boolean default: false responses: '200': description: The PGN representation of the study. headers: Access-Control-Allow-Origin: schema: type: string default: '''*''' Last-Modified: schema: type: string example: Tue, 25 Apr 2023 13:23:09 GMT content: application/x-chess-pgn: schema: $ref: '#/components/schemas/StudyPgn' head: operationId: studyAllChaptersHead summary: Study metadata description: 'Only get the study headers, including `Last-Modified`. ' tags: - Studies security: [] parameters: - in: path name: studyId description: The study ID required: true schema: type: string minLength: 8 maxLength: 8 responses: '204': description: The study headers. headers: Access-Control-Allow-Origin: schema: type: string default: '''*''' Last-Modified: schema: type: string example: Tue, 25 Apr 2023 13:23:09 GMT /api/study: post: operationId: apiStudyPost summary: Create a new Study description: 'Create a [study](https://lichess.org/study), and a new empty chapter within it. You can make up to 30 new studies per day. ' tags: - Studies security: - OAuth2: - study:write requestBody: description: Parameters of the study required: true content: application/x-www-form-urlencoded: schema: type: object properties: name: type: string description: The study name. minLength: 2 maxLength: 100 visibility: type: string enum: - public - unlisted - private default: unlisted description: 'Who can view the study. * `public`: Default. Anyone can view the study, it appears on public listings * `unlisted`: Only people with the link can view the study, it doesn''t appear on public listings * `private`: Only the study members can view the study ' computer: $ref: '#/components/schemas/StudyUserSelection' explorer: $ref: '#/components/schemas/StudyUserSelection' cloneable: $ref: '#/components/schemas/StudyUserSelection' shareable: $ref: '#/components/schemas/StudyUserSelection' chat: $ref: '#/components/schemas/StudyUserSelection' sticky: type: string enum: - 'true' - 'false' default: 'true' description: Keep everyone on the same chapter and position required: - name - visibility - computer - explorer - cloneable - shareable - chat responses: '200': description: The Study has been successfully created. headers: Access-Control-Allow-Origin: schema: type: string default: '''*''' content: application/json: schema: type: object properties: id: type: string examples: default: value: id: 9kze56XR '400': description: The creation of the Study failed. content: application/json: schema: $ref: '#/components/schemas/Error' /api/study/{studyId}/import-pgn: post: operationId: apiStudyImportPGN summary: Import PGN into a study description: 'Imports arbitrary PGN into an existing [study](https://lichess.org/study). Creates a new chapter in the study. If the PGN contains multiple games (separated by 2 or more newlines) then multiple chapters will be created within the study. Note that a study can contain at most 64 chapters. ' tags: - Studies security: - OAuth2: - study:write parameters: - in: path name: studyId description: ID of the study schema: type: string required: true requestBody: description: Parameters of the import required: true content: application/x-www-form-urlencoded: schema: type: object properties: pgn: type: string description: 'PGN to import. Can contain multiple games separated by 2 or more newlines. ' name: type: string description: 'Name of the new chapter. If not specified, or if multiple chapters are created, the names will be inferred from the PGN tags. ' minLength: 1 maxLength: 100 orientation: type: string description: Default board orientation. enum: - white - black default: white variant: $ref: '#/components/schemas/VariantKey' mode: type: string description: 'Analysis mode. If not specified, Normal analysis. * practice - Practise with Computer * conceal - Hide next moves * gamebook - Interactive lesson ' enum: - practice - conceal - gamebook required: - pgn responses: '200': description: The chapters that were created. headers: Access-Control-Allow-Origin: schema: type: string default: '''*''' content: application/json: schema: $ref: '#/components/schemas/StudyImportPgnChapters' '400': description: The creation of the chapter(s) failed. content: application/json: schema: $ref: '#/components/schemas/Error' /api/study/{studyId}/{chapterId}/tags: post: operationId: apiStudyChapterTags summary: Update PGN tags of a study chapter description: 'Add, update and delete the PGN tags of a study. By providing a list of PGN tags in the usual PGN format, you can: - Add new tags if the chapter doesn''t have them yet - Update existing chapter tags - Delete existing chapter tags, by providing a tag with an empty value. The chapter keeps the tags that you don''t provide. ' tags: - Studies security: - OAuth2: - study:write parameters: - in: path name: studyId description: The study ID required: true schema: type: string minLength: 8 maxLength: 8 - in: path name: chapterId description: The chapter ID required: true schema: type: string minLength: 8 maxLength: 8 requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: pgn: type: string description: 'PGN text containing the tags. Only the tags are used. Moves are just ignored. ' required: - pgn responses: '204': description: Tags updated successfully, if the chapter exists and you are authorized the update the study. headers: Access-Control-Allow-Origin: schema: type: string default: '''*''' '400': description: The request body was invalid, such as missing or malformed PGN tag data. content: application/json: schema: $ref: '#/components/schemas/Error' /api/study/{studyId}/{chapterId}/moves: post: operationId: apiStudyChapterMoves summary: Update the moves of a study chapter description: 'Replaces the moves tree of a study chapter. No tags will be modified. ' tags: - Studies security: - OAuth2: - study:write parameters: - in: path name: studyId description: The study ID required: true schema: type: string minLength: 8 maxLength: 8 - in: path name: chapterId description: The chapter ID required: true schema: type: string minLength: 8 maxLength: 8 requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: pgn: type: string description: 'PGN text containing the moves that will replace the chapter''s existing moves. Any provided tags are ignored. ' required: - pgn responses: '204': description: Moves updated, as the chapter exists and you are allowed to edit it. headers: Access-Control-Allow-Origin: schema: type: string default: '''*''' '400': description: Bad request - might be the provided study/chapter doesn't exist, or you aren't allowed to edit it, or the PGN is invalid. content: application/json: schema: $ref: '#/components/schemas/Error' /api/study/by/{username}/export.pgn: get: operationId: studyExportAllPgn summary: Export all studies of a user description: 'Download all chapters of all studies of a user in PGN format. If authenticated, then all public, unlisted, and private studies are included. If not, only public (non-unlisted) studies are included. ' tags: - Studies security: - OAuth2: - study:read parameters: - in: path name: username description: The user whose studies we export required: true schema: type: string - in: query name: clocks description: 'Include clock comments in the PGN moves, when available. Example: `2. exd5 { [%clk 1:01:27] } e5 { [%clk 1:01:28] }` ' schema: type: boolean default: true - in: query name: comments description: 'Include analysis and annotator comments in the PGN moves, when available. Example: `12. Bxf6 { [%eval 0.23] } a3 { White is in a pickle. }` ' schema: type: boolean default: true - in: query name: variations description: 'Include non-mainline moves, when available. Example: `4. d4 Bb4+ (4... Nc6 5. Nf3 Bb4+ 6. Bd2 (6. Nbd2 O-O 7. O-O) 6... Bd6) 5. Nd2` ' schema: type: boolean default: true - in: query name: orientation description: 'Add a `Orientation` PGN tag with the chapter predefined orientation. Example: `[Orientation "white"]` ' schema: type: boolean default: false responses: '200': description: The studies of the user. content: application/x-chess-pgn: schema: $ref: '#/components/schemas/StudyPgn' /api/study/by/{username}: get: operationId: studyListMetadata summary: List studies of a user description: 'Get metadata (name and dates) of all studies of a user. If authenticated, then all public, unlisted, and private studies are included. If not, only public (non-unlisted) studies are included. Studies are streamed as [ndjson](#description/streaming-with-nd-json). ' tags: - Studies security: - OAuth2: - study:read parameters: - in: path name: username description: The user whose studies we list required: true schema: type: string responses: '200': description: The list of studies. headers: Access-Control-Allow-Origin: schema: type: string default: '''*''' content: application/x-ndjson: schema: $ref: '#/components/schemas/StudyMetadata' /api/study/{studyId}/{chapterId}: delete: operationId: apiStudyStudyIdChapterIdDelete summary: Delete a study chapter tags: - Studies security: - OAuth2: - study:write parameters: - in: path name: studyId description: The study ID required: true schema: type: string minLength: 8 maxLength: 8 - in: path name: chapterId description: The chapter ID required: true schema: type: string minLength: 8 maxLength: 8 description: 'Delete a chapter of a study you own. This is definitive. A study must have at least one chapter; so if you delete the last chapter, an empty one will be automatically created to replace it. ' responses: '204': description: Chapter successfully deleted headers: Access-Control-Allow-Origin: schema: type: string default: '''*''' components: schemas: StudyImportPgnChapters: type: object properties: chapters: type: array items: type: object properties: id: type: string description: The chapter ID name: type: string description: The chapter name players: type: array minItems: 2 maxItems: 2 items: type: object properties: name: type: - string - 'null' description: The player name rating: type: integer description: The player rating status: type: string description: The chapter status example: chapters: - id: iBjmYBya name: test 2 players: - name: Carlsen, Magnus rating: 2837 - name: Chadaev, Nikolay rating: 2580 status: 1-0 Error: type: object properties: error: type: string description: The cause of the error. required: - error example: error: This request is invalid because [...] StudyPgn: type: string example: '[Event "All about the Sicilian Defense: Dragon Variation"] [Site "https://lichess.org/study/8c8bmUfy/qwnXMwVC"] [Result "*"] [UTCDate "2017.06.25"] [UTCTime "10:12:04"] [Variant "Standard"] [ECO "B76"] [Opening "Sicilian Defense: Dragon Variation, Yugoslav Attack, Panov Variation"] [Annotator "https://lichess.org/@/Francesco_Super"] { This chapter will go over the Dragon Variation, a very common variation used by Black and it is the most aggressive variation in the Sicilian defense. } 1. e4 c5 2. Nf3 { Simple developing move to control the d4 square } { [%csl Gd4,Gc5][%cal Gf3d4,Gc5d4] } 2... d6 { [%cal Gd6e5] } (2... e6 3. d4 cxd4 4. Nxd4 Nf6 5. e5 (5. Nc3 { [%cal Ge4e5] }) 5... Qa5+) 3. d4 { Whites want the exchange of pawns } { [%cal Gc5d4] } 3... cxd4 { [%cal Gf3d4] } 4. Nxd4 { Whites are now ahead in development but blacks still have the two central pawns whereas whites only one. } { [%csl Ge7,Gd6,Ge4] } 4... Nf6 { Blacks are now developing their knight and threatening the e4 pawn } { [%csl Ge4][%cal Gf6e4] } 5. Nc3 { The e4 pawn is now protected by the c3 knight } { [%csl Ge4,Bc3][%cal Rf6e4,Bc3e4] } 5... g6 { This is the DRAGON VARIATION. g6 allows the dark-squared bishop to develop and move to g7, controlling the long dark-squared diagonal } { [%csl Gd4] } 6. Be3 { [%cal Gd1d2,Gf2f3,Ge1c1,Gg2g4,Gh2h4,Gg4g5] } (6. Be2 Bg7 7. O-O Nc6 8. Be3 { [%cal Ge3d4] } (8. f3 Nxe4 { [%cal Gg7d4,Gc6d4] } 9. Nxc6 Qb6+ { [%cal Gb6c6,Gb6g1] } 10. Kh1 Nxc3 { [%cal Gc3d1,Gc3e2] } 11. bxc3 bxc6 { [%cal Gc8a6] }) 8... O-O 9. Nb3 a6 { [%cal Gb7b5,Gb5b4,Ge2c4] }) 6... Bg7 (6... Ng4 { [%cal Gg4e3] } 7. Bb5+ { [%cal Gb5e8,Gb8d7,Gc8d7,Gd1g4] } 7... Nc6 8. Nxc6 bxc6 9. Bxc6+ { [%cal Gc6a8] }) 7. f3 { The key opening moves for White, who attempt to castle queenside , whereas f3 strengthens the pawn structure, connecting e4 to the h2 and g2, while White also plan pushing to g4 and possibly h4. } { [%csl Bf3,Be3][%cal Rg2g4,Rh2h4,Rg4g5] } 7... O-O (7... h5 { Is operating against g4. }) 8. Qd2 { [%csl Gh6,Gg7][%cal Ge1c1,Ga1d1,Re3h6,Rd2h6] } 8... Nc6 { [%csl Gc6,Gh6][%cal Gb8c6,Ge1c1,Ga7a6,Ge3h6] } 9. g4 (9. Bh6 { [%cal Ge3d4] } 9... Bxh6 10. Qxh6 Nxd4) 9... Be6 10. Nxe6 fxe6 { [%cal Gf8f1] } 11. O-O-O Ne5 12. Be2 { [%csl Gf3][%cal Re5f3,Bd1h1,Bg1d1] } 12... Qc7 { [%csl Gc4][%cal Ge5c4,Gc4e3,Gc4d2,Bf8c8,Yc7c3] } 13. h4 Nc4 * ' StudyMetadata: type: object properties: id: type: string description: The study ID name: type: string description: The study name createdAt: type: integer format: int64 description: The study creation date updatedAt: type: integer format: int64 description: The study last update date required: - id - name - createdAt - updatedAt example: id: WTvnkWAL name: Guess the move createdAt: 1463756350225 updatedAt: 1469965025205 VariantKey: type: string enum: - standard - chess960 - crazyhouse - antichess - atomic - horde - kingOfTheHill - racingKings - threeCheck - fromPosition example: standard default: standard StudyUserSelection: type: string enum: - nobody - owner - contributor - member - everyone 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)