allgame.js SDK

The SDK is a small dependency-free script (no build step, ES5 compatible) that wraps the REST API and the messaging with the play shell.

<script src="/sdk/allgame.js"></script>

AllGame.init(options) → Promise<Client>

Creates a client, loads the current player and tells the shell the game is ready.

OptionDescription
gameSlug. Detected automatically inside the shell (?game= or the /play/{slug}/files/ path).
tokenPlayer token agp_… for use outside the portal.
sessionPlay session token. Detected automatically (?session=).

Rejects with an error when the player is not logged in (code: 'unauthorized').

Client properties

PropertyDescription
player{ id, username, display_name, avatar_url, email, … }
entitlement{ unlimited, allowance_seconds, used_seconds, remaining_seconds, limit_reached, resets_in_seconds }
unlimitedBoolean shortcut.
pausedTrue while the shell has paused the game.
sessionCurrent play session token (null outside the shell).
remainingSeconds()Seconds left today, or null for Unlimited.

Save states: client.state

await ag.state.list();                       // [{ slot, label, version, size_bytes, updated_at }]
await ag.state.load(slot);                   // the saved object, or null
await ag.state.save(slot, object, { label, expectedVersion });   // { slot, version, size_bytes }
await ag.state.remove(slot);
  • object is any JSON-serialisable value up to 256 KB.
  • expectedVersion enables optimistic locking: if another device saved in between, the call rejects with code: 'version_conflict' and details.current_version.
  • Slots are 0 … save_slots-1 from the manifest.

Scores: client.scores

await ag.scores.submit(1234, { board: 'main', meta: { level: 7 } });
// → { accepted, score, board, rank: { rank, best } | null, personal_best }

await ag.scores.leaderboard({ board: 'main', period: 'week', limit: 25, offset: 0 });
// → { leaderboard: [{ rank, score, entries, last_played, player: { username, display_name, avatar_url, country } }], me: { rank, best } | null }

await ag.scores.mine();                      // this player's recent scores for the game

Scores are integers. Use board names (^[a-z0-9_-]{1,40}$) for separate rankings, e.g. per difficulty. The current play session is attached automatically so staff can audit suspicious entries.

Events: client.on(event, handler)

EventPayloadWhen
readyclientAfter init() resolved.
pause{ reason }Tab hidden (visibility), daily limit (limit_reached), connection problem (error). Stop timers and input.
resume{}Tab visible again.
limitentitlementThe player's 15 minutes are over. The shell covers the game with the upgrade screen; save your state now.
entitlemententitlementAfter every heartbeat (about every 30 s). Use it to show "time left" inside the game if you like.

client.off(event, handler) removes a handler.

Shell UI: client.ui

ag.ui.fullscreen();   // toggle fullscreen on the whole stage
ag.ui.exit();         // end the session and return to the game page
ag.ui.upgradeUrl();   // '/membership' — link to it from your own "time is up" screen

Low level: AllGame.request(method, path, body, { token })

Calls any /api/v1 endpoint and resolves with the data object, or rejects with { code, message, status, details }.

const me = await AllGame.request('GET', '/me');

Behaviour to design for

  1. The daily limit can end a session mid-level. Save progress often (every level, every minute).
  2. Players switch devices. Load the state at start, do not assume local storage.
  3. Scores are public. Only submit what should appear on a board.
  4. The shell may pause you at any time. Treat pause like a lost window focus.

Last updated October 11, 2026.