SDK overview
A small Promise-based bridge between your game and ZUQ Play.
On this page
Install and initialize
Use the platform-hosted script. window.ZUQ and window.ZUQSDK refer to the same SDK; version is "1.0". No npm package is required.
<script src="https://zuqplay.com/sdk/zuq-sdk-v1.js"></script>
<script>
async function start() {
const context = await ZUQ.init();
await ZUQ.loadingProgress(100);
await ZUQ.gameReady();
return context;
}
start().catch(console.error);
</script>First-party direct mode
Games opened directly at https://zuqplay.com/<slug>/ use the same Promise API without an iframe. HTTP/HTTPS localhost and 127.0.0.1 are accepted for tests. Other top-level origins reject. The path must identify an available catalog game. Load /assets/zuq-account.js for account support; signed-in requests use its getIdToken() Bearer token. Guests can initialize, report anonymous aggregate gameplay events and save on this device, but scores and challenge claims require a verified sign-in. Account changes invalidate the current play session. Existing first-party game saves keep their own registered account keys; SDK saves use a separate stable game-scoped snapshot.
Embedded games continue to use the source/origin-checked postMessage bridge. The parent holds the account token; it is never sent into the game iframe. The Inspector isolates leaderboard submissions as test-only and does not create live sessions, scores or rewards.
Leaderboards and weekly challenges
All boards are not authoritative: gameplay and scores are client-reported. Daily puzzles use midnight IST; other daily boards and Monday weekly boards use UTC. All-time boards retain accepted scores. Higher scores rank first unless a named board declares asc. Ties share a rank. Super admin controls plausibility limits, review, removal and board bans. Hidden profiles appear as Player to others.
await ZUQ.init({boards: [{board: "classic", sort: "desc"}]});
await ZUQ.gameplayStart();
// Play a full run, then report optional stars before stopping.
await ZUQ.track("stars", {value: 3});
await ZUQ.gameplayStop();
const result = await ZUQ.leaderboard.submit(120, {board: "classic"});
// result.status is accepted or flagged; flagged scores wait for review.
const top = await ZUQ.leaderboard.top({board: "classic", period: "weekly", friends: false});
const mine = await ZUQ.leaderboard.me({board: "classic", period: "all-time"});Default board is default; default period is weekly. Declare up to sixteen named boards using init({boards:[{board,sort}]}), catalog leaderboardBoards, or Super admin. Client declarations apply only for a signed-in player (guests may pass them; they are ignored) and cannot change an existing sort. Declarations are bounded and carry no authority; operators should configure boards before launch. Names use a lowercase initial letter followed by lowercase letters, digits, underscores or hyphens, at most forty characters. Only Super admin may change established sort and bounds.
gameplayStart returns a server-issued session and start time for a signed-in player. The SDK retains the nonce privately. Each run may submit once per board within six hours. Do not restart the session before submitting. The server measures duration, caps submissions at sixty/hour per account, limits starts and events, and flags scores beyond configured max score, max score per second, minimum duration or statistical outlier bounds. A flagged score does not count toward ranks or score challenges until approved.
Weekly challenges are free; ZQ points have no cash value. Score progress uses the maximum accepted score. Plays count completed sessions meeting the default board minimum duration. Stars are integer values from zero to three per run, reported before stop. Streak is the longest sequence of UTC play days within the challenge window. Progress must occur after the challenge starts and before it ends. Claim from the player UI before the end; badges and the existing points ledger update once atomically. Ended challenges are archived. Read /fair-play/ for review and appeals.
Lifecycle
Call loadingProgress as assets load, gameReady when the start screen is ready, gameplayStart when playing, and gameplayStop on pause/end. happyMoment is an optional milestone event. Avoid reporting these on every frame.
Transport and errors
Every method returns a Promise. Calls use the wrapper bridge for embedded games or the same-origin API for first-party pages on https://zuqplay.com (localhost is allowed for tests); init must complete before other methods. Requests are limited to 65,536 UTF-8 bytes of serialized args, with an overall wrapper guard. Circular/non-JSON data and unavailable wrappers reject. A missing reply rejects after 15 seconds. The wrapper accepts at most 240 messages per minute per attached frame; excess calls may time out. Both ends validate the message source and origin. Handle rejections without blocking the game.
try {
await ZUQ.gameplayStart();
} catch (error) {
console.warn("ZUQ event unavailable", error.message);
}Game-room chat
First-party web games announce the current room in the same window as the overlay. Use a code of 1–64 letters, digits, underscores or hyphens. Dispatch code: null when leaving. The optional URL is informational; the server keys rooms by the catalog game and code and does not trust a supplied URL. Embedded developer games use await ZUQ.room(code) and await ZUQ.room(null), which cross the validated SDK bridge.
window.dispatchEvent(new CustomEvent('zuq:room', {
detail: {code: 'ROOM_A', url: '/your-game/?room=ROOM_A'}
}));
// On leave:
window.dispatchEvent(new CustomEvent('zuq:room', {detail: {code: null}}));The overlay joins POST /api/community/room/join with {game, code}, heartbeats once a minute, and leaves on a null code or page-unload beacon. Membership expires after 30 minutes without a heartbeat. The Room tab and member list are available only to eligible signed-in adults who accepted the social rules, and never in Family games. Filtered text and quick phrases expire after 24 hours; an empty room closes after two hours. Report and Block are available for members and messages. Add friend always requires acceptance. Optional audio uses a four-person mesh when staff enable Voice calls. Calls are never recorded; call metadata is retained for 90 days and included in account export/delete.
Next steps
Every SDK method, parameters, returns, examples and errors →