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
- Sign in at games.gametok.co/dashboard, choose your username and accept the Developer Agreement.
- Add the bridge to your game's
index.html:<script src="https://gametok.co/bridge.js"></script> - Allow GameTok to frame your page (see below) and deploy.
- 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.
- 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
| Host | Where |
|---|---|
| Vercel | vercel.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 Pages | Nothing to do — it doesn't block framing. |
| itch.io | Publish 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:
- Dashboard: + New Game → your hosted URL, or upload a single self-contained
index.html. - API:
POST /api/publishwith an API key (see reference). - AI agent: give Claude Code, Cursor or similar the prompt on the home page; it follows skill.md.
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:
GameTok.init()returns a test player (idt_…) and a test session.- Every message between your game and GameTok is shown in a log.
- An integration checklist ticks itself: bridge loaded, player requested, session verified by your server, score submitted.
- Buttons send pause/resume so you can check your game handles them.
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.
| Test | Live | |
|---|---|---|
| API key | gtk_test_… | gtk_live_… |
| Publishing creates | a private draft | a live game (if checks pass) |
| Where it plays | the test player | the GameTok feed and app |
| Player ids | t_… | p_… |
| Sessions / matches it can verify | test only | live 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.
| Check | Required | Fails when |
|---|---|---|
| Served over HTTPS | yes | the URL, or where it redirects, is http:// |
| Game URL loads | yes | it returns an HTTP error (404, 500…) |
| Can be shown inside GameTok | yes | X-Frame-Options or frame-ancestors blocks gametok.co |
| Is a web page | yes | the URL returns something other than HTML (e.g. a .zip) |
| Mobile viewport meta tag | recommended | no <meta name="viewport"> |
| GameTok bridge script | recommended | no 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).
| Call | What 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`.
player.idis a pseudonym for your game only. The same player always gets the same id in your game and a different one in every other game. Use it as your user id (progress, unlocks, saves).- Guests: players who aren't signed in get
guest: true, the name "Guest" and an id tied to their device. - Never trust the browser. Anyone can edit game code. Your server must check the session:
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.
| Endpoint | What it does |
|---|---|
POST/publish | Publish (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/games | Your games with plays, unique players, checks and integration status. |
POST/developer/games/:id/verify | Re-run the automatic checks. |
POST/developer/games/:id/submit | Go live (live key or dashboard). Runs the checks. |
GET/developer/games/:id/analytics | Plays, unique players, average session, high score. |
DELETE/developer/games/:id | Unpublish and delete a game (test keys: drafts only). |
POST/developer/sessions/verify | Check 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
| Code | Meaning |
|---|---|
AGREEMENT_REQUIRED | Accept the current Developer Agreement in the dashboard. |
GAME_URL_NOT_HTTPS · GAME_URL_UNREACHABLE · GAME_NOT_EMBEDDABLE · GAME_URL_NOT_HTML · GAME_HTML_INVALID | An automatic check failed; error says how to fix it. |
TEST_KEY_CANNOT_GO_LIVE · TEST_KEY_LIVE_GAME | Test keys only work on drafts. |
NOT_IN_GAMETOK · NO_RESPONSE | GameTok.init() outside GameTok, or the player didn't answer. |
SESSION_EXPIRED · SESSION_INVALID · WRONG_GAME · WRONG_MODE | Session 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]