CEEJAYDocs

Create a connect session

Start a connect session from your own server for a player you have authenticated, or attach that player to a code a member created in Discord.

POST /v1/games/{game}/connect/sessions · requires players:connect

Use it when your server, not the game, talks to CEEJAY. The secret key verifies who the player is, so the session is at the verified level. See Connect for the full flow.

Path parameters

Prop

Type

Body parameters

Prop

Type

Returns

Prop

Type

Example

Request
curl -X POST https://ceejay.communitystudios.xyz/api/v1/games/rugby_manager/connect/sessions \
  -H "Authorization: Bearer $CEEJAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "playerId": "p_19",
    "playerName": "Nova77",
    "returnTo": "game"
  }'

The TypeScript tab calls ceejay.connect.createSession from the TypeScript SDK. It returns the data of the response below.

200 OK
{
  "success": true,
  "data": {
    "sessionId": "kT3v9QmZ1xY7bLw2RfA8cN",
    "url": "https://ceejay.communitystudios.xyz/connect/s/kT3v9QmZ1xY7bLw2RfA8cN",
    "qrUrl": "https://ceejay.communitystudios.xyz/connect/s/kT3v9QmZ1xY7bLw2RfA8cN/qr",
    "code": "K7M-2QX",
    "sessionSecret": "ceejay_cs_4f8a2c1e9b7d3e41f8a6b0c1d25f0c2a9b7d3e41f8a6b0c1d24f8a2c1e9b7d3e",
    "expiresAt": "2026-10-08T18:14:11.000Z",
    "status": "pending",
    "alreadyConnected": false,
    "member": null
  }
}
200 OK, with a code
{
  "success": true,
  "data": {
    "sessionId": "kT3v9QmZ1xY7bLw2RfA8cN",
    "url": null,
    "qrUrl": null,
    "code": null,
    "sessionSecret": "ceejay_cs_4f8a2c1e9b7d3e41f8a6b0c1d25f0c2a9b7d3e41f8a6b0c1d24f8a2c1e9b7d3e",
    "expiresAt": "2026-10-08T18:14:11.000Z",
    "status": "needs_game_confirmation",
    "alreadyConnected": false,
    "member": {
      "displayName": "Nova",
      "avatarUrl": "https://cdn.discordapp.com/avatars/409876543210987654/a1b2c3d4e5f60718293a4b5c6d7e8f90.png"
    }
  }
}

What to do with the response

Pass url to the player's device, or show code with the URL to enter it at, or show the image at qrUrl. The player approves with their Discord account on CEEJAY's connect page. The session lasts 10 minutes, and starting one ends every earlier open session for the same player.

Share sessionSecret with your game only when the game should hold the player's tokens: with it the game reads the result with Get the result and gets a player session and a refresh token. A server that runs the whole flow never passes it on, and reads the session with Get a connect session.

Confirmation by the game

A connection is saved only after the Discord member and the game have both confirmed. The game's confirmation can come in three ways:

  • From the game, with sessionSecret, through Confirm connect.
  • From your server, through Confirm a connect session, after your game has shown the player the Discord name.
  • Up front, with confirmInGame: false. Send that only when the link is opened on the device the player is signed in on and the code is never shown where others can read it: the step it skips is the one where a player sees that someone else approved.

With a code

A member can start in Discord, where they get a code to enter in the game. When your game does not integrate CEEJAY directly, your server sends that code here with the player. No new session is created: the player is attached to the member's session, the code is cleared, and member identifies whose code it was. Show that name to the player before the game approves.

The code comes from the game's button in the community's Discord server: the member presses it and gets a code that works once and lasts 10 minutes, and then enters it in the game. Where the community has not posted the button, or the code has been used or has run out, no open request has it and code returns 404 with the code code_not_found.

A player who is already connected

When this player is already connected at the verified level with the member's own approval, nobody is asked again: status is approved, alreadyConnected is true, and url, qrUrl and code are null. A player your server linked with Link an account is not connected that way until the member has approved once, so the session takes the usual path.

Age

A game set up for a mixed audience must send underAge with every session. true returns 403 with the code under_age: nothing is stored, and a connection the player has is ended. A game set up as made for children connects nobody.

The request takes no idempotencyKey: a second call creates a second session and ends the first.

The scope

players:connect lets a server act for a player: it can create a pass, and with a pass any player who is already connected at the verified level can be signed in. Keep it on your own server. It is never part of *: a Full Access key returns 403 here. Tick Act for a player when you make the key.

Limits

The Connect requests of a server have a limit of their own: 600 requests a minute for each game, across all five Connect endpoints. They are not counted against the key's own requests per minute. One API key is also capped at 6,000 requests a minute across all five Connect endpoints. The three X-RateLimit headers report the game's limit of 600 once the request has resolved its game, and the key's limit of 6,000 on a response returned before that: see Rate limits.

Errors

StatuscodeerrorWhen
400bad_requestThe request body must be a JSON objectThe body is null, text, a number or a list. A request with no Content-Type header is read as text, so it gets this response too
404not_availableThis is not available on this instance yet.Connect is not enabled for this instance. It is enabled per instance. The body adds feature, which is players. Retrying will not change the response
403community_not_activeThis community is no longer active on CEEJAYThe community removed CEEJAY from its server
404game_not_foundGame not foundThe community has no game with this slug, or the game was removed. A slug that is not 2 to 32 lower-case letters, digits and underscores, starting with a letter, gets this response too
403game_not_allowedThis API key is limited to other gamesThe key is limited to other games of the community
403audience_not_allowedA game made for children cannot connect players or send player dataThe game is set up as made for children. Such a game connects nobody
409game_pausedThis game is pausedThe game is paused or suspended
400bad_player_idplayerId must be 1 to 128 characters: letters, digits and . _ : @ | + = -, starting with a letter or a digitplayerId is missing, is not text, is longer than 128 characters, or contains a character that is not allowed. A number is refused
400bad_requestplayerName must be text of at most 80 charactersplayerName was sent and is not text, is longer than 80 characters, or contains a null character (U+0000)
400bad_requestcode must be textcode was sent and is not text
400unknown_returnreturnTo is not one of the return addresses saved for this gamereturnTo is not the key of a return URL saved for the game
400bad_requestlocale must be a language tag such as en or pt-BRlocale was sent and is not a language tag of at most 12 characters
400bad_requestunderAge must be true or falseunderAge was sent and is not true or false
400bad_requestconfirmInGame must be true or falseconfirmInGame was sent and is not true or false
400age_answer_requiredThis game is for a mixed audience, so underAge must be sent as true or falseThe game is set up for a mixed audience and underAge was not sent
403under_ageThis player cannot be connectedunderAge is true. Nothing is stored, and a connection the player has is ended when the player is verified
404code_not_foundNo open request has this codeNo request started by a member in Discord for this game has this code: it is incorrect, it was already used, or its 10 minutes are over
409session_lockedThis request was locked after too many attempts. Start againThe code belongs to an open request that was locked by this fifth failed attempt on it

The checks run in that order: the body, the game in the path, then the fields.

Every error body also carries requestId, and a 400 with the code bad_request names the invalid field in field. Match on code, not on the message text, which can change.

The errors every request shares (401, 403 for a missing scope, 405, 429, 500) are on the Errors page.

On this page

Community StudiosPrivacyTerms