Lichess Bulk pairings API

Create many games for other players. These endpoints are intended for tournament organisers.

Operations 6

GET /api/bulk-pairing View your bulk pairings #
POST /api/bulk-pairing Create a bulk pairing #
POST /api/bulk-pairing/{id}/start-clocks Manually start clocks #
GET /api/bulk-pairing/{id} Show a bulk pairing #
DELETE /api/bulk-pairing/{id} Cancel a bulk pairing #
GET /api/bulk-pairing/{id}/games Export games of a bulk pairing #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/lichess-bulk-pairings-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

lichess-bulk-pairings-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  version: 2.0.144
  title: Lichess.org API reference Bulk pairings 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!'
servers:
- url: https://lichess.org
- url: https://lichess.dev
- url: http://localhost:{port}
  variables:
    port:
      default: '8080'
- url: http://l.org
tags:
- name: Bulk pairings
  description: 'Create many games for other players.


    These endpoints are intended for tournament organisers.'
paths:
  /api/bulk-pairing:
    get:
      operationId: bulkPairingList
      summary: View your bulk pairings
      description: Get a list of bulk pairings you created.
      tags:
      - Bulk pairings
      security:
      - OAuth2:
        - challenge:bulk
      responses:
        '200':
          description: The list of bulk pairing the logged in user created.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/BulkPairing'
    post:
      operationId: bulkPairingCreate
      summary: Create a bulk pairing
      description: 'Schedule many games at once, up to 24h in advance.

        OAuth tokens are required for all paired players, with the `challenge:write` scope.

        You can schedule up to 500 games every 10 minutes. Contact us if you need higher limits.

        If games have a real-time clock, each player must have only one pairing.

        For correspondence games, players can have multiple pairings within the same bulk.


        **The entire bulk is rejected if:**

        - a token is missing

        - a token is present more than once (except in correspondence)

        - a token lacks the `challenge:write` scope

        - a player account is closed

        - a player is paired more than once (except in correspondence)

        - a bulk is already scheduled to start at the same time with the same player

        - you have 20 scheduled bulks

        - you have 1000 scheduled games


        Partial bulks are never created. Either it all fails, or it all succeeds.

        When it fails, it does so with an error message explaining the issue.

        Failed bulks are not counted in the rate limiting, they are free.

        Fix the issues, manually or programmatically, then retry to schedule the bulk.

        A successful bulk creation returns a JSON bulk document. Its ID can be used for further operations.'
      tags:
      - Bulk pairings
      security:
      - OAuth2:
        - challenge:bulk
      requestBody:
        description: Parameters of the pairings
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                players:
                  type: string
                  description: 'OAuth tokens of all the players to pair, with the syntax `tokenOfWhitePlayerInGame1:tokenOfBlackPlayerInGame1,tokenOfWhitePlayerInGame2:tokenOfBlackPlayerInGame2,...`.

                    The 2 tokens of the players of a game are separated with `:`. The first token gets the white pieces. Games are separated with `,`.

                    Up to 1000 tokens can be sent, for a max of 500 games.

                    Each token must be included at most once.

                    Example: `token1:token2,token3:token4,token5:token6`

                    '
                clock.limit:
                  type: integer
                  description: 'Clock initial time in seconds. Example: `600`

                    '
                  minimum: 0
                  maximum: 10800
                clock.increment:
                  type: integer
                  description: 'Clock increment in seconds. Example: `2`

                    '
                  minimum: 0
                  maximum: 60
                days:
                  type: integer
                  description: Days per turn. For correspondence games only.
                  enum:
                  - 1
                  - 2
                  - 3
                  - 5
                  - 7
                  - 10
                  - 14
                pairAt:
                  type: integer
                  format: int64
                  description: 'Date at which the games will be created as a Unix timestamp in milliseconds.

                    Up to 7 days in the future.

                    Omit, or set to current date and time, to start the games immediately.

                    Example: `1612289869919`

                    '
                startClocksAt:
                  type: integer
                  format: int64
                  description: 'Date at which the clocks will be automatically started as a Unix timestamp in milliseconds.

                    Up to 7 days in the future.

                    Note that the clocks can start earlier than specified, if players start making moves in the game.

                    If omitted, the clocks will not start automatically.

                    Example: `1612289869919`

                    '
                rated:
                  type: boolean
                  description: Game is rated and impacts players ratings
                  default: false
                variant:
                  $ref: '#/components/schemas/VariantKey'
                fen:
                  $ref: '#/components/schemas/FromPositionFEN'
                message:
                  type: string
                  description: 'Message that will be sent to each player, when the game is created.  It is sent from your user account.

                    `{opponent}` and `{game}` are placeholders that will be replaced with the opponent and the game URLs.

                    You can omit this field to send the default message,

                    but if you set your own message, it must at least contain the `{game}` placeholder.

                    '
                  default: 'Your game with {opponent} is ready: {game}.'
                rules:
                  type: string
                  enum:
                  - noAbort
                  - noRematch
                  - noGiveTime
                  - noClaimWin
                  - noEarlyDraw
                  description: 'Extra game rules separated by commas.

                    Example: `noAbort,noRematch`

                    '
      responses:
        '200':
          description: The bulk pairing has been successfully created.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkPairing'
        '400':
          description: The creation of the bulk pairings failed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/bulk-pairing/{id}/start-clocks:
    post:
      operationId: bulkPairingStartClocks
      summary: Manually start clocks
      description: 'Immediately start all clocks of the games of a bulk pairing.

        This overrides the `startClocksAt` value of an existing bulk pairing.

        If the games have not yet been created (`bulk.pairAt` is in the future), then this does nothing.

        If the clocks have already started (`bulk.startClocksAt` is in the past), then this does nothing.'
      tags:
      - Bulk pairings
      security:
      - OAuth2:
        - challenge:bulk
      parameters:
      - in: path
        name: id
        schema:
          type: string
          description: The ID of the bulk pairing
          example: 5IrD6Gzz
        required: true
      responses:
        '200':
          description: The clocks of the games of a bulk pairing were successfully started.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Ok'
        '404':
          description: The bulk pairing was not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFound'
  /api/bulk-pairing/{id}:
    get:
      operationId: bulkPairingGet
      summary: Show a bulk pairing
      description: Get a single bulk pairing by its ID.
      tags:
      - Bulk pairings
      security:
      - OAuth2:
        - challenge:bulk
      parameters:
      - in: path
        name: id
        schema:
          type: string
          description: The ID of the bulk pairing
          example: 5IrD6Gzz
        required: true
      responses:
        '200':
          description: The bulk pairing.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkPairing'
        '404':
          description: The bulk pairing was not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFound'
    delete:
      operationId: bulkPairingDelete
      summary: Cancel a bulk pairing
      description: 'Cancel and delete a bulk pairing that is scheduled in the future.

        If the games have already been created, then this does nothing.

        Canceling a bulk pairing does not refund the rate limit cost of that bulk pairing.'
      tags:
      - Bulk pairings
      security:
      - OAuth2:
        - challenge:bulk
      parameters:
      - in: path
        name: id
        schema:
          type: string
          description: The ID of the bulk pairing
          example: 5IrD6Gzz
        required: true
      responses:
        '200':
          description: The bulk pairing was successfully deleted.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Ok'
        '404':
          description: The bulk pairing to delete was not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFound'
  /api/bulk-pairing/{id}/games:
    get:
      operationId: bulkPairingIdGamesGet
      summary: Export games of a bulk pairing
      description: Download games of a bulk in PGN or ndjson format, depending on the request `Accept` header.
      tags:
      - Bulk pairings
      security:
      - OAuth2:
        - challenge:bulk
      parameters:
      - $ref: '#/components/parameters/AcceptPgnOrNdjson'
      - in: path
        name: id
        schema:
          type: string
          description: The ID of the bulk pairing
          example: 5IrD6Gzz
        required: true
      - in: query
        name: moves
        description: Include the PGN moves.
        schema:
          type: boolean
          default: true
      - in: query
        name: pgnInJson
        description: Include the full PGN within the JSON response, in a `pgn` field.
        schema:
          type: boolean
          default: false
      - in: query
        name: tags
        description: Include the PGN tags.
        schema:
          type: boolean
          default: true
      - in: query
        name: clocks
        description: 'Include clock status when available.

          Either as PGN comments: `2. exd5 { [%clk 1:01:27] } e5 { [%clk 1:01:28] }`

          Or in a `clocks` JSON field, as centisecond integers, depending on the response type.

          '
        schema:
          type: boolean
          default: false
      - in: query
        name: evals
        description: 'Include analysis evaluations and comments, when available.

          Either as PGN comments: `12. Bxf6 { [%eval 0.23] } a3 { [%eval -1.09] }`

          Or in an `analysis` JSON field, depending on the response type.

          '
        schema:
          type: boolean
          default: false
      - in: query
        name: accuracy
        description: 'Include [accuracy percent](https://lichess.org/page/accuracy) of each player, when available. Only available in JSON.

          '
        schema:
          type: boolean
          default: false
      - in: query
        name: opening
        description: 'Include the opening name.

          Example: `[Opening "King''s Gambit Accepted, King''s Knight Gambit"]`

          '
        schema:
          type: boolean
          default: false
      - in: query
        name: division
        description: 'Plies which mark the beginning of the middlegame and endgame.

          Only available in JSON

          '
        schema:
          type: boolean
          default: false
      - in: query
        name: literate
        description: 'Insert textual annotations in the PGN about the opening, analysis variations, mistakes, and game termination.

          Example: `5... g4? { (-0.98 → 0.60) Mistake. Best move was h6. } (5... h6 6. d4 Ne7 7. g3 d5 8. exd5 fxg3 9. hxg3 c6 10. dxc6)`

          '
        schema:
          type: boolean
          default: false
      responses:
        '200':
          description: The representation of the games.
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                default: '''*'''
          content:
            application/x-chess-pgn:
              schema:
                $ref: '#/components/schemas/GamePgn'
            application/x-ndjson:
              schema:
                $ref: '#/components/schemas/GameJson'
