Every endpoint, its auth scope, and a request/response example — 305 across 46 groups.
Most games use the @triggair/sdk
client rather than raw HTTP, but this is the underlying contract. Machine-readable:
/openapi.json
(OpenAPI 3.1). A publishable key goes in
X-Triggair-Key; a player token and the
developer/operator sessions go in Authorization: Bearer.
No endpoints match — try a method (post), a path fragment
(leaderboards), or a keyword.
Email/password + Google sign-in are first-class endpoints —
POST /v1/players/signup,
/login,
/token/refresh,
/password-reset, and
/oauth/google/start (all below). The SDK
wraps them as
tg.auth.signUp /
signInWithPassword /
signInWithGoogle /
sendPasswordReset and handles the
session + token refresh for you. See the
Player
accounts guide.
POST /v1/players/anonymouspublishable key
Mint an anonymous player token
Exchanges a stable device id for a 24h player token. The player is created on first use. This is what the SDK's tg.login() calls; every player-scoped call sends the returned token as `Authorization: Bearer`.
Is an origin allowed for a game (OAuth callback guard)
Keyless. The centralized OAuth /auth/callback page calls this before delivering a Google session, to confirm the return `origin` is in the game's allowlist (pk passed as `?key`). Returns only `{ allowed }`, never the session. BE-19 security guard.
response
{
"allowed": true
}
POST /v1/players/signuppublishable key
Register a player account (email/password)
Create an account. With email confirmation on (the default), returns `{ needs_confirmation: true }` and a confirmation email is sent; set `redirect_to` (an allowlisted origin) for where its link lands. If a session is issued immediately, returns `{ needs_confirmation: false, session, player }`. The SDK wraps this as `tg.auth.signUp`.
Verify credentials and return the account `session` (access + refresh token) plus a game-scoped player token (resume/adopt/link/create, or a `conflict` merge offer). Bad credentials return a generic 401. The SDK wraps this as `tg.auth.signInWithPassword`.
Exchange a `refresh_token` for a fresh account session AND a re-minted player token, so a login survives token/session expiry. The SDK calls this automatically.
Always returns `{ ok: true }` — never reveals whether the address has an account. `redirect_to` (an allowlisted origin) is where the link lands. The SDK wraps this as `tg.auth.sendPasswordReset`.
request
{
"email": "player@example.com"
}
response
{
"ok": true
}
POST /v1/players/logoutpublishable key
Revoke the account session
Best-effort revoke of the account session (`Authorization: Bearer <access token>`). The client clears its own session regardless.
response
{
"ok": true
}
GET /v1/players/oauth/google/startno auth
Start Google sign-in (redirect)
Keyless (opened in a popup; `key` + `origin` in the query). Validates the key + that the origin is allowlisted + Google is enabled, then 302-redirects into the Google OAuth flow, returning to the centralized callback. The SDK wraps this as `tg.auth.signInWithGoogle`.
Parameters
key (query) The game's publishable key.
origin (query) The calling game's origin (must be allowlisted).
POST /v1/players/sessionpublishable key
Exchange an account session for a player token
Verifies an account session token (`Authorization: Bearer`, obtained via tg.auth) and returns a game-scoped player token, resolving the account↔player mapping. `outcome` is one of resumed/adopted/linked/created, or `conflict` — which also returns a `merge` block (an account player AND a distinct anonymous player with data both exist). Send the current `device_id` so a first login can link the anonymous player.
request
{
"device_id": "a-stable-device-uuid"
}
response · On outcome=conflict, `merge.ticket` is passed to /v1/players/session/merge.
With the merge ticket from a `conflict` session, choose `keep_account` (keep the account's data) or `use_anonymous` (replace it with the anonymous progress — a pointer swap that PARKS, never deletes, the displaced player). Returns a token for the resulting player. BE-18.
Last-write-wins by default. Send `If-Match: <version>` for optimistic concurrency — a stale version returns 409 save_conflict. Returns 201 on first write, 200 on update.
Submits a score to a configured board. The board keeps each player's best score for the period (higher_is_better sets direction); there is no last/sum mode. The period (all-time/daily/weekly) is set by the developer; the response reports the player's kept score for the current period.
Creates a short code carrying an opaque context blob (a level, a challenge, a referral). Resolve it with GET /v1/share/:code on the recipient's device.
A WebSocket upgrade. Because a browser WS can't send headers, the pk + player token go in the query (?key=&token=). Presence + broadcast; chat is moderated in transit. Rooms named team:<id> / match:<id> require membership. Use tg.realtime.join(room) from the SDK.
Assign the player to a variant (sticky) + log exposure
Deterministic, sticky server-side bucketing — the same player always gets the same variant. Returns { variant: null, in_experiment: false } when the experiment is unknown, not running, or the player isn't targeted (treat as control).
Marks the enrolled player's first conversion. `metric` names the goal reached; it counts when it matches the experiment's measured metric (omit to match the primary one).
The key the browser needs to subscribe to Web Push. Pass its bytes as applicationServerKey to pushManager.subscribe (the SDK's tg.push.subscribe() does this).
response
{
"key": "BEl…<base64url P-256 public key>"
}
POST /v1/push/subscribeplayer token
Register this device's push subscription
Body mirrors the browser's PushSubscription JSON. Refused for minors / age-unknown players — the behavioral_push compliance gate runs before the row is stored (403 age_restricted / parental_consent_required).
Returns a provider checkout URL to send the buyer to. The payment provider is abstracted (a mock provider ships by default; swap it for a merchant-of-record without touching these routes).
Public endpoint a payment provider POSTs subscription events to; the provider module verifies the signature and normalizes the event. A no-op for the built-in mock provider.
Returns a `tg_pat_` token ONCE. It authenticates this developer for the whole management API (/v1/dev/*) and the MCP server, with full parity to a dashboard session — an agent or CI can create and configure games with it, no browser needed. Treat it like a password; only its hash is stored.
request
{
"name": "ci-bot"
}
response · Store the token now — it won't be shown again.
POST /v1/dev/games/:id/leaderboards/:board/resetdeveloper session
Reset a board's scores (keep the definition)
Wipe every score from the board while keeping its config. Use it to clean up after a verify/test run so exploratory submissions don't linger on a live board. Also exposed as the triggair_reset_leaderboard MCP tool.
Fans out to the target (all / a segment / one player), encrypting per subscription (RFC 8291) and signing VAPID (RFC 8292). Dead endpoints (404/410) are pruned. Requires VAPID configured on the deployment.
Parameters
id (path) Game id.
request
{
"title": "Your daily reward is ready",
"body": "Claim it before the streak resets.",
"url": "https://yourgame.example/play",
"target": {
"type": "all"
}
}
history_limit = how many recent chat messages a room replays to a joiner (0–200; 0 opts out of history for high-frequency state rooms). Applied to new connections via the DO.
GET /v1/dev/games/:id/email-templatesdeveloper session
Get the effective account-email templates
Returns every email type (signup, recovery, email_change, magiclink, invite, reauthentication) with its effective template — the customization if one exists, else the built-in default — plus the placeholder reference. See the 'Customizing account emails' guide.
PUT /v1/dev/games/:id/email-templates/:typedeveloper session
Customize one account email
Set the subject + HTML for one email type. The HTML is sanitized to a safe email subset on save (sanitize-and-store-clean); the response reports what was `removed` and any author `warnings` (e.g. a missing action placeholder). Idempotent per (game, type).
Model Context Protocol endpoint (streamable HTTP, JSON-RPC 2.0)
The agent-facing management surface: the triggair_* tools (configure games/boards/economy/flags/moderation/compliance, verify_integration, search_docs) over the Web-standard streamable-HTTP MCP transport, stateless JSON mode. Point an MCP client (Cursor, Claude, …) here with your developer session token as `Authorization: Bearer <jwt>`. Tool calls run in-process against your own games — ownership is enforced exactly as on /v1/dev/*.
Social
/v1/friendsplayer tokenList friends
/v1/friends/requestsplayer tokenList incoming friend requests
/v1/friends/:idplayer tokenSend or accept a friend request
id(path) The other player's id./v1/friends/:idplayer tokenRemove a friend / cancel a request
id(path) The other player's id./v1/friends/:id/blockplayer tokenBlock a player
id(path) The player to block./v1/shareplayer tokenMint a share / invite link
Creates a short code carrying an opaque context blob (a level, a challenge, a referral). Resolve it with GET /v1/share/:code on the recipient's device.
/v1/share/:codeplayer tokenResolve a share link
code(path) Share code.