> ## Documentation Index
> Fetch the complete documentation index at: https://docs-staging.blumint.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Registers your create-lobby callback URL.

> Registers the https URL BluMint calls when a BluMint match is ready to
play. Your endpoint creates a lobby, lets only the players listed in
teams play, and answers with how they join, as you chose in the setup
form: a link players open, a lobby code players type, or, if your own
client puts the players in, a link the host can open to watch. In the
setup form you also give the range of teams per match and of players
per team your game server runs. A host can't set up a tournament of
your game outside those ranges, so every create you receive fits
them, and the range of teams is exactly two on a best-of series.
Ignore any field you do not recognize in a body BluMint sends you:
BluMint can add a field at any time, so a server that refuses an
unknown field stops working when one is added. Use and keep the player and
spectator ids BluMint sends only to put players into matches in your
game's BluMint tournaments and to let the spectators who chose to
watch do so. Share them with no one else, and keep them secure.
Registering again replaces the previous URL. The URL's host must
resolve only to public addresses, an IP-address host must be a public
IPv4 address, and BluMint follows no redirects, so the URL must
answer directly.

Which answer to send when BluMint calls your URL:

| Situation | Status | Code | Data field | What happens next |
| --- | --- | --- | --- | --- |
| Created, or a repeat of a key already created | `200` |  |  | The players get the match and it starts. |
| You can't match the id of a player the create identifies | `400` | `player_unlinked` | `players` | For a seat BluMint filled from an account the player linked on BluMint, such as a Lichess username, BluMint tells the player you didn't recognize that account and retries under the same key every 60 seconds, so a retry can name an account you already refused. A player still unmatched when the tournament's hold length runs out is disqualified. For a seat BluMint filled from your lookup, BluMint looks the named players up again and retries once under the same key. If you answer that retry with player_unlinked again, the host takes the match, and any other answer to it does what its own row says. If your lookup no longer finds a player, BluMint asks the player to connect their account and retries under the same key every 60 seconds. A player still unlinked when the tournament's hold length runs out is disqualified. While the match is held, a player_unlinked on a looked-up seat keeps it held until the next retry. |
| A player the create identifies is still in another of your lobbies | `423` | `player_busy` | `players` | BluMint tells the named players to finish their other match and retries under the same key every 60 seconds. A player still busy when the tournament's hold length runs out is disqualified. |
| You are down or overloaded | `502`, `503`, `504`, `408`, `429`, or no answer |  |  | The match keeps reading as being set up, and BluMint tells every player the create identifies once that you aren't responding. BluMint retries under the same key every 60 seconds, or once the wait your Retry-After names has passed when that is later, waiting at most 5 minutes. If you are still down when the tournament's hold length runs out, the host takes the match and nobody is disqualified. |
| You cannot run this match | `400` | `match_unsupported` |  | The host takes the match and starts it manually. |
| BluMint's request breaks the rules in this guide | `400` | `invalid_request` |  | The host takes the match and starts it manually. |
| The key arrived with a different body, or a close already named it | `409` | `idempotency_key_reused` |  | The host takes the match and starts it manually. |
| Your server failed on this request | `500` |  |  | The host takes the match and starts it manually. |

For what BluMint sends to your URL and how to answer it, see [Create a lobby](/guide/create-a-lobby).



## OpenAPI

