Gamearly API v1
Dashboard

Get started / Authentication

Authentication#

Every project has two API keys, created for you automatically. There is nothing to set up and nothing to choose — the only decision is which one goes where, and that decision is the whole of Gamearly's API security model.

Public key Private key
Token looks like gak_pub_… gak_prv_…
Belongs in your game build your server, CI, backend jobs
Can send events, run the account-link flow, read your project's public info everything the public key can, plus everything below
Cannot complete quests, grant or revoke entitlements, verify launch tokens, mark events trusted, import history, wipe data
Safe to ship to players yes never

Both keys are on your project dashboard, under the API integration section. You can reveal either one as often as you like, and regenerate either one independently.

Request headers

Header Value
X-Api-Key [YOUR_PROJECT_API_KEY]
Content-Type application/json

Authorization: ApiKey [YOUR_PROJECT_API_KEY] works identically if that suits your HTTP client better.

Why two keys#

A key inside a game build is not a secret. Anyone who owns your game can extract it from the binary, from memory, or from the network traffic — this is not a hypothetical, it is routine, and no amount of obfuscation changes it.

So the question is never "how do I hide the key in my build", it is "what happens when someone finds it". With a public key the answer is: they can send you fake telemetry about themselves. That is annoying and it is why trusted events exist, but it costs nobody anything real.

With a full-power key the answer is: they can complete quests to grant themselves rewards, and revoke other players' access to your game. That is why quests/complete_task, entitlements/* and launch_tokens/verify are private-key only. It is a deliberate boundary, not an oversight.

If you already shipped a build containing your key

The key your project had before this change is now your private key, and it still works exactly as it did — nothing has broken. But if you embedded it in a game build, that build is holding a key that can grant rewards.

Fix it in two steps: ship the public key in your next build, then regenerate the private key. Regenerating gives you a grace window (7 days by default), so your servers keep working while you roll out the new value.

Scopes#

Scopes are the mechanism underneath public/private. You never assign them — they follow from the key's kind — but they are what the API actually checks, and they are what a 403 names.

Scope Grants Public key
project:read Read your project's public information
link:write Start an account-linking session
link:read Poll a linking session's status
users:read Look up a linked user by partner_user_id
events:write Ingest events, timers, device identification, player tags and traits
events:read Counts, trends, funnels, event search, per-player lookups opt-in
quests:read List quests, read one, check completion private only
quests:write Complete a task and grant its reward private only
contests:read List and read contests private only
votes:read List and read referendums private only
leaderboard:read Read the project leaderboard and a player's position private only
entitlements:read Check whether a player owns your game private only
entitlements:write Revoke a player's entitlement private only
launch:verify Verify and consume a launch token private only
events:trusted Mark ingested events as trusted private only
events:import Bulk historical backfill with arbitrary timestamps private only
events:wipe Delete your project's test data private only

A private key holds every scope, including any added in future — you never have to regenerate it to pick up a new capability.

events:read on the public key#

This is the one capability you can add to your public key, from the key card on your dashboard. It is off by default, and you should leave it off unless your game genuinely needs to display its own analytics to players.

Turning it on means that anyone who extracts the key from your build can read: your event counts and trends across the whole project, your funnels, your event search results, your per-player event totals and leaderboards, and your player tags and traits. None of it is per-player-scoped — it is your project's analytics, and the key is public.

Reading a 403#

A scope failure returns 403 and tells you exactly what happened:

{
  "error": "insufficient_scope",
  "required": ["quests:write"],
  "granted": ["events:write", "link:read", "link:write", "project:read", "users:read"],
  "key_kind": "public"
}

key_kind: "public" on a route that needs a private scope means the call is coming from the wrong place — move it to your server rather than looking for a way to widen the key.

Regenerating a key#

Regenerating mints a replacement and leaves the old key working for a grace period, so you are never in a state where half your traffic is 401ing mid-deploy.

Default grace Allowed range
Private key 7 days 0–90 days
Public key 90 days 7–365 days

The public key's grace is long and its minimum cannot be waived, because you cannot update a build that is already on a player's machine. A player who has not launched your game in two months still has the old key in their install, and console certification alone can take weeks. Ninety days is the smallest window that reliably covers a real release cycle.

While a key is inside its grace window, every response it authenticates carries:

X-Gamearly-Key-Expires-At: 2026-11-16T09:00:00Z

Log it. A key that is about to stop working shows up in your own logs long before it shows up as an incident.

Errors#

Status error Meaning
401 missing_api_key No X-Api-Key header and no Authorization: ApiKey …
401 invalid_api_key No key matches, the key was revoked, or the caller's IP is not allowed
401 expired_api_key The key was real, but its regeneration grace period has ended
403 insufficient_scope Valid key, wrong kind for this route — see above
403 inactive_client The project is inactive on Gamearly

expired_api_key is deliberately distinct from invalid_api_key: it means you regenerated this key and something is still using the old value. Search your config for the previous token rather than opening a support ticket.

Revealing a key is repeatable

Both tokens are recoverable from your dashboard at any time. You will not be shown a "copy this now, you will never see it again" screen, so there is no reason to paste a Gamearly key into a notes app.