openapi: 3.1.0
info:
version: 2.0.144
title: Lichess.org API reference Account Tournaments (Arena) 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: Tournaments (Arena)
description: 'Access Arena tournaments played on Lichess.
[Official Arena tournaments](https://lichess.org/tournament) are maintained by Lichess,
but you can [create your own Arena tournaments](https://lichess.org/tournament/new) as well.
'
paths:
/api/tournament:
get:
operationId: apiTournament
summary: Get current tournaments
description: 'Get recently active and finished tournaments.
This API is used to display the [Lichess tournament schedule](https://lichess.org/tournament).
'
tags:
- Tournaments (Arena)
security: []
responses:
'200':
description: The list of current tournaments.
headers:
Access-Control-Allow-Origin:
schema:
type: string
default: '''*'''
content:
application/json:
schema:
$ref: '#/components/schemas/ArenaTournaments'
examples:
default:
$ref: '#/components/examples/arenas-getCurrentTournaments.json'
post:
operationId: apiTournamentPost
summary: Create a new Arena tournament
description: "Create a public or private Arena tournament.\nThis endpoint mirrors the form on <https://lichess.org/tournament/new>.\nYou can create up to 12 public tournaments per day, or 24 private tournaments.\nA team battle can be created by specifying the `teamBattleByTeam` argument.\nAdditional restrictions:\n - clockTime + clockIncrement > 0\n - 15s and 0+1 variant tournaments cannot be rated\n - Clock time in comparison to tournament length must be reasonable: 3 <= (minutes * 60) / (96 * clockTime + 48 * clockIncrement + 15) <= 150\n"
tags:
- Tournaments (Arena)
security:
- OAuth2:
- tournament:write
requestBody:
description: Parameters of the tournament
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
name:
type: string
description: The tournament name. Leave empty to get a random Grandmaster name
minLength: 2
maxLength: 30
clockTime:
type: number
description: Clock initial time in minutes
example: 2
enum:
- 0
- 0.25
- 0.5
- 0.75
- 1
- 1.5
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 10
- 15
- 20
- 25
- 30
- 40
- 50
- 60
clockIncrement:
type: integer
description: Clock increment in seconds
example: 1
enum:
- 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 10
- 15
- 20
- 25
- 30
- 40
- 50
- 60
minutes:
type: integer
description: How long the tournament lasts, in minutes
example: 60
enum:
- 20
- 25
- 30
- 35
- 40
- 45
- 50
- 55
- 60
- 70
- 80
- 90
- 100
- 110
- 120
- 150
- 180
- 210
- 240
- 270
- 300
- 330
- 360
- 420
- 480
- 540
- 600
- 720
waitMinutes:
type: integer
description: How long to wait before starting the tournament, from now, in minutes
default: 5
enum:
- 1
- 2
- 3
- 5
- 10
- 15
- 20
- 30
- 45
- 60
startDate:
type: integer
format: int64
description: Timestamp (in milliseconds) to start the tournament at a given date and time. Overrides the `waitMinutes` setting
variant:
$ref: '#/components/schemas/VariantKey'
rated:
type: boolean
description: Games are rated and impact players ratings
default: true
position:
$ref: '#/components/schemas/FromPositionFEN'
berserkable:
type: boolean
description: Whether the players can use berserk. Only allowed if clockIncrement <= clockTime * 2
default: true
streakable:
type: boolean
description: After 2 wins, consecutive wins grant 4 points instead of 2.
default: true
hasChat:
type: boolean
description: Whether the players can discuss in a chat
default: true
description:
type: string
description: Anything you want to tell players about the tournament
password:
type: string
description: 'Make the tournament private, and restrict access with a password.
You can also [generate user-specific entry codes](https://github.com/lichess-org/api/tree/master/example/tournament-entry-code)
based on this password.
'
teamBattleByTeam:
type: string
description: 'Set the ID of a team you lead to create a team battle.
The other teams can be added using the [team battle edit endpoint](#tag/arena-tournaments/POST/api/tournament/team-battle/{id}).
'
conditions.teamMember.teamId:
type: string
description: 'Restrict entry to members of a team.
The teamId is the last part of a team URL, e.g. `https://lichess.org/team/coders` has teamId = `coders`.
Leave empty to let everyone join the tournament.
Do not use this to create team battles, use `teamBattleByTeam` instead.
'
conditions.minRating.rating:
type: integer
description: Minimum rating to join. Leave empty to let everyone join the tournament.
enum:
- 1000
- 1100
- 1200
- 1300
- 1400
- 1500
- 1600
- 1700
- 1800
- 1900
- 2000
- 2100
- 2200
- 2300
- 2400
- 2500
- 2600
conditions.maxRating.rating:
type: integer
description: Maximum rating to join. Based on best rating reached in the last 7 days. Leave empty to let everyone join the tournament.
enum:
- 2200
- 2100
- 2000
- 1900
- 1800
- 1700
- 1600
- 1500
- 1400
- 1300
- 1200
- 1100
- 1000
- 900
- 800
conditions.nbRatedGame.nb:
type: integer
description: Minimum number of rated games required to join.
enum:
- 0
- 5
- 10
- 15
- 20
- 30
- 40
- 50
- 75
- 100
- 150
- 200
conditions.allowList:
type: string
description: 'Predefined list of usernames that are allowed to join, separated by commas.
If this list is non-empty, then usernames absent from this list will be forbidden to join.
Adding `%titled` to the list additionally allows any titled player to join.
Example: `thibault,german11,%titled`
'
conditions.bots:
type: boolean
description: Whether bots are allowed to join the tournament.
default: false
conditions.accountAge:
type: integer
description: Minium account age in days required to join.
enum:
- 1
- 3
- 7
- 14
- 30
- 60
- 90
- 180
- 365
- 730
- 1095
required:
- clockTime
- clockIncrement
- minutes
responses:
'200':
description: The Arena tournament has been successfully created.
headers:
Access-Control-Allow-Origin:
schema:
type: string
default: '''*'''
content:
application/json:
schema:
$ref: '#/components/schemas/ArenaTournamentFull'
examples:
default:
$ref: '#/components/examples/arenas-createArena.json'
'400':
description: The creation of the Arena tournament failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/tournament/{id}:
parameters:
- in: path
name: id
description: The tournament ID.
schema:
type: string
required: true
get:
operationId: tournament
summary: Get info about an Arena tournament
description: 'Get detailed info about recently finished, current, or upcoming tournament''s duels, player standings, and other info.
'
tags:
- Tournaments (Arena)
security: []
parameters:
- in: query
name: page
description: Specify which page of player standings to view.
schema:
type: integer
example: 1
default: 1
minimum: 1
maximum: 200
responses:
'200':
description: The information of the Arena tournament.
headers:
Access-Control-Allow-Origin:
schema:
type: string
default: '''*'''
content:
application/json:
schema:
$ref: '#/components/schemas/ArenaTournamentFull'
examples:
default:
$ref: '#/components/examples/arenas-getArenaById.json'
post:
operationId: apiTournamentUpdate
summary: Update an Arena tournament
description: "Update an Arena tournament.\nBe mindful not to make important changes to ongoing tournaments.\nCan be used to update a team battle.\nAdditional restrictions:\n - clockTime + clockIncrement > 0\n - 15s and 0+1 variant tournaments cannot be rated\n - Clock time in comparison to tournament length must be reasonable: 3 <= (minutes * 60) / (96 * clockTime + 48 * clockIncrement + 15) <= 150\n"
tags:
- Tournaments (Arena)
security:
- OAuth2:
- tournament:write
requestBody:
description: Parameters of the tournament
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
name:
type: string
description: The tournament name. Leave empty to get a random Grandmaster name
minLength: 2
maxLength: 30
clockTime:
type: number
description: Clock initial time in minutes
example: 2
enum:
- 0
- 0.25
- 0.5
- 0.75
- 1
- 1.5
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 10
- 15
- 20
- 25
- 30
- 40
- 50
- 60
clockIncrement:
type: integer
description: Clock increment in seconds
example: 1
enum:
- 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 10
- 15
- 20
- 25
- 30
- 40
- 50
- 60
minutes:
type: integer
description: How long the tournament lasts, in minutes
example: 60
enum:
- 20
- 25
- 30
- 35
- 40
- 45
- 50
- 55
- 60
- 70
- 80
- 90
- 100
- 110
- 120
- 150
- 180
- 210
- 240
- 270
- 300
- 330
- 360
- 420
- 480
- 540
- 600
- 720
waitMinutes:
type: integer
description: How long to wait before starting the tournament, from now, in minutes
default: 5
enum:
- 1
- 2
- 3
- 5
- 10
- 15
- 20
- 30
- 45
- 60
startDate:
type: integer
format: int64
description: Timestamp (in milliseconds) to start the tournament at a given date and time. Overrides the `waitMinutes` setting
variant:
$ref: '#/components/schemas/VariantKey'
rated:
type: boolean
description: Games are rated and impact players ratings
default: true
position:
$ref: '#/components/schemas/FromPositionFEN'
berserkable:
type: boolean
description: Whether the players can use berserk. Only allowed if clockIncrement <= clockTime * 2
default: true
streakable:
type: boolean
description: After 2 wins, consecutive wins grant 4 points instead of 2.
default: true
hasChat:
type: boolean
description: Whether the players can discuss in a chat
default: true
description:
type: string
description: Anything you want to tell players about the tournament
password:
type: string
description: Make the tournament private, and restrict access with a password
conditions.minRating.rating:
type: integer
description: Minimum rating to join. Leave empty to let everyone join the tournament.
enum:
- 1000
- 1100
- 1200
- 1300
- 1400
- 1500
- 1600
- 1700
- 1800
- 1900
- 2000
- 2100
- 2200
- 2300
- 2400
- 2500
- 2600
conditions.maxRating.rating:
type: integer
description: Maximum rating to join. Based on best rating reached in the last 7 days. Leave empty to let everyone join the tournament.
enum:
- 2200
- 2100
- 2000
- 1900
- 1800
- 1700
- 1600
- 1500
- 1400
- 1300
- 1200
- 1100
- 1000
- 900
- 800
conditions.nbRatedGame.nb:
type: integer
description: Minimum number of rated games required to join.
enum:
- 0
- 5
- 10
- 15
- 20
- 30
- 40
- 50
- 75
- 100
- 150
- 200
conditions.allowList:
type: string
description: 'Predefined list of usernames that are allowed to join, separated by commas.
If this list is non-empty, then usernames absent from this list will be forbidden to join.
Adding `%titled` to the list additionally allows any titled player to join.
Example: `thibault,german11,%titled`
'
conditions.bots:
type: boolean
description: Whether bots are allowed to join the tournament.
default: false
conditions.accountAge:
type: integer
description: Minium account age in days required to join.
enum:
- 1
- 3
- 7
- 14
- 30
- 60
- 90
- 180
- 365
- 730
- 1095
required:
- clockTime
- clockIncrement
- minutes
responses:
'200':
description: The Arena tournament was successfully updated.
headers:
Access-Control-Allow-Origin:
schema:
type: string
default: '''*'''
content:
application/json:
schema:
$ref: '#/components/schemas/ArenaTournamentFull'
examples:
default:
$ref: '#/components/examples/arenas-updateArena.json'
'400':
description: The update of the Arena tournament failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/tournament/{id}/join:
post:
operationId: apiTournamentJoin
summary: Join an Arena tournament
description: 'Join an Arena tournament, possibly with a password and/or a team.
Also unpauses if you had previously [paused](#tag/arena-tournaments/POST/api/tournament/{id}/withdraw) the tournament.
'
tags:
- Tournaments (Arena)
security:
- OAuth2:
- tournament:write
parameters:
- in: path
name: id
description: The tournament ID.
schema:
type: string
example: hL7vMrFQ
required: true
requestBody:
description: You may need these depending on the tournament to join
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
password:
type: string
description: 'The tournament password, if one is required.
Can also be a [user-specific entry code](https://github.com/lichess-org/api/tree/master/example/tournament-entry-code)
generated and shared by the organizer.
'
team:
type: string
description: The team to join the tournament with, for team battle tournaments
pairMeAsap:
type: boolean
default: false
description: 'If the tournament is started, attempt to pair the user,
even if they are not connected to the tournament page.
This expires after one minute, to avoid pairing a user who is long gone.
You may call "join" again to extend the waiting.
'
responses:
'200':
description: The tournament was successfully joined.
headers:
Access-Control-Allow-Origin:
schema:
type: string
default: '''*'''
content:
application/json:
schema:
$ref: '#/components/schemas/Ok'
'400':
description: Joining the tournament failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/tournament/{id}/withdraw:
post:
operationId: apiTournamentWithdraw
summary: Pause or leave an Arena tournament
description: 'Leave a future Arena tournament, or take a break on an ongoing Arena tournament.
It''s possible to join again later. Points and streaks are preserved.
'
tags:
- Tournaments (Arena)
security:
- OAuth2:
- tournament:write
parameters:
- in: path
name: id
description: The tournament ID.
schema:
type: string
example: hL7vMrFQ
required: true
responses:
'200':
description: The tournament was successfully paused or left.
headers:
Access-Control-Allow-Origin:
schema:
type: string
default: '''*'''
content:
application/json:
schema:
$ref: '#/components/schemas/Ok'
'400':
description: Pausing/leaving the tournament failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/tournament/{id}/terminate:
post:
operationId: apiTournamentTerminate
summary: Terminate an Arena tournament
description: 'Terminate an Arena tournament
'
tags:
- Tournaments (Arena)
security:
- OAuth2:
- tournament:write
parameters:
- in: path
name: id
description: The tournament ID.
schema:
type: string
example: hL7vMrFQ
required: true
responses:
'200':
description: The tournament was successfully terminated.
headers:
Access-Control-Allow-Origin:
schema:
type: string
default: '''*'''
content:
application/json:
schema:
$ref: '#/components/schemas/Ok'
'400':
description: Terminating the tournament failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/tournament/team-battle/{id}:
post:
operationId: apiTournamentTeamBattlePost
summary: Update a team battle
description: 'Set the teams and number of leaders of a team battle.
To update the other attributes of a team battle, use the [tournament update endpoint](#tag/arena-tournaments/POST/api/tournament/{id}).
'
tags:
- Tournaments (Arena)
security:
- OAuth2:
- tournament:write
parameters:
- in: path
name: id
description: The tournament ID
required: true
schema:
type: string
minLength: 8
maxLength: 8
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
teams:
type: string
description: 'All team IDs of the team battle, separated by commas.
Make sure to always send the full list.
Teams that are not in the list will be removed from the team battle.
Example: `coders,zhigalko_sergei-fan-club,hhSwTKZv`
'
nbLeaders:
type: integer
description: Number team leaders per team.
required:
-
# --- truncated at 32 KB (338 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/lichess/refs/heads/main/openapi/lichess-tournaments-arena-api-openapi.yml