REST API overview
- Written for
- + Written for
- Deprecated
- + Deprecated
- Applies to
- + Applies to
REST API overview
The Cool GPT Games REST API is the source of truth for everything you do as a developer: creating games, uploading builds, reading your stats, running tournaments, configuring live-ops and webhooks. The Publisher SDK, the CLI and the MCP server are thin wrappers over the endpoints on this page.
This page covers the conventions that apply to every endpoint, then gives an index of every developer-facing endpoint with links to the page that documents it in detail.
Base URL
https://api.coolgptgames.comEvery path in these docs is relative to that origin, for example GET https://api.coolgptgames.com/v1/me/games.
All endpoints live under the /v1/ prefix. Two unversioned health endpoints also exist (GET /health, GET /ready); they are for uptime monitoring and carry no data you need.
Authentication
There are two ways to authenticate. Both identify your account, and both are checked on every request.
Method | How it's sent | Who uses it | Scopes |
|---|---|---|---|
API key |
| Your servers, scripts, CI, the CLI, the Publisher SDK, the MCP server | Limited to the scopes chosen when the key was created |
Interactive session | Set by signing in on coolgptgames.com (browser cookie, or a session bearer token) | The website and dashboard | Full access to your account; never scope-limited |
API keys
Create keys in the dashboard under Dashboard → API keys (see API keys & scopes). Send the key as a bearer token:
curl https://api.coolgptgames.com/v1/me/games \
-H "Authorization: Bearer $COOLGPTGAMES_API_KEY"New keys start with
ak_. Keys created before September 2026 start witharc_live_and keep working unchanged. Treat both the same way.API keys are accepted only in the
Authorization: Bearerheader. A key placed in a cookie is ignored.A revoked key stops working immediately, on the very next request.
A key belonging to a banned or deleted account stops working immediately.
Key requests are exempt from CSRF checks (they can't ride an ambient browser cookie), so no extra headers are needed.
What API keys can never do
Some routes manage your account itself (its email, its keys, its payout details, its public profile) or spend and move coins. Those routes require an interactive session and reject any API key, whatever its scopes, with:
{
"error": {
"code": "session_required",
"message": "API keys can't manage your account — sign in to the dashboard."
}
}(HTTP 403.) This means a leaked key, even a full-access one, can't mint new keys, revoke your other keys, change your email, delete your account, redirect your payouts, or spend your coins. The session-only routes are:
Method & path | What it does |
|---|---|
| Create an API key |
| List your API keys |
| Revoke an API key |
| Start payout (bank) onboarding |
| Edit your public profile |
| Upload your avatar |
| Upload your profile banner |
| Change your account email |
| Delete your account |
| Notification preferences |
| Onboarding interests |
| Ad-personalisation age declaration |
| Claim the daily coin reward |
| Gift coins to a friend |
| Buy from the platform cosmetics shop |
| Claim a season reward tier |
| Buy an in-game store item |
| Fund a tournament prize pool (free tournaments still accept a key) |
Do these signed in on coolgptgames.com.
Calling from a browser
The API only accepts cross-origin browser requests from Cool GPT Games' own sites. Call the API from your server, script or CI job, not from JavaScript running on your own website. It's also the right choice for security: an API key in browser code is a leaked key.
Inside a game you never call the REST API directly. Games talk to the platform through the GameSDK (see GameSDK core reference), and the player page makes the API calls for you.
Session cookies and CSRF
This only matters if you are building against the API with a browser session rather than a key. Cookie-authenticated POST, PUT, PATCH and DELETE requests must echo the value of the csrf cookie in an X-CSRF-Token header, or they fail with 403 forbidden ("CSRF token missing or invalid"). Bearer-token requests (API keys and session tokens) are exempt.
Roles
Every account can both play and publish games. Creator endpoints check that the caller owns the game in question. Acting on someone else's game returns 403 forbidden (or 404 not_found where the game's existence shouldn't be revealed).
Requests
JSON bodies. Send
Content-Type: application/jsonwhen there is a body. Don't send that header on requests without a body (for exampleDELETE /v1/games/:id), because an empty body declared as JSON is rejected.Binary bodies. A few endpoints take raw bytes instead of JSON:
Bundle uploads to the presigned
uploadUrl:Content-Type: application/zip.Game images (
POST /v1/games/:id/media):image/png,image/jpeg,image/giforimage/webp. The real type is detected from the file's bytes, not the header.
Body size. Every endpoint accepts at most 1 MB of body unless documented otherwise. Image uploads allow 5 MB. Bundles go straight to storage through the presigned URL, with a limit that depends on the runtime. See Errors & limits. - IDs vs slugs. Write and owner endpoints take the game's id (
:id). Public read endpoints take its slug (:slug).POST /v1/gamesreturns both.GET /v1/me/gameslists both for all your games.Timestamps are ISO 8601 strings in UTC. Date-only fields (such as daily earnings) are
YYYY-MM-DD.Unknown fields in a JSON body are ignored.
Responses
Successful responses are JSON objects, usually 200 OK. Creation endpoints return 201 Created (POST /v1/games, POST /v1/games/:id/versions, POST /v1/me/keys, POST /v1/dev/webhooks). Most action endpoints that have nothing else to return send { "ok": true }.
Money amounts in creator earnings responses are US dollars, in fields ending Usd. Coins (fields ending Coins, or named coins) are the platform's virtual currency. They are not real money and can't be cashed out.
Errors
Every error handled by the API uses the same envelope:
{
"error": {
"code": "cover_required",
"message": "Add a cover image before publishing your game.",
"details": {}
}
}Field | Meaning |
|---|---|
| Stable, machine-readable string. Branch on this. |
| Human-readable explanation. Can change wording at any time, so don't parse it. |
| Optional. Present on some errors, notably |
The HTTP status tells you the class of the error (400 bad input, 401 not authenticated, 403 not allowed, 404 not found, 409 conflict, 429 rate limited, 5xx server-side). One exception: requests to a path that doesn't exist at all return the web framework's default 404 body ({ "message", "error", "statusCode" }) instead of the envelope.
The complete list of codes, and every rate and size limit, is in Errors & limits.
Rate limits
All /v1/ requests share a limit of 100 requests per minute per IP address. When you exceed it you get 429 rate_limited with a Retry-After header (in seconds). Many endpoints also have their own tighter limits (uploads, key creation, tournament creation and so on). Those return 429 rate_limited without a Retry-After header. See Errors & limits for the full table.
Build in backoff: on 429, wait Retry-After seconds if present, or about a minute otherwise, then retry.
Pagination
Most list endpoints return a bounded list in one response (for example your games, reports and payouts return at most 200 items, newest first). No paging is needed.
The public catalogue (GET /v1/games) and game reviews (GET /v1/games/:slug/reviews) use cursor pagination:
curl "https://api.coolgptgames.com/v1/games?sort=new&limit=24"
# → { "games": [...], "nextCursor": "MjQ" }
curl "https://api.coolgptgames.com/v1/games?sort=new&limit=24&cursor=MjQ"
# → { "games": [...], "nextCursor": null } ← last pagePass
nextCursorback ascursorto get the next page.nullmeans you've reached the end.Treat cursors as opaque strings. Don't build them yourself.
GET /v1/gamesacceptslimitfrom 1 to 48 (default 24). Reviews come 20 per page.Paging reaches at most about 10,000 items deep. Narrow the query with filters instead of paging past that.
Idempotency
POST /v1/games (create a game) accepts an optional Idempotency-Key header (up to 128 characters). If you retry a create with the same key, you get the same draft back (200 with "idempotent": true) instead of a duplicate:
curl -X POST https://api.coolgptgames.com/v1/games \
-H "Authorization: Bearer $COOLGPTGAMES_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ci-build-4812" \
-d '{"title":"Space Miner","categorySlug":"arcade"}'No other endpoint takes an idempotency key. Many writes are naturally safe to repeat:
POST /v1/upload/completefor a version that already completed returns200with"idempotent": trueand the version's current state instead of processing it again.Remote config
PUTreplaces the whole config.Store items are upserted by
sku.Revoking an already-revoked key or cancelling an already-cancelled tournament does nothing new.
Reserving a version is not idempotent: every POST /v1/upload/init or POST /v1/games/:id/versions call reserves a new version number and counts against your hourly upload allowance.
Versioning
The API is versioned in the path (/v1/). There is no version header. Additive changes, such as new endpoints, new optional request fields and new response fields, can ship within v1 at any time, so ignore fields you don't recognise.
Endpoint index
"Auth" says what the caller must be:
Public: no credentials needed. - Key or session: an API key or a signed-in session. - Session only: interactive session; API keys get
403 session_required.Player page: called for you by the game player while someone plays. You don't call it directly.
"Scope" is the API-key scope the endpoint checks. A signed-in session is never scope-limited. A publish key also satisfies read. None checked means any valid key for your account works, whatever scopes it holds. See API keys & scopes.
Your games: create, upload, manage
Detailed in Games & uploads API and Packaging & publishing.
Method | Path | Auth | Scope |
|---|---|---|---|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Presigned URL (no API key) | n/a |
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Public | n/a |
Your dashboard data (/v1/me/*)
Documented in Creator dashboard endpoints below.
Method | Path | Auth | Scope |
|---|---|---|---|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session | None checked |
|
| Session only | n/a |
API keys
Detailed in API keys & scopes.
Method | Path | Auth | Scope |
|---|---|---|---|
|
| Session only | n/a |
|
| Session only | n/a |
|
| Session only | n/a |
Analytics and remote config
Detailed in Remote config & analytics.
Method | Path | Auth | Scope |
|---|---|---|---|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Public | n/a |
Webhooks
Detailed in Webhooks.
Method | Path | Auth | Scope |
|---|---|---|---|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
Tournaments
Detailed in Tournaments.
Method | Path | Auth | Scope |
|---|---|---|---|
|
| Key or session (session only when |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Public | n/a |
|
| Public | n/a |
|
| Public | n/a |
In-game economy
Detailed in In-game economy.
Method | Path | Auth | Scope |
|---|---|---|---|
|
| Key or session |
|
|
| Key or session |
|
|
| Key or session |
|
|
| Public | n/a |
Public game data
Useful for building your own pages, bots or leaderboards. No credentials needed.
Method | Path | Detailed in |
|---|---|---|
|
| This page (Pagination); Games & uploads API |
|
| Games & uploads API (your own unpublished game needs a session, or a key with |
|
| |
|
| |
|
| This page (Pagination) |
|
| Your public creator profile and published games |
|
| Your public creator progression |
Called by the player page (not for direct use)
While someone plays your game, the player page calls these on their behalf, in response to GameSDK calls your game makes. They're listed so you recognise them in traces and limit tables. Don't call them from your own code; use the GameSDK instead. See How games run and the GameSDK pages.
Method | Path | Triggered by |
|---|---|---|
|
| The player loading and running your game |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
various |
|
|
Creator dashboard endpoints
These endpoints back the creator dashboard. Each returns only your own data. The read endpoints need a key with read (or publish); preview and rollback need publish. A signed-in session can call all of them.
GET /v1/me/games
Lists your games, including drafts, newest-updated first (up to 200). Deleted games are excluded.
{
"games": [
{
"id": "7c1f…",
"slug": "space-miner-3fa2c1",
"title": "Space Miner",
"status": "published",
"playsTotal": 1824,
"ratingAvg": 4.3,
"publishedAt": "2026-09-02T18:11:04.000Z"
}
]
}status is one of draft, scanning, pending_review, published, rejected, delisted, dmca_removed.
The public GET /v1/games/:slug returns 404 for a game that isn't published. Use this endpoint and GET /v1/me/games/:id to see your drafts.
GET /v1/me/games/:id
The owner-only manage view for one game: metadata, every version with its moderation result, and per-day revenue.
{
"game": {
"id": "7c1f…", "slug": "space-miner-3fa2c1", "title": "Space Miner",
"description": "…", "instructions": "…",
"status": "published", "visibility": "full",
"category": { "slug": "arcade", "name": "Arcade" },
"aiGenerated": true, "aiDisclosure": "…",
"playsTotal": 1824, "ratingAvg": 4.3, "ratingCount": 51,
"currentVersionId": "b9e0…",
"publishedAt": "…", "createdAt": "…", "updatedAt": "…"
},
"versions": [
{
"id": "b9e0…", "versionNumber": 3, "status": "live",
"realtimeEnabled": false, "sizeBytes": 481223,
"runtime": "html5", "runtimeVersion": "1.0.0",
"createdAt": "…", "isCurrent": true,
"moderation": { "verdict": "auto_approve", "confidence": 0.97, "status": "complete", "error": null },
"review": null
}
],
"analytics": {
"earningsTotalUsd": 12.4,
"byDay": [{ "date": "2026-09-20", "validPlays": 88, "impressions": 140, "grossUsd": 0.61, "creatorShareUsd": 0.3 }],
"reportsOpen": 0
}
}visibilityislimited(reachable by direct link, not yet shown in public discovery) orfull.Version
statusisuploaded,scanning,passed,failedorlive.moderationis the automated scan result.verdictisauto_approve,auto_rejectorneeds_review, andstatusisqueued,running,completeorerror.reviewis the recorded decision,{ decision, reasonCodes, notes, at }withdecisioneitherapproveorreject, when one exists. Human and automated decisions both land here. An automated one hasnotesof"Approved by automated moderation."or"Rejected by automated moderation.". If a version was rejected, the reason codes are here.
Errors: 404 not_found if the game doesn't exist or was deleted; 403 forbidden if it isn't yours.
When you ship an update to a game that's already live, the game's status stays published while the new version is moderated. Watch the new version's entry in versions (by its id) to see the verdict: live means approved, failed rejected, passed waiting for a human.
GET /v1/me/games/:id/preview
Returns a private, short-lived play link for your game's build, including a build that isn't published yet. Use it to play-test before or during review.
Query | Meaning |
|---|---|
| Preview a specific version. Default: the current version, or else the newest upload. |
{ "playUrl": "https://…?t=…", "version": { "id": "…", "versionNumber": 4, "status": "scanning" } }The link carries an access ticket that expires after 15 minutes. Request a new one each time you need it.
Errors: 400 no_build (nothing uploaded yet), 400 runtime (runtime unavailable for preview), 403/404 as above.
POST /v1/me/games/:id/versions/:versionId/rollback
Makes an earlier version the live one again, instantly and without re-review. Only versions that were approved and published before (status live) qualify. A passed version, which is still waiting for a human reviewer, doesn't. The game becomes published with full visibility.
{ "ok": true, "currentVersionId": "a13c…", "versionNumber": 2 }Errors: 400 not_approved (that version was never approved and published), 409 game_removed (the game was delisted or DMCA-removed), 404 (unknown game or version, or a deleted game).
GET /v1/me/summary
Headline numbers for your account.
{
"playsTotal": 5120, "gamesTotal": 4, "gamesLive": 3, "gamesPending": 1, "reportsOpen": 0,
"lifetimeEarningsUsd": 41.2, "last30EarningsUsd": 9.85,
"availableUsd": 41.2, "pendingPayoutUsd": 0,
"payoutStatus": "none", "payoutMinimumUsd": 50, "creatorRevenueSharePct": 50
}GET /v1/me/earnings
Per-day earnings across all your games.
Query | Meaning |
|---|---|
| First date to include, |
| Last date to include, |
{
"totals": { "grossUsd": 82.4, "creatorShareUsd": 41.2, "validPlays": 5020, "impressions": 7310 },
"byDay": [{ "date": "2026-09-20", "grossUsd": 1.2, "creatorShareUsd": 0.6, "validPlays": 88, "impressions": 140 }],
"payoutMinimumUsd": 50
}GET /v1/me/payouts
Your payout history (up to 200, newest first) and your current unpaid balance.
{
"payouts": [{ "id": "…", "periodStart": "…", "periodEnd": "…", "amountUsd": 55.1, "status": "paid", "createdAt": "…", "paidAt": "…" }],
"availableUsd": 12.4,
"payoutStatus": "none",
"payoutMinimumUsd": 50
}Setting up where payouts go (POST /v1/me/connect/onboard) is session-only. Do it in the dashboard.
GET /v1/me/reports
Player reports filed against your games (up to 200, newest first). This is read-only: moderators resolve reports, and you can't dismiss them.
{
"reports": [{ "id": "…", "gameId": "…", "gameTitle": "Space Miner", "gameSlug": "space-miner-3fa2c1", "reasonCode": "broken", "details": "…", "status": "open", "createdAt": "…" }],
"openCount": 1
}GET /v1/me/creator
Your creator progression (creator level, XP and unlocked perks), recalculated on each call. Higher creator levels raise your hourly upload allowance (see Errors & limits).
GET /v1/auth/me
Returns the account the credentials belong to, as { "user": { … } }, or 401 unauthorized. Useful as a "does this key work?" check.
See also
API keys & scopes: creating keys and choosing scopes - Errors & limits: every error code and limit - Games & uploads API: the publishing flow in detail - Publisher SDK, CLI, MCP server: wrappers over this API