GameTok for Developers

Docs

Your game stays on your own HTTPS site. GameTok shows it in its feed, in a frame, and one script — bridge.js — lets it ask who's playing and report scores. Your server checks players with the GameTok API before trusting them.

How it fits together

Your game

Any web game (HTML5, Canvas, Phaser, Three.js, Unity WebGL, Godot…) on your own HTTPS address. It loads bridge.js and calls GameTok.*.

The GameTok player

The feed and game pages on gametok.co (and the GameTok app). It frames your game, pauses and resumes it, and answers GameTok.init() with the signed-in player.

Your server (optional)

Holds your secret API key. Checks player sessions and saves progress against the player's id.

Updates are instant: GameTok loads your hosted URL, so every time you deploy, players get the new version.

Quick start

  1. Sign in at games.gametok.co/dashboard, choose your username and accept the Developer Agreement.
  2. Add the bridge to your game's index.html:
    <script src="https://gametok.co/bridge.js"></script>
  3. Allow GameTok to frame your page (see below) and deploy.
  4. Try it as a draft: in the dashboard click + New Game, paste your URL and tick Save as a draft to test first. It opens in the private test player.
  5. Go live: click Go live in the test player or on the game's page. If the automatic checks pass, it's in the feed at gametok.co/game/<id>.

Allow GameTok to show your game

GameTok shows your game inside a frame on https://gametok.co (and the test player on https://games.gametok.co). Your page must not send X-Frame-Options: DENY or SAMEORIGIN. If you send a Content-Security-Policy, include:

Content-Security-Policy: frame-ancestors 'self' https://gametok.co https://games.gametok.co

Examples