````yaml /openapi.json post /tournaments/match/setCreate
openapi: 3.0.1
info:
  title: BluMint game partner API
  version: 2.0.0
  description: >-
    Reference for the endpoints your game uses to run BluMint tournaments. For
    the walkthrough, see the [game integration guide](https://docs.blumint.com).
    To request an API key, fill in the [game partner setup
    form](https://staging.blumint.io/contact/game-partner), and for a question,
    [contact BluMint](https://staging.blumint.io/contact).
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
servers:
  - description: Staging, for building and testing
    url: https://staging.blumint.io/api
  - description: Production
    url: https://app.blumint.com/api
security:
  - ApiKeyAuth: []
tags: []
paths:
  /tournaments/match/setCreate:
    post:
      tags:
        - Tournaments
      summary: Registers your create-lobby callback URL.
      description: >-
        Registers the https URL BluMint calls when a BluMint match is ready to

        play. Your endpoint creates a lobby, lets only the players listed in

        teams play, and answers with how they join, as you chose in the setup

        form: a link players open, a lobby code players type, or, if your own

        client puts the players in, a link the host can open to watch. In the

        setup form you also give the range of teams per match and of players

        per team your game server runs. A host can't set up a tournament of

        your game outside those ranges, so every create you receive fits

        them, and the range of teams is exactly two on a best-of series.

        Ignore any field you do not recognize in a body BluMint sends you:

        BluMint can add a field at any time, so a server that refuses an

        unknown field stops working when one is added. Use and keep the player
        and

        spectator ids BluMint sends only to put players into matches in your

        game's BluMint tournaments and to let the spectators who chose to

        watch do so. Share them with no one else, and keep them secure.

        Registering again replaces the previous URL. The URL's host must

        resolve only to public addresses, an IP-address host must be a public

        IPv4 address, and BluMint follows no redirects, so the URL must

        answer directly.


        Which answer to send when BluMint calls your URL:


        | Situation | Status | Code | Data field | What happens next |

        | --- | --- | --- | --- | --- |

        | Created, or a repeat of a key already created | `200` |  |  | The
        players get the match and it starts. |

        | You can't match the id of a player the create identifies | `400` |
        `player_unlinked` | `players` | For a seat BluMint filled from an
        account the player linked on BluMint, such as a Lichess username,
        BluMint tells the player you didn't recognize that account and retries
        under the same key every 60 seconds, so a retry can name an account you
        already refused. A player still unmatched when the tournament's hold
        length runs out is disqualified. For a seat BluMint filled from your
        lookup, BluMint looks the named players up again and retries once under
        the same key. If you answer that retry with player_unlinked again, the
        host takes the match, and any other answer to it does what its own row
        says. If your lookup no longer finds a player, BluMint asks the player
        to connect their account and retries under the same key every 60
        seconds. A player still unlinked when the tournament's hold length runs
        out is disqualified. While the match is held, a player_unlinked on a
        looked-up seat keeps it held until the next retry. |

        | A player the create identifies is still in another of your lobbies |
        `423` | `player_busy` | `players` | BluMint tells the named players to
        finish their other match and retries under the same key every 60
        seconds. A player still busy when the tournament's hold length runs out
        is disqualified. |

        | You are down or overloaded | `502`, `503`, `504`, `408`, `429`, or no
        answer |  |  | The match keeps reading as being set up, and BluMint
        tells every player the create identifies once that you aren't
        responding. BluMint retries under the same key every 60 seconds, or once
        the wait your Retry-After names has passed when that is later, waiting
        at most 5 minutes. If you are still down when the tournament's hold
        length runs out, the host takes the match and nobody is disqualified. |

        | You cannot run this match | `400` | `match_unsupported` |  | The host
        takes the match and starts it manually. |

        | BluMint's request breaks the rules in this guide | `400` |
        `invalid_request` |  | The host takes the match and starts it manually.
        |

        | The key arrived with a different body, or a close already named it |
        `409` | `idempotency_key_reused` |  | The host takes the match and
        starts it manually. |

        | Your server failed on this request | `500` |  |  | The host takes the
        match and starts it manually. |


        For what BluMint sends to your URL and how to answer it, see [Create a
        lobby](/guide/create-a-lobby).
      operationId: setCreateMatch
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - createMatchUrl
              properties:
                createMatchUrl:
                  type: string
                  format: uri
                  description: The https URL of your create-lobby endpoint.
                  example: https://www.yourgame.com/api/match/create
                authentication:
                  description: >-
                    The secret BluMint sends when it calls your create-lobby
                    endpoint. When omitted, any secret registered earlier stays
                    in place.
                  allOf:
                    - $ref: '#/components/schemas/CallbackAuthentication'
      responses:
        '200':
          description: The create-lobby callback URL is registered.
          content:
            application/json:
              schema:
                type: object
                required:
                  - message
                properties:
                  message:
                    type: string
                    example: Success - Match creation callback URL set successfully.
        '400':
          $ref: '#/components/responses/CallbackRegistrationRefused'
        '401':
          $ref: '#/components/responses/CallbackRegistrationUnauthenticated'
        '404':
          $ref: '#/components/responses/CallbackRegistrationGameNotFound'
        '405':
          $ref: '#/components/responses/CallbackRegistrationMethodNotAllowed'
      callbacks:
        matchCreation:
          '{$request.body#/createMatchUrl}':
            post:
              description: |-
                You choose in the setup form how your server runs a match.

                - Best-of series (the better user experience): your server
                  runs the whole best-of series in one lobby. BluMint sends
                  one create per BluMint match, carrying series.gamesToWin,
                  and players join that one lobby for the whole match.
                - Single game sessions: your server runs one game session at
                  a time. BluMint sends one create per game session, with no
                  series, and players join a new lobby before each game
                  session.

                On a best-of series, BluMint sometimes needs a new lobby for a
                match already under way, for example after you abort with
                retryable: true. That create gives each team startingWins: the
                game sessions the team has already won in the match as
                BluMint records it, which can be 0 after the host resets the
                score. The first create for a BluMint match carries no
                startingWins, so count from 0. Count startingWins into every
                progress, result and abort report for the new lobby. A report
                with fewer wins than startingWins answers 400 invalid_wins. If
                your server cannot resume a best-of series from a starting
                score, choose single game sessions in the setup form.

                BluMint can send one create more than once: an answer can be
                lost on the network or arrive after BluMint's deadline, and
                BluMint retries a create through an outage or a hold. When an
                answer is lost, BluMint can't tell whether you made the lobby,
                so it sends the request again, and a server that made a new
                lobby for every request would split one match's players
                across two lobbies. The Idempotency-Key header tells you which
                requests are the same create.

                A repeated create carrying the same Idempotency-Key must
                return the same lobby. The key is at most 128 ASCII letters,
                digits and -, so it always fits as a matchId. BluMint closes a
                lobby by its key, and every report names it, so keep each key
                for as long as you keep the lobby it made.
                Keep a key whose create made no lobby for at
                least 3 hours, the longest BluMint
                can go on sending that key's create and its close, so a close
                can mark it closed and a later create under it answers 409
                idempotency_key_reused. Two requests with one key can arrive
                at the same moment, so serialize on the key, for example with
                a unique reservation row, so one key yields one lobby. A close
                takes the same reservation: a close that finds a create under
                its key still building records the key closed and answers
                200, and before that create commits its lobby, it re-reads the
                mark under the reservation, tears down what it built and
                answers 409 idempotency_key_reused, which BluMint expects for
                a match it moved past. Honor the key one
                of two ways: store the key with the lobby and answer a repeat
                with the stored lobby, or derive your matchId from the key, the
                key itself or a UUIDv5 of it, so your own uniqueness on lobby
                ids finds the existing lobby and the key lives exactly as long
                as its lobby, which satisfies both rules. Every repeat
                of one create carries the same key. BluMint sends a new key
                whenever it needs a new lobby for the same BluMint match (or
                the same game session, on single game sessions): after you
                abort with retryable: true, after the host resets the score,
                and after the host undoes the start of the tournament and
                starts it again. A matchId you derive from the key is
                therefore the same for every repeat and new for every new
                lobby. If you registered a close URL, BluMint waits for your
                200 to a close before it creates another lobby for any player
                in the closed lobby.

                Answer within 30 seconds: BluMint waits 40 seconds for each
                request, counted on the wall clock and including DNS lookup
                and connection time. Players are waiting while you create the
                lobby, so BluMint holds the match rather than let one stuck
                request hold them up, and the 10 seconds between the two
                cover the network, so an answer you send in time is never
                taken for an outage. If a request arrives for a key you are
                still creating a lobby for, answer with that lobby once it
                exists, or answer 503 so BluMint sends the same key again.
                Never answer 409 there: BluMint treats 409 as final and closes
                the lobby your first request is still creating. Never start a
                second lobby for one key.

                When a round starts, BluMint sends the creates for all of its
                matches at the same moment, and sets no limit on how many it
                sends at once: a 256-team single-elimination tournament sends
                about 128 together. Handle the burst rather than answering
                429, which BluMint reads as an outage answer.

                Which answer to send when is the decision table above.

                When your server is down only for a while, answer 503 or
                another status on the outage row. An outage answer may carry
                Retry-After, in seconds or as an HTTP date. The outage row
                says how long BluMint then waits, and a wait reaching past the
                end of the hold is cut short, so BluMint still sends one last
                create. Any answer the table does not list is final and does
                what the 500 row says. BluMint reads a 500 as your code
                failing on this request, which sending it again would only
                repeat, so when a problem will clear on its own, such as a
                deploy, a restart or a full queue, answer 503, not 500. Never
                answer a busy player with a 5xx, which BluMint reads as your
                server being down. After
                a 500, idempotency_key_reused, an answer the table does not
                list, a 200 that breaks the rules below, or an outage answer
                to BluMint's last try, you may hold a lobby no player will
                join: with a close URL registered, BluMint closes it by its
                key, and without one, expire any lobby none of its players
                joins. After match_unsupported, invalid_request or
                player_unlinked, BluMint assumes you made no lobby and sends
                no close, so check the request before you create anything. A
                refusal carries only its code and, where the table names it,
                players. BluMint ignores any other text you add. Send
                player_unlinked for any player you can't match to one of
                yours, listing in players every id from the request you don't
                recognize. Treat a refused create as if it never happened:
                when you answer player_unlinked or player_busy, create nothing
                and don't mark the Idempotency-Key as used. BluMint sends the
                same key again, possibly with corrected player ids, and you
                must handle that retry like a first request.
              parameters:
                - name: Idempotency-Key
                  in: header
                  required: true
                  description: >-
                    A key BluMint chooses for this one create, built from
                    BluMint's own ids: at most 128 ASCII letters, digits and -.
                    Treat it as opaque and never parse it.
                  schema:
                    $ref: '#/components/schemas/PartnerCreateIdempotencyKey'
                  example: tA1b2-round-1-match-1
              requestBody:
                required: true
                content:
                  application/json:
                    schema:
                      type: object
                      required:
                        - teams
                        - spectators
                        - matchSettings
                        - readyWithinSeconds
                      properties:
                        teams:
                          type: array
                          description: >-
                            Every team in the match, within the teams-per-match
                            range you gave in the setup form, which is exactly
                            two on a best-of series. Admit only these players,
                            even when someone else learns the join link or lobby
                            code.
                          items:
                            type: object
                            required:
                              - name
                              - players
                            properties:
                              name:
                                type: string
                              players:
                                type: array
                                description: One entry per team member.
                                items:
                                  type: object
                                  required:
                                    - identities
                                  properties:
                                    identities:
                                      $ref: >-
                                        #/components/schemas/MatchCreationSeatIdentities
                              startingWins:
                                type: integer
                                minimum: 0
                                description: >-
                                  On a best-of series, present on every team
                                  when BluMint asks you for a new lobby for a
                                  match already under way: after you abort with
                                  retryable: true, and after the host resets the
                                  match. It is the game sessions of this match
                                  BluMint has already recorded for the team, 0
                                  after a reset. Absent on the first create for
                                  a match, including BluMint's retries of it,
                                  and on every create for a single game session.
                                  Count it into every report of the new lobby.
                        spectators:
                          type: array
                          maxItems: 16
                          description: >-
                            The host, streamers and moderators of the tournament
                            who chose to watch, never a player in the match or
                            anyone registered in the tournament. Always present,
                            and empty when nobody is listed. It can list more
                            spectators than your lobby admits. If your game
                            supports watching, admit listed identities as
                            spectators, in list order, until your lobby holds as
                            many as it admits; a spectator can never play or
                            report a result. Otherwise ignore the field. Never
                            refuse a create because of its spectators.
                          items:
                            type: object
                            required:
                              - identities
                            properties:
                              identities:
                                $ref: >-
                                  #/components/schemas/MatchCreationSeatIdentities
                        matchSettings:
                          type: object
                          additionalProperties: true
                          description: >-
                            The match settings the host chose, passed to you
                            unchanged, so hosts can run custom events of your
                            game, such as a one-map tournament or a short time
                            limit for a fast bracket. Its keys are the settings
                            of your game you listed in the setup form. Set up
                            the lobby with each one. An empty object means the
                            host chose none, so use your defaults. Answer 400
                            match_unsupported for a setting you cannot run.
                        readyWithinSeconds:
                          type: integer
                          minimum: 300
                          maximum: 1800
                          description: >-
                            The tournament's hold length in seconds, which the
                            host sets between 5 and 30 minutes, 10 by default.
                            BluMint tells every player to be ready this long
                            after their match starts, or be disqualified, and
                            BluMint times that itself. If your game ends a lobby
                            on its own when a player doesn't show up, let that
                            happen no earlier than this after you answer the
                            create; otherwise ignore the field. The host can
                            lengthen the hold while a match waits, so a repeat
                            of one Idempotency-Key can carry a larger value.
                            Leave it out when you compare a repeat's body.
                        series:
                          type: object
                          description: >-
                            Present on every best-of series create, and absent
                            on single game sessions.
                          required:
                            - gamesToWin
                          properties:
                            gamesToWin:
                              type: integer
                              minimum: 1
                              description: >-
                                The game sessions a team must win to take the
                                match.
                    example:
                      teams:
                        - name: Team Alice
                          players:
                            - identities:
                                - provider: lichess
                                  inGameId: alice
                        - name: Team Bob
                          players:
                            - identities:
                                - provider: lichess
                                  inGameId: bob
                      spectators: []
                      matchSettings:
                        clock:
                          limitSeconds: 180
                          incrementSeconds: 2
                        rated: false
                      readyWithinSeconds: 600
                      series:
                        gamesToWin: 3
              responses:
                '200':
                  description: >-
                    The lobby exists. Answer matchId and one of three ways for
                    players to get in, the one your integration declared in the
                    setup form. A join link: send matchUrl, which players open.
                    A lobby code: send lobbyCode, which players type into your
                    game. Neither, because your own game client puts players
                    into the lobby: send spectateUrl, a watch link BluMint
                    offers the host so they can follow the match. Send only the
                    field of your own way in. A missing field, a field of
                    another way in, or a link on another hostname fails the
                    create for good: the host takes the match and starts it
                    manually.
                  content:
                    application/json:
                      schema:
                        type: object
                        required:
                          - matchId
                        properties:
                          matchId:
                            type: string
                            minLength: 1
                            maxLength: 256
                            description: >-
                              Your id for this lobby. BluMint treats it as
                              opaque, sends it back unchanged, and you name it
                              in every report. It is well-formed Unicode, with
                              no unpaired UTF-16 surrogate.
                          matchUrl:
                            type: string
                            format: uri
                            maxLength: 2048
                            description: >-
                              On an integration whose players join by a link,
                              the link players open, to a page on your site or
                              your game client directly. It is https, carries no
                              `user:pass@`, and its hostname is exactly one of
                              the join-link hostnames you gave BluMint for this
                              environment; a subdomain does not match. A lobby
                              code in the fragment after `#` is fine, since
                              BluMint sends the link byte for byte.
                          lobbyCode:
                            type: string
                            minLength: 1
                            maxLength: 32
                            description: >-
                              On an integration whose players join by a code,
                              the code players type into your game, using only
                              ASCII letters, digits, spaces, `_`, `*`, `.`, the
                              backtick and `-`. BluMint shows it in chat, so it
                              is never wrapped in `*`, `_` or backticks and
                              holds no link or email address.
                          spectateUrl:
                            type: string
                            format: uri
                            maxLength: 2048
                            description: >-
                              On an integration whose own game client puts
                              players into the lobby, the https watch link
                              BluMint offers the host, on one of the watch-link
                              hostnames you gave BluMint. Anyone viewing the
                              tournament can read it, so it lets its holder
                              watch and nothing more: never play, control the
                              match, or get the access you give the spectators
                              listed in the create.
                      example:
                        matchId: 4f9c2a7e
                        matchUrl: https://lichess.org/AbCd1234
                '400':
                  description: A refusal the decision table above lists.
                  content:
                    application/json:
                      schema:
                        oneOf:
                          - type: object
                            title: player_unlinked
                            required:
                              - code
                              - players
                            properties:
                              code:
                                type: string
                                enum:
                                  - player_unlinked
                              players:
                                type: array
                                minItems: 1
                                items:
                                  type: string
                                description: >-
                                  Every id from the request you can't match to
                                  one of your players.
                          - type: object
                            title: request refused
                            required:
                              - code
                            properties:
                              code:
                                type: string
                                enum:
                                  - match_unsupported
                                  - invalid_request
                      example:
                        code: player_unlinked
                        players:
                          - emb1_example
                '409':
                  description: >-
                    idempotency_key_reused, the decision table's refusal of a
                    key that arrived with a different body or that a close
                    already named.
                  content:
                    application/json:
                      schema:
                        type: object
                        required:
                          - code
                        properties:
                          code:
                            type: string
                            enum:
                              - idempotency_key_reused
                '423':
                  description: >-
                    player_busy, the decision table's answer when a player the
                    create identifies is still in another of your lobbies.
                    BluMint holds the match and retries.
                  content:
                    application/json:
                      schema:
                        type: object
                        required:
                          - code
                          - players
                        properties:
                          code:
                            type: string
                            enum:
                              - player_busy
                          players:
                            type: array
                            minItems: 1
                            items:
                              type: string
                            description: >-
                              Every player id from the request that another of
                              your lobbies still holds.
                      example:
                        code: player_busy
                        players:
                          - emb1_example
              method: post
              type: path
            path: '{$request.body#/createMatchUrl}'
      security:
        - ApiKeyAuth: []
components:
  schemas:
    CallbackAuthentication:
      type: object
      required:
        - secret
        - config
      properties:
        secret:
          type: string
          description: >-
            A value you choose, which BluMint sends to your server so you can
            tell the call came from BluMint. It is not your BluMint API key, so
            never put that key here. Use a long random value.
          example: your-inbound-secret
        config:
          type: object
          description: >-
            Where BluMint puts the secret. It sends valuePrefix, then the
            secret, then valueSuffix, under the name in key. In a header, that
            value may hold only tabs and Latin-1 characters from U+0020 through
            U+00FF other than DEL (U+007F), and cannot start or end with a space
            or tab, which your server's HTTP parser strips, so trim the newline
            or space a secret read from a file often ends in. BluMint refuses
            any other header value with 400.
          required:
            - location
            - key
          properties:
            location:
              type: string
              enum:
                - header
                - queryParam
                - body
              description: >-
                header sends the secret as a request header, and queryParam as a
                query parameter. body puts it into every POST body BluMint sends
                this URL as a top-level field: check that field, then remove it
                before you read or validate the rest of the body, and, on a
                callback that carries an Idempotency-Key, before you compare a
                request with an earlier one under the same key.
              example: header
            key:
              type: string
              description: >-
                The header name, query parameter or body field that carries the
                secret. BluMint refuses the registration with 400, quoting the
                key and saying whether it is a header or a body field, when the
                key names something it already sends this callback in the same
                place: a body field such as `teams`, any sign-in method field a
                player lookup can carry (`discord`, `epic`, `twitch` and
                `lichess`, even one your game does not use), the
                `Idempotency-Key` header, or a header every BluMint POST carries
                (`Accept`, `Accept-Encoding`, `Connection`, `Content-Length`,
                `Content-Type`, `Host` and `User-Agent`). Header names match in
                any case, and body fields exactly. A header key must be a valid
                HTTP header name, one or more letters, digits or characters from
                `!#$%&'*+-.^_|~` or the backtick, with no spaces, and cannot be
                `common`, `delete`, `expect`, `get`, `head`, `patch`, `post`,
                `put`, `trailer`, `transfer-encoding` or `__proto__` in any
                case, names BluMint's HTTP client reserves. A body key cannot be
                a built-in JavaScript object property name such as
                `constructor`, `toString` or `__proto__`. A query parameter key
                may be any string. A name such as `blumint_secret` passes every
                rule.
              example: Authorization
            valuePrefix:
              type: string
              description: Text BluMint sends before the secret, such as "Bearer ".
              example: 'Bearer '
            valueSuffix:
              type: string
              description: Text BluMint sends after the secret.
    PartnerCreateIdempotencyKey:
      type: string
      maxLength: 128
      pattern: ^[A-Za-z0-9-]{1,128}$
      description: >-
        The Idempotency-Key BluMint sent with the create that made the lobby,
        exactly as sent: at most 128 ASCII letters, digits and -. Treat it as
        opaque and never parse it.
    MatchCreationSeatIdentities:
      type: array
      minItems: 1
      description: >-
        The ids that identify this person in your game. If BluMint gets your
        player ids from your lookup URL, the list holds exactly one entry, `{
        inGameId }`: your own player id, as your lookup last answered it.
        Otherwise it holds one entry, `{ provider, inGameId }`, for each
        authentication method you chose in the setup form that this person has
        linked: admit them if any one matches, and identify them in a report by
        any one of them. Your integration receives only one of the two forms, so
        you never need to tell them apart.
      items:
        oneOf:
          - $ref: '#/components/schemas/ProviderSeatIdentity'
          - $ref: '#/components/schemas/PartnerSeatIdentity'
    ProviderSeatIdentity:
      type: object
      required:
        - provider
        - inGameId
      properties:
        provider:
          type: string
          enum:
            - discord
            - epic
            - twitch
            - lichess
          description: >-
            The authentication method the person linked on BluMint, one you
            chose in the setup form.
        inGameId:
          type: string
          description: >-
            The person's id on that provider. Every inGameId is a string, so
            store it as a string and send it back as one in every report: an id
            sent as a number is refused with invalid_request. An id that happens
            to hold only digits is still a string: a Discord id is longer than a
            JSON number holds exactly, so an id parsed into a number comes back
            as a different id.
    PartnerSeatIdentity:
      type: object
      required:
        - inGameId
      not:
        required:
          - provider
      properties:
        inGameId:
          type: string
          maxLength: 256
          description: >-
            Your player id for this person, as your lookup answered it for this
            create.
  responses:
    CallbackRegistrationRefused:
      description: >-
        The URL is missing, is not a valid absolute URL or is not https,
        contains a user name or password (`user:pass@`), has an IP-address host
        other than a public IPv4 address, the authentication block is malformed,
        its header key or value is not a valid HTTP header name or value, its
        header key is a name BluMint's HTTP client reserves, its body key is a
        built-in JavaScript object property name, or its key names a header or
        body field BluMint already sends this callback, which for a lookup is
        every sign-in method field a lookup can carry. A refusal of the key
        quotes it and says whether it is a header or a body field.
    CallbackRegistrationUnauthenticated:
      description: The X-Api-Key header is missing or unknown.
    CallbackRegistrationGameNotFound:
      description: The API key is bound to no game, or its game does not exist.
    CallbackRegistrationMethodNotAllowed:
      description: The method is not POST.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-Api-Key

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.