Chess — Create a session
Sessions are created server-side using your secret API key. Never call this from the browser — your API key would be exposed. The response contains a short-lived JWT sessionToken that is safe to pass to the client.
Endpoint
Request
const res = await fetch('https://api.beta-gamer.com/v1/sessions', {
method: 'POST',
headers: {
'Authorization': 'Bearer bg_live_xxxx', // secret API key — server-side only
'Content-Type': 'application/json',
},
body: JSON.stringify({
game: 'chess',
matchType: 'matchmaking', // see matchType options below
players: [{ id: 'user_123', displayName: 'Alex' }],
afkTimeoutEnabled: true,
}),
});
const { sessionToken, sessionId, expiresAt } = await res.json();
// Pass sessionToken to your client — never the raw API keyBody parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
game | "chess" | Yes | — | Must be "chess". |
matchType | "matchmaking" | "bot" | "private" | Yes | — | How the match is created. See matchType details below. |
players | Player[] | Yes | — | { id, displayName }[]. id is your tenant's userId — it appears in game:over.winner for result identification. displayName is shown in the UI. One entry for matchmaking/bot, two for private. |
botDifficulty | "easy" | "medium" | "hard" | No | "medium" | Bot strength. Only applies when matchType is "bot". |
afkTimeoutEnabled | boolean | No | true | Whether the 90-second AFK forfeit rule is active. |
theme | ThemeOverride | No | — | Override dashboard theme tokens for this session only. See Theming. |
matchType details
matchmakingPlayer is placed in a queue. The server pairs them with the next available opponent. Pass one player.
{ game: 'chess', matchType: 'matchmaking', players: [{ id: 'u1', displayName: 'Alex' }] }botPlayer is immediately matched against an AI. Use botDifficulty to set strength. Pass one player.
{ game: 'chess', matchType: 'bot', botDifficulty: 'hard', players: [{ id: 'u1', displayName: 'Alex' }] }privateA private room is created. Pass two players — both receive the same sessionToken and connect to the same room.
{ game: 'chess', matchType: 'private', players: [{ id: 'u1', displayName: 'Alex' }, { id: 'u2', displayName: 'Sam' }] }Response
| Field | Type | Description |
|---|---|---|
sessionId | string | Unique session identifier. Store this server-side to look up results later. |
sessionToken | string | Short-lived JWT. Pass to the client and use as the token prop on BetaGamerProvider. |
expiresAt | string | ISO 8601 timestamp. Token is valid until this time (typically 1 hour). |
{
"sessionId": "sess_01j9abc123",
"sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXNzaW9uSWQiOiJzZXNzXzAxajlhYmMxMjMiLCJnYW1lIjoiY2hlc3MiLCJtYXRjaFR5cGUiOiJib3QiLCJwbGF5ZXJzIjpbeyJpZCI6InVzZXJfMTIzIiwiZGlzcGxheU5hbWUiOiJBbGV4In1dLCJ0aGVtZSI6e30sImlhdCI6MTc0MjA4MDAwMCwiZXhwIjoxNzQyMDgzNjAwfQ.signature",
"expiresAt": "2026-03-16T02:00:00.000Z"
}Ended sessions
If a player refreshes the page after a game ends, the token is still valid but the session is marked ended. Validate the token before rendering the game UI:
// GET /api/v1/sessions/validate?token=<sessionToken>
const res = await fetch(`/api/v1/sessions/validate?token=${sessionToken}`);
const { status, game, result } = await res.json();
if (status === 'ended') {
// show final result screen — result: { winner, reason, duration, pgn, fen }
} else {
// render BetaGamerProvider with the token
}players[].id is your tenant's user ID — this is what game:over.winner contains. Always compare winner against players[0].id, never against displayName. Display names can change; user IDs are stable identifiers you control.