HostWhere
Vercelvercel.json → "headers": [{ "source": "/(.*)", "headers": [{ "key": "Content-Security-Policy", "value": "frame-ancestors 'self' https://gametok.co https://games.gametok.co" }] }]
Netlify / Cloudflare Pages_headers file: /* then   Content-Security-Policy: frame-ancestors 'self' https://gametok.co https://games.gametok.co
GitHub PagesNothing to do — it doesn't block framing.
itch.ioPublish the game file URL (html-classic.itch.zone/…), not the store page: right-click the game → Open frame in new tab.

Players' browsers block http:// pages inside GameTok, so your game must be served over https://.

Publishing

Three ways, all ending in the same automatic checks:

Publishing again with the same title updates your game. Re-check a live game any time from its Checks tab.

Test mode

Drafts are private: they aren't in the feed, search or your public profile, and their GameTok page isn't public. You play them in the test player (games.gametok.co/sandbox/?game=<id>) — the real GameTok player in TEST mode:

Make drafts with a test key (gtk_test_…) — anything it publishes is a draft and it can never change a live game — or with the dashboard's Save as a draft. When it works, click Go live.

TestLive
API keygtk_test_…gtk_live_…
Publishing createsa private drafta live game (if checks pass)
Where it playsthe test playerthe GameTok feed and app
Player idst_…p_…
Sessions / matches it can verifytest onlylive only

Automatic checks

Every publish and Go live runs these. There's no manual review queue: the game goes live when every required check passes. You are still responsible for following the Developer Agreement.

CheckRequiredFails when
Served over HTTPSyesthe URL, or where it redirects, is http://
Game URL loadsyesit returns an HTTP error (404, 500…)
Can be shown inside GameTokyesX-Frame-Options or frame-ancestors blocks gametok.co
Is a web pageyesthe URL returns something other than HTML (e.g. a .zip)
Mobile viewport meta tagrecommendedno <meta name="viewport">
GameTok bridge scriptrecommendedno bridge.js tag

If GameTok can't reach your URL at all (timeout, your host blocks bots), the game still publishes with a warning — open the GameTok link to make sure it plays.

bridge.js reference

Load it from https://gametok.co/bridge.js (never a copy: it gets fixes). Outside GameTok it stays dormant and your game works normally. Promise-returning calls reject with an Error that has a .code (see Error codes).

CallWhat it does
GameTok.init()
→ { player, session, mode, expiresIn }
Who's playing. player is { id, name, avatar, guest }. Call it when the game starts. See Player identity.
GameTok.session()
→ { session, expiresIn }
A fresh session token (they last 15 minutes). Ask for one whenever you call your server.
GameTok.getPlayer()The player from the last init(), or null.
GameTok.on(event, fn)'pause' / 'resume' (another game is on screen or the app went to the background — stop timers and sound), 'mute' / 'unmute', 'restart'.
GameTok.submitScore(n)Report a score (whole number).
GameTok.gameOver(score?)The run ended; also reports session length to your analytics.
GameTok.recordEvent(name, data)A custom analytics event.

Player identity

Players are already signed in to GameTok, so your game doesn't need its own login.

const { player, session, mode } = await GameTok.init()
// player = { id: "p_3QmZ…", name: "Tolu", avatar: "https://…", guest: false }
// Send `session` to your server and verify it there before trusting `player`.
POSThttps://gametok-backend-267787411422.us-central1.run.app/api/developer/sessions/verify
Authorization: Bearer gtk_live_…        (gtk_test_… in the test player)
{ "session": "<session from the game>" }

→ 200 { "valid": true, "gameId": "tap-tap", "mode": "live",
        "player": { "id": "p_3QmZ…", "name": "Tolu", "guest": false }, "expiresAt": "…" }
→ 401 { "valid": false, "code": "SESSION_EXPIRED" | "SESSION_INVALID" }
→ 403 { "valid": false, "code": "WRONG_GAME" | "WRONG_MODE" }

Full server example: sample/server.js.

Server API reference

Base URL https://gametok-backend-267787411422.us-central1.run.app/api. Authenticate with Authorization: Bearer <API key>. Keep keys on your server.

EndpointWhat it does
POST/publishPublish (or update) a game. Body: url or html, title, description, orientation (portrait|landscape), category, draft. Returns gameId, url, status, checks, and testUrl for drafts.
GET/developer/gamesYour games with plays, unique players, checks and integration status.
POST/developer/games/:id/verifyRe-run the automatic checks.
POST/developer/games/:id/submitGo live (live key or dashboard). Runs the checks.
GET/developer/games/:id/analyticsPlays, unique players, average session, high score.
DELETE/developer/games/:idUnpublish and delete a game (test keys: drafts only).
POST/developer/sessions/verifyCheck a player session (see Player identity).

API keys

Create keys in Dashboard → Settings → API Keys. Each key is shown once; GameTok stores only a hash of the key. Revoke a key there at any time — it stops working immediately. Keys can't accept the Developer Agreement or create other keys; that needs you, signed in.

Error codes

CodeMeaning
AGREEMENT_REQUIREDAccept the current Developer Agreement in the dashboard.
GAME_URL_NOT_HTTPS · GAME_URL_UNREACHABLE · GAME_NOT_EMBEDDABLE · GAME_URL_NOT_HTML · GAME_HTML_INVALIDAn automatic check failed; error says how to fix it.
TEST_KEY_CANNOT_GO_LIVE · TEST_KEY_LIVE_GAMETest keys only work on drafts.
NOT_IN_GAMETOK · NO_RESPONSEGameTok.init() outside GameTok, or the player didn't answer.
SESSION_EXPIRED · SESSION_INVALID · WRONG_GAME · WRONG_MODESession verification failed; ask the game for a fresh GameTok.session().

Sample game

Tap Tap is a complete 40-line game using player identity, pause/resume and scores — view its source, copy it, and publish it as a draft to see the test player in action. sample/server.js is the matching Node server that verifies sessions.

Using an AI agent

Prefer to let an agent do it? Give Claude Code, Cursor or another coding agent this prompt from your game's folder. It follows skill.md and asks you for your API key.

Read https://games.gametok.co/skill.md and publish this game to GameTok. Ask me for my GameTok API key (games.gametok.co/dashboard → Settings → API Keys) before publishing.

Questions or problems: [email protected]