components:
  schemas:
    GameOpening:
      type: object
      properties:
        eco:
          type: string
        name:
          type: string
        ply:
          type: integer
      required:
      - eco
      - name
      - ply
    GameColor:
      type: string
      enum:
      - white
      - black
    Speed:
      type: string
      enum:
      - ultraBullet
      - bullet
      - blitz
      - rapid
      - classical
      - correspondence
    GamePlayers:
      type: object
      properties:
        white:
          $ref: '#/components/schemas/GamePlayerUser'
        black:
          $ref: '#/components/schemas/GamePlayerUser'
      required:
      - white
      - black
    Error:
      type: object
      properties:
        error:
          type: string
          description: The cause of the error.
      required:
      - error
      example:
        error: This request is invalid because [...]
    GameStatusName:
      type: string
      enum:
      - created
      - started
      - aborted
      - mate
      - resign
      - stalemate
      - timeout
      - draw
      - outoftime
      - cheat
      - noStart
      - unknownFinish
      - insufficientMaterialClaim
      - variantEnd
    BulkPairing:
      type: object
      properties:
        id:
          type: string
        games:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              black:
                type: string
              white:
                type: string
        variant:
          $ref: '#/components/schemas/VariantKey'
        clock:
          $ref: '#/components/schemas/Clock'
        pairAt:
          type: integer
        pairedAt:
          type:
          - integer
          - 'null'
        rated:
          type: boolean
        startClocksAt:
          type: integer
        scheduledAt:
          type: integer
      required:
      - id
      - games
      - variant
      - clock
      - pairAt
      - pairedAt
      - rated
      - startClocksAt
      - scheduledAt
      example:
        id: RVAcwgg7
        games:
        - id: NKop9IyD
          black: lizen1
          white: thibault
        - id: KT8374ut
          black: lizen3
          white: lizen2
        - id: wInQr8Sk
          black: lizen5
          white: lizen4
        variant: standard
        clock:
          increment: 0
          limit: 300
        pairAt: 1612289869919
        pairedAt: null
        rated: false
        startClocksAt: 1612200422971
        scheduledAt: 1612203514628
    VariantKey:
      type: string
      enum:
      - standard
      - chess960
      - crazyhouse
      - antichess
      - atomic
      - horde
      - kingOfTheHill
      - racingKings
      - threeCheck
      - fromPosition
      example: standard
      default: standard
    Clock:
      type: object
      properties:
        limit:
          type: integer
        increment:
          type: integer
      required:
      - limit
      - increment
    PatronColor:
      type: integer
      description: 'Players can choose a color for their Patron wings.

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


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

        '
      minimum: 1
      maximum: 10
    GamePgn:
      type: string
      example: '[Event "Rated Blitz game"]

        [Site "https://lichess.org/fY44h4OY"]

        [Date "2018.03.29"]

        [Round "-"]

        [White "pveldman"]

        [Black "thibault"]

        [Result "1-0"]

        [UTCDate "2018.03.29"]

        [UTCTime "01:38:15"]

        [WhiteElo "1610"]

        [BlackElo "1601"]

        [WhiteRatingDiff "+10"]

        [BlackRatingDiff "-10"]

        [Variant "Standard"]

        [TimeControl "180+0"]

        [ECO "C62"]

        [Opening "Ruy Lopez: Steinitz Defense"]

        [Termination "Normal"]


        1. e4 { [%clk 0:03:00] } e5 { [%clk 0:03:00] } 2. Nf3 { [%clk 0:02:59] } Nc6 { [%clk 0:02:58] } 3. Bb5 { [%clk 0:02:57] } d6 { [%clk 0:02:55] } 4. h3 { [%clk 0:02:54] } Nf6 { [%clk 0:02:52] } 5. Bxc6+ { [%clk 0:02:52] } bxc6 { [%clk 0:02:49] } 6. d3 { [%clk 0:02:51] } Be7 { [%clk 0:02:46] } 7. O-O { [%clk 0:02:47] } O-O { [%clk 0:02:45] } 8. b3 { [%clk 0:02:45] } d5 { [%clk 0:02:45] } 9. exd5 { [%clk 0:02:33] } cxd5 { [%clk 0:02:40] } 10. Nxe5 { [%clk 0:02:31] } Qd6 { [%clk 0:02:38] } 1-0

        '
    Title:
      type: string
      enum:
      - GM
      - WGM
      - IM
      - WIM
      - FM
      - WFM
      - NM
      - CM
      - WCM
      - WNM
      - LM
      - BOT
      description: only appears if the user is a titled player or a bot user
    Flair:
      type: string
      description: See [available flair list and images](https://github.com/lichess-org/lila/tree/master/public/flair)
    GameMoveAnalysis:
      type: object
      properties:
        eval:
          type: integer
          description: Evaluation in centipawns
        mate:
          type: integer
          description: Number of moves until forced mate
        best:
          type: string
          example: c2c3
          description: Best move in UCI notation (only if played move was inaccurate)
        variation:
          type: string
          example: c3 Nc6 d4 Qb6 Be2 Nge7 Na3 cxd4 cxd4 Nf5
          description: Best variation in SAN notation (only if played move was inaccurate)
        judgment:
          type: object
          description: Judgment annotation (only if played move was inaccurate)
          properties:
            name:
              type: string
              enum:
              - Inaccuracy
              - Mistake
              - Blunder
            comment:
              type: string
              example: Blunder. Nxg6 was best.
    FromPositionFEN:
      type: string
      description: Custom initial position (in X-FEN). Variant must be standard, fromPosition, or chess960 (if a valid 960 starting position), and the game cannot be rated.
      default: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
    LightUser:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        flair:
          $ref: '#/components/schemas/Flair'
        title:
          $ref: '#/components/schemas/Title'
        patron:
          $ref: '#/components/schemas/Patron'
        patronColor:
          $ref: '#/components/schemas/PatronColor'
      required:
      - id
      - name
    NotFound:
      properties:
        error:
          type: string
      required:
      - error
      example:
        error: Not found.
    GamePlayerUser:
      type: object
      properties:
        user:
          $ref: '#/components/schemas/LightUser'
        rating:
          type: integer
        ratingDiff:
          type: integer
        name:
          type: string
        provisional:
          type: boolean
        aiLevel:
          type: integer
        analysis:
          type: object
          properties:
            inaccuracy:
              type: integer
            mistake:
              type: integer
            blunder:
              type: integer
            acpl:
              type: integer
            accuracy:
              type: integer
          required:
          - inaccuracy
          - mistake
          - blunder
          - acpl
        team:
          type: string
      required:
      - user
      - rating
    Patron:
      type: boolean
      deprecated: true
      description: 'Use patronColor value instead to determine if player is a patron.

        '
    GameJson:
      type: object
      properties:
        id:
          type: string
        rated:
          type: boolean
        variant:
          $ref: '#/components/schemas/VariantKey'
        speed:
          $ref: '#/components/schemas/Speed'
        perf:
          type: string
        createdAt:
          type: integer
          format: int64
        lastMoveAt:
          type: integer
          format: int64
        status:
          $ref: '#/components/schemas/GameStatusName'
        source:
          type: string
        players:
          $ref: '#/components/schemas/GamePlayers'
        initialFen:
          type: string
        winner:
          $ref: '#/components/schemas/GameColor'
        opening:
          $ref: '#/components/schemas/GameOpening'
        moves:
          type: string
        pgn:
          type: string
        daysPerTurn:
          type: integer
        analysis:
          type: array
          items:
            $ref: '#/components/schemas/GameMoveAnalysis'
        tournament:
          type: string
        swiss:
          type: string
        clock:
          type: object
          properties:
            initial:
              type: integer
            increment:
              type: integer
            totalTime:
              type: integer
          required:
          - initial
          - increment
          - totalTime
        clocks:
          type: array
          items:
            type: integer
        division:
          type: object
          properties:
            middle:
              type: integer
              description: Ply at which the middlegame begins
            end:
              type: integer
              description: Ply at which the endgame begins
          required: []
      required:
      - id
      - rated
      - variant
      - speed
      - perf
      - createdAt
      - lastMoveAt
      - status
      - players
    Ok:
      properties:
        ok:
          type: boolean
      required:
      - ok
  parameters:
    AcceptPgnOrNdjson:
      in: header
      name: Accept
      description: 'Specify the desired response format.

        Use `application/x-chess-pgn` to get the games in PGN format.

        Use `application/x-ndjson` to get the games in ndjson format. [Read about ndjson here](#description/streaming-with-nd-json) and how you can parse it in Javascript.

        '
      schema:
        type: string
        enum:
        - application/x-chess-pgn
        - application/x-ndjson
        default: application/x-chess-pgn
  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)