Create a connect pass
Verify a player your server has authenticated, so the game can start a connect session at the verified level.
POST /v1/games/{game}/connect/passes · requires players:connect
Call it from your own server when a player presses Connect in your game, and send the pass to the game. The game sends it as proof in Start connect. CEEJAY then trusts your server's verification of the player, and the session is at the verified level. Connect explains the whole flow.
Path parameters
Prop
Type
Body parameters
Prop
Type
Returns
Prop
Type
Example
curl -X POST https://ceejay.communitystudios.xyz/api/v1/games/rugby_manager/connect/passes \
-H "Authorization: Bearer $CEEJAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"playerId": "p_19",
"playerName": "Nova77"
}'The TypeScript tab calls ceejay.connect.createPass from the TypeScript SDK. It returns the data of the response below.
{
"success": true,
"data": {
"pass": "ceejay_pass_4f8a2c1e9b7d3e41f8a6b0c1d25f0c2a9b7d3e41f8a6b0c1d24f8a2c1e9b7d3e",
"expiresAt": "2026-10-08T18:14:11.000Z"
}
}What a pass is
A pass lasts 10 minutes and works once, for this game and this player. CEEJAY stores only its hash, so it cannot be shown again: create a new pass when the player presses Connect again.
A pass is used up by the Start connect that carries it, whether or not the session is finished. A second start with the same pass returns 401 with the code proof_rejected and reason: "used".
The request takes no idempotencyKey: creating a pass has no side effects, and a second call creates a second pass.
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
| Status | code | error | When |
|---|---|---|---|
400 | bad_request | The request body must be a JSON object | The 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 |
400 | bad_player_id | playerId must be 1 to 128 characters: letters, digits and . _ : @ | + = -, starting with a letter or a digit | playerId is missing, is not text, is longer than 128 characters, or contains a character that is not allowed. A number is refused |
400 | bad_request | playerName must be text of at most 80 characters | playerName was sent and is not text, is longer than 80 characters, or contains a null character (U+0000) |
404 | not_available | This 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 |
403 | community_not_active | This community is no longer active on CEEJAY | The community removed CEEJAY from its server |
404 | game_not_found | Game not found | The 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 |
403 | game_not_allowed | This API key is limited to other games | The key is limited to other games of the community |
403 | audience_not_allowed | A game made for children cannot connect players or send player data | The game is set up as made for children. Such a game connects nobody |
409 | game_paused | This game is paused | The game is paused or suspended |
The checks run in that order: the body, playerId and playerName, then the game in the path.
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.

