API Docs

API keys & scopes

AdminUpdated Sep 22, 2026

API keys & scopes

API keys let your servers, scripts, CI jobs, the CLI, the Publisher SDK and the MCP server act on your Cool GPT Games account without a browser. This page covers creating, listing and revoking keys, what each scope unlocks, what keys can never do, and how to handle keys safely.

Quick facts

Format

New keys start with ak_. Keys created before September 2026 start with arc_live_ and still work.

How to send

Authorization: Bearer <key> header only

Lifetime

No expiry. A key works until you revoke it.

Revocation

Takes effect on the very next request

Shown

Once, at creation. It can't be retrieved later.

Creation limit

10 new keys per hour per account

Who can manage keys

You, signed in to the dashboard. Keys can't create, list or revoke keys.

Creating a key

In the dashboard

  1. Sign in and open Dashboard → API keys.

  2. Enter a name that says where the key will live, for example github-actions or my-laptop.

  3. Choose scopes:

    • Leave Full access (*) ticked for a key that can do everything a key can do, or

    • Untick it and tick only the scopes the key needs (at least one).

  4. Select Create key and copy the key straight away. It's shown once. If you lose it, revoke the key and create a new one.

With the API

POST /v1/me/keys creates a key. It requires an interactive session (you signed in on the website). An API key calling it gets 403 session_required. In practice, use the dashboard.

Request body:

Field

Type

Required

Notes

name

string, 1–80 chars

Yes

A label for your own reference

scopes

array of scope names

No

Any of read, publish, tournaments, webhooks, config, analytics, economy. Omitted or empty means full access (*). * itself can't be sent; leave scopes out instead.

Response (201 Created):

{
  "id": "0f9c…",
  "name": "github-actions",
  "keyPrefix": "ak_aed3cbe11f59",
  "scopes": ["publish", "read"],
  "createdAt": "2026-09-21T10:02:11.000Z",
  "key": "ak_…",
  "availableScopes": ["read", "publish", "tournaments", "webhooks", "config", "analytics", "economy"]
}

key is the secret. This is the only response that ever contains it.

Errors:

Status

Code

Why

403

session_required

Called with an API key instead of a signed-in session

409

atlas_link_required

Your sign-in session predates the current sign-in system. Sign out, sign in again, then retry.

429

rate_limited

More than 10 keys created in the past hour

400

validation_error

Missing name, or an unknown scope name

503

atlas_unavailable

The key service is temporarily unreachable. Retry shortly.

Listing keys

GET /v1/me/keys (session only) returns every key on your account, newest first, including revoked ones. It never includes the secret.

{
  "keys": [
    {
      "id": "0f9c…",
      "name": "github-actions",
      "keyPrefix": "ak_aed3cbe11f59",
      "scopes": ["publish", "read"],
      "createdAt": "2026-09-21T10:02:11.000Z",
      "revokedAt": null,
      "lastUsedAt": null,
      "kind": "atlas"
    }
  ]
}
  • keyPrefix is the start of the key. Use it to match a key you hold to a row here.

  • revokedAt is set once a key is revoked.

  • lastUsedAt is always null at the moment, so the dashboard shows "never" for every key. Don't rely on it to find unused keys.

  • kind is always "atlas". It exists for compatibility and you can ignore it.

Revoking a key

In the dashboard, select Revoke next to the key. Through the API, DELETE /v1/me/keys/:id (session only) does the same and returns { "ok": true }.

  • Revocation is immediate. Anything using the key gets 401 unauthorized on its next request.

  • Revoking an already-revoked key succeeds and changes nothing.

  • An id that isn't one of your keys returns 404 not_found.

  • Revoked keys can't be restored. Create a new one.

Scopes

A key's scopes are fixed when it's created. To change them, create a new key and revoke the old one.

A signed-in session is never scope-limited. Scopes only restrict API keys.

What each scope unlocks

Some endpoints check a scope; the others accept any valid key. The table lists every endpoint that checks one.

Scope

Endpoints it unlocks

Typical use

publish

Games: POST /v1/games, POST /v1/games/:id, DELETE /v1/games/:id. Builds: POST /v1/upload/init, POST /v1/upload/complete, POST /v1/games/:id/versions. Images: POST /v1/games/:id/media, DELETE /v1/games/:id/media, POST /v1/games/:id/media/reorder. Preview and rollback: GET /v1/me/games/:id/preview, POST /v1/me/games/:id/versions/:versionId/rollback. Also satisfies read.

CI publishing, the CLI, the Publisher SDK

read

GET /v1/me/games, GET /v1/me/games/:id, GET /v1/me/summary, GET /v1/me/earnings, GET /v1/me/payouts, GET /v1/me/reports, GET /v1/me/creator, and the owner's view of an unpublished game through GET /v1/games/:slug

Read-only dashboards and reporting

analytics

GET /v1/dev/games/:id/analytics

Pull event, crash and player stats into your own tools

config

GET /v1/dev/games/:id/config, PUT /v1/dev/games/:id/config

Change remote config from a script or ops tool

webhooks

POST /v1/dev/webhooks, GET /v1/dev/webhooks, DELETE /v1/dev/webhooks/:id, POST /v1/dev/webhooks/:id/test, GET /v1/dev/webhooks/:id/deliveries

Manage webhook endpoints

tournaments

POST /v1/dev/tournaments (free tournaments only, see below), GET /v1/dev/tournaments, POST /v1/dev/tournaments/:id/cancel

Schedule tournaments from your server

economy

POST /v1/dev/games/:id/items, GET /v1/dev/games/:id/items, DELETE /v1/dev/games/:id/items/:sku

Manage your in-game store items

*

Everything a key can do

Personal keys on a trusted machine

A key without the required scope gets:

{ "error": { "code": "forbidden", "message": "This API key lacks the \"publish\" scope." } }

(HTTP 403.)

Two details to know:

  • publish covers read. A publishing key can read back what it just published (moderation status, versions) without also holding read. Nothing else implies another scope.

  • Unpublished games stay hidden from keys without read. GET /v1/games/:slug is public for published games. For your own draft, scanning, rejected or taken-down game, a key without read (or publish) gets 404 not_found, exactly as a stranger would.

Endpoints that accept any key

These don't check a scope. Any valid key on your account can call them, whatever scopes it holds:

  • GET /v1/auth/me (a handy "does this key work?" check)

  • Player-facing endpoints that act as the account holder and don't move coins, for example saves and social features. These are normally driven by the game player page, not by developer tooling.

What keys can never do

These routes reject every API key, including full-access (*) keys, with 403 session_required. Do them signed in on coolgptgames.com (account and key management live in the dashboard).

Route

Action

POST /v1/me/keys, GET /v1/me/keys, DELETE /v1/me/keys/:id

Create, list or revoke API keys

POST /v1/me/connect/onboard

Set up or change where payouts are sent

PATCH /v1/me/profile, POST /v1/me/avatar, POST /v1/me/banner

Edit your public profile

POST /v1/me/email

Change your email

DELETE /v1/me/account

Delete your account

PATCH /v1/me/settings, POST /v1/me/interests, POST /v1/me/age-eligibility

Account settings and preferences

POST /v1/daily/claim

Claim the daily coin reward

POST /v1/gifts/:handle

Gift coins to a friend

POST /v1/shop/buy

Buy from the platform cosmetics shop

POST /v1/season/claim/:tier

Claim a season reward tier

POST /v1/games/:id/purchase

Buy an in-game store item

POST /v1/dev/tournaments with prizePoolCoins above 0

Fund a tournament prize pool from your coins

So even a leaked full-access key can't lock you out, hide itself by revoking your other keys, mint fresh keys, redirect your payouts, or spend or move your coins. Free tournaments (no prize pool) can still be created with a tournaments key. A leaked key with publish can still act on your games, so revoke a leaked key immediately.

How key checks work

On every request that carries a key:

  1. The key's secret is verified.

  2. The key must belong to your account and must not be revoked.

  3. Your account must not be banned or deleted.

  4. If the endpoint needs a scope, the key must hold that scope or *.

A failure at steps 1–3 returns 401 unauthorized, exactly as if no key had been sent. A failure at step 4 returns 403 forbidden.

If the key-verification service is briefly unreachable, requests fail with 503 atlas_unavailable rather than 401. This is temporary: retry with backoff, and don't treat it as a bad key.

Best practices

Least privilege

  • Create one key per place it's used: one per CI pipeline, one per server, one per laptop. When one leaks, you revoke only that key.

  • Pick the narrowest scopes that work. For example:

Job

Scopes

CI that publishes builds (and checks the verdict)

publish

Reporting or dashboard script

read, analytics

Ops tool that tweaks remote config

config

Tournament scheduler

tournaments

Webhook provisioning

webhooks

Store management

economy

  • A publish key already covers read, so a CI job that publishes and then checks moderation status needs only publish.

Storing keys

  • Keep keys in a secret store: your CI's encrypted secrets, a cloud secret manager or a password manager. Never commit them to git, and never put them in a game bundle, a web page or client-side JavaScript. Everything in a game bundle is public.

  • Read the key from an environment variable at runtime (the CLI and MCP server use ARCADEY_API_KEY).

  • Keys never appear in API responses after creation, but they can leak through logs. Don't print request headers in CI output.

CI

A typical GitHub Actions setup:

# .github/workflows/publish.yml
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Check the key works
        env:
          COOLGPTGAMES_API_KEY: ${{ secrets.COOLGPTGAMES_API_KEY }}
        run: |
          curl -fsS https://api.coolgptgames.com/v1/auth/me \
            -H "Authorization: Bearer $COOLGPTGAMES_API_KEY" > /dev/null
  • Store the key as a repository or environment secret, not a plain variable.

  • Remember the shared limit of 100 requests per minute per IP, and the hourly upload allowance (see Errors & limits). CI runners that share IPs share that per-IP budget.

Rotation

Keys don't expire, so rotate them on your own schedule (for example every 90 days) and whenever someone with access leaves:

  1. Create the new key in the dashboard with the same scopes.

  2. Update the secret everywhere the old key is used.

  3. Confirm the new key works (GET /v1/auth/me).

  4. Revoke the old key.

Because each key is independent, the old and new keys can overlap for as long as you need.

If a key leaks

  1. Revoke it in Dashboard → API keys straight away. It stops working on the next request.

  2. Check your games in the dashboard for unexpected new versions, edits or deletions, and roll back if needed.

  3. Create a replacement key and update your secrets.

See also

Was this page helpful?