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.
| Option | Description |
|---|---|
game | Slug. Detected automatically inside the shell (?game= or the /play/{slug}/files/ path). |
token | Player token agp_… for use outside the portal. |
session | Play session token. Detected automatically (?session=). |
Rejects with an error when the player is not logged in (code: 'unauthorized').
Client properties
| Property | Description |
|---|---|
player | { id, username, display_name, avatar_url, email, … } |
entitlement | { unlimited, allowance_seconds, used_seconds, remaining_seconds, limit_reached, resets_in_seconds } |
unlimited | Boolean shortcut. |
paused | True while the shell has paused the game. |
session | Current 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);
objectis any JSON-serialisable value up to 256 KB.expectedVersionenables optimistic locking: if another device saved in between, the call rejects withcode: 'version_conflict'anddetails.current_version.- Slots are
0 … save_slots-1from 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)
| Event | Payload | When |
|---|---|---|
ready | client | After init() resolved. |
pause | { reason } | Tab hidden (visibility), daily limit (limit_reached), connection problem (error). Stop timers and input. |
resume | {} | Tab visible again. |
limit | entitlement | The player's 15 minutes are over. The shell covers the game with the upgrade screen; save your state now. |
entitlement | entitlement | After 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
- The daily limit can end a session mid-level. Save progress often (every level, every minute).
- Players switch devices. Load the state at start, do not assume local storage.
- Scores are public. Only submit what should appear on a board.
- The shell may pause you at any time. Treat
pauselike a lost window focus.
Last updated October 11, 2026.