Methods

Every game → platform call, its arguments, return value, and capability requirements.

These are the calls your game makes on the SDK. They come in two shapes:

  • Signals — fire-and-forget. Return Promise<void> that resolves immediately; the platform’s ack is not awaited. Validation errors surface as Promise rejections, so if you neither await nor .catch() them they become unhandled rejections. Examples: gameReady, gameStart, gameOver, updateScore, gameSaveState, updateMissionProgress, requestPause, logEvent.
  • Data-returning — return a Promise<T> that resolves with the platform’s reply. Can hit BRIDGE_TIMEOUT (default 30 s) or BRIDGE_ERROR. Always await them. Examples: init, purchaseItemWithGems, loadRewardedVideo, showRewardedVideo. Exception: showRewardedVideo and purchaseItemWithGems never time out — their reply arrives only after the player finishes the ad or purchase dialog, which routinely takes longer than 30 s.

Gated methods (those that require a capability) throw CAPABILITY_MISSING synchronously before anything reaches the wire if the capability wasn’t declared at init() time. See Capabilities for the full matrix and Error handling for GameeError codes.

For events the platform pushes to your game (pause, resume, start, …), see Events. For SDK-level helpers like hasPlatformContext and sdk.platform, see Utilities.

init#

Declares the capability set the game needs and resolves with the platform’s GameInitResponse (locale, country, save state, deep-link data, mission config).

init() is one-shot. It may only be called once per SDK instance; a second call rejects with INVALID_STATE. When you need a fresh instance — almost always in tests — use createSdk() instead of mutating state. This is the canonical reference for the rule; other pages link here.

const initData = await gamee.init({
  capabilities: ['saveState', 'rewardedAds'],
});

console.log(initData.locale, initData.country);
if (initData.saveState) restoreFrom(JSON.parse(initData.saveState));
if (initData.initData) handleDeepLink(JSON.parse(initData.initData));
FieldTypeRequiredNotes
capabilitiesCapability[]trueArray of one or more of: saveState, rewardedAds, logEvents, missions, gems, platformExtraLife. Unknown strings reject with VALIDATION.

Returns Promise<GameInitResponse>. The SDK checks that the platform returned a real object with all required fields — anything missing surfaces as BRIDGE_ERROR.

GameInitResponse#

This is the init data every game receives — the platform’s response to init(). Read it once from the resolved init promise; it’s also available afterwards as gamee.initResponse.

FieldTypeRequiredNotes
environment'production' | 'development'trueRuntime the platform advertises. Branch debug overlays / verbose logging off development.
platform'web' | 'mobile_web' | 'ios' | 'android'trueWhere the game is running. ios / android mean inside the native GAMEE webview; mobile_web is a plain mobile browser.
countrystringtrueISO 3166-1 alpha-2 country code (e.g. US, CZ).
localestringtrueNavigator-style locale (e.g. en-US, cs-CZ). Use for in-game translations.
gameContext'normal' | 'battle' | 'mission'trueWhat kind of run this is. missionData is only meaningful when this is 'mission'.
soundbooleantrueWhether audio is currently enabled. Mirror this into your audio engine on boot.
noAdsbooleanfalseWhen true, the player has paid for an ad-free experience. Don’t show interstitials. Rewarded ads remain opt-in.
saveStatestringfalseStringified JSON of whatever the game previously passed to gameSaveState. JSON.parse() before use.
initDatastringfalseStringified JSON deep-link payload the platform was opened with. JSON.parse() before use. Shape is game-specific.
missionDataMissionDatafalseMission config; present only when gameContext === 'mission'. See sub-table below.

MissionData#

FieldTypeRequiredNotes
idstringtrueMission identifier.
valuestringtrueMission target value (game decides how to interpret).
levelnumberfalseLevel number for the mission.
configstringfalseFree-form config string the game can interpret.
overallMissionOrdernumberfalsePosition of this mission in the broader mission stream.
difficulty'easy' | 'medium' | 'hard'falseMission difficulty tier.
difficultyDatastringfalseDifficulty-specific payload.

Both saveState and initData come over the wire as strings. The platform hands them back exactly as the game (or the deep-link origin) supplied them. The SDK does not parse them.

gameReady#

Tells the platform the first frame is rendered and the game is interactive. After this resolves the platform may immediately dispatch start / pause etc. — subscribe via gamee.on(...) first (Events → subscribe before gameReady()).

gamee.on('start', beginRun);
gamee.gameReady();

No arguments. Signal — returns Promise<void> that resolves immediately.

gameStart#

Signals that a new run is starting (often paired with the platform’s start event, called after the game has set up its run state).

gamee.gameStart();

No arguments. Signal.

gameOver#

Ends the current run. Send any state you want preserved for the next session in saveStateData; the SDK stringifies non-string values for you.

gamee.gameOver({
  saveStateData: { highScore: score, unlockedLevels: 3 },
  rewardIds: ['legendary-chest-12345'],
  metadata: { runDurationMs: 42_318, deathCause: 'spike' },
});
FieldTypeRequiredNotes
saveStateDataobject | stringfalsePass an object (auto-stringified by the SDK) or an already-stringified JSON string. Sent on the wire as state.
rewardIdsreadonly (string | number)[]falseIDs of in-game level/quest rewards the player completed during the run. Sent on the wire as-is (elements are never stringified) under the key completedGameLevelRewardIds. The platform stores these as integer ids — prefer numbers.
metadataobject | stringfalseFree-form end-of-run metadata. Pass an object (auto-stringified) or an already-stringified JSON string.

Signal. Calling with no arg (gamee.gameOver()) sends an empty object (data: {}) on the wire — never null. This matches legacy gamee-js behavior, which the Android host app depends on: its native handler throws on a null gameOver payload.

gameSaveState#

Persist arbitrary state outside of a gameOver. Use this for checkpoints, mid-run autosaves, or settings the player changed in-game.

await gamee.gameSaveState({ level: 3, coins: 420 });
FieldTypeRequiredNotes
dataobject | stringtruePass an object (auto-stringified by the SDK) or an already-stringified JSON string.

Capability: saveState. Calling without it throws CAPABILITY_MISSING.

Signal. The wire method is saveState (not gameSaveState) — relevant only if you’re inspecting the bridge traffic.

updateScore#

Push the player’s current score to the platform. Designed to be called frequently (per checkpoint or even per frame); the SDK doesn’t throttle.

Pass a number for the score-only shorthand, or an options object when you also want to send playTime, checksum, or metadata. Fields you don’t pass are omitted from the wire payload entirely.

// Score only (shorthand)
gamee.updateScore(100);

// Or with the full options object
gamee.updateScore({
  score,
  playTime: (performance.now() - startedAt) / 1000,
  checksum: 'mychecksum',
  metadata: { combo: 3 },
});

Argument: number | UpdateScoreOptions. Passing a number is sugar for { score: <number> }.

UpdateScoreOptions:

FieldTypeRequiredNotes
scorenumbertrueMust be a finite number. Truncated to an integer via Math.trunc() on the wire.
playTimenumberfalseSeconds since the run started. Must be finite and ≥ 0 if provided.
checksumstringfalseAnti-cheat token your game produces. Must be a non-empty string if provided.
metadataRecord<string, unknown>falseFree-form analytics blob. Sent as-is.

Signal. Validation failures reject the returned promise with VALIDATION.

updateMissionProgress#

Report progress on the current mission (gameContext === 'mission'). The platform uses this for progress UI; you still need to call gameOver when the run actually ends.

gamee.updateMissionProgress(42); // 42%
FieldTypeRequiredNotes
progressnumbertrueFinite number in [0, 100] (percent).

Capability: missions.

Signal.

requestPause#

The game is asking the platform to enter the paused state (e.g. the player opened an in-game menu). The platform will typically reply by dispatching the pause event — handle the pause logic in that event handler.

gamee.requestPause();

No arguments. Signal.

Don’t confuse this with the pause event, which is the platform telling your game to pause (incoming call, app backgrounded, …).

logEvent#

Custom analytics ping. The platform forwards these into its analytics pipeline.

Pass a string for the name-only shorthand, or an options object when you also want to send a value. If you omit value, the wire payload only carries the event name.

// Name only (shorthand)
gamee.logEvent('boss_defeated');

// Or with the full options object
gamee.logEvent({ name: 'boss_defeated', value: 'level_3' });

Argument: string | LogEventOptions. Passing a string is sugar for { name: <string> }.

LogEventOptions:

FieldTypeRequiredNotes
namestringtrueNon-empty string, ≤ 24 characters.
valuestringfalseString, ≤ 160 characters. Can be empty.

Capability: logEvents.

Signal. Both length caps are enforced locally and reject with VALIDATION.

purchaseItemWithGems#

Spend the player’s in-game gem currency on an item. Data-returning — await it.

game.freeze(); // stop the loop + audio yourself — no `pause` event is coming
try {
  const result = await gamee.purchaseItemWithGems({
    gemsCost: 50,
    itemName: 'extra_life',
  });
  if (result.success) grantExtraLife();
} finally {
  game.thaw(); // …and no `resume` event either
}

Argument (PurchaseDetails):

FieldTypeRequiredNotes
gemsCostnumbertrueFinite, ≥ 0.
itemNamestringtrueNon-empty string identifying the item.

Returns Promise<PurchaseResult>:

FieldTypeRequiredNotes
successbooleantruetrue if the transaction completed; false if the platform declined (e.g. insufficient gems).

Capability: gems. Can reject with BRIDGE_ERROR. Never times out — the platform replies only after the player completes or cancels the purchase flow (payment sheets and approval prompts can legitimately take minutes). For reacting to slow flows in your UI, see the Promise.race tip under showRewardedVideo.

No pause / resume around the purchase dialog. Same rule as the rewarded ad: the platform only stops its internal gameplay clock while the dialog is up and dispatches no events. Freeze the game before the call, thaw in finally. See player-paced calls → lifecycle.

loadRewardedVideo#

Prefetch a rewarded video ad. Call this when you anticipate showing one soon (e.g. right after a death) so the ad is ready when the player taps “watch”.

const { videoLoaded } = await gamee.loadRewardedVideo();
if (videoLoaded) ui.showWatchAdButton();

No arguments. Returns Promise<RewardedLoadResult>:

FieldTypeRequiredNotes
videoLoadedbooleantrueWhether an ad is ready to be shown.

Capability: rewardedAds. Can reject with BRIDGE_TIMEOUT / BRIDGE_ERROR.

showRewardedVideo#

Show the prefetched rewarded video. Resolves once the player either watched the ad through to the end (videoPlayed: true) or skipped/closed it (videoPlayed: false).

game.freeze(); // stop the loop + audio yourself — no `pause` event is coming
try {
  const { videoPlayed } = await gamee.showRewardedVideo();
  if (videoPlayed) grantReward();
} finally {
  game.thaw(); // …and no `resume` event either
}

No arguments. Returns Promise<RewardedResult>:

FieldTypeRequiredNotes
videoPlayedbooleantruetrue only if the player watched the ad fully. Reward accordingly.

Capability: rewardedAds. Can reject with BRIDGE_ERROR. Never times out — the platform replies only after the ad finishes, which routinely exceeds 30 s (matching legacy gamee-js, which waited indefinitely).

No pause / resume around the ad (or the purchase dialog)#

The platform does not dispatch pause when the ad opens or resume when it closes. What it does instead is internal: it stops its gameplay-time counter the moment showRewardedVideo arrives and restarts it when it replies with videoPlayed. Nothing reaches your event handlers. purchaseItemWithGems follows the exact same rule for its purchase dialog.

So the game is responsible for its own lifecycle around the call:

  1. Before calling — stop the game loop, silence audio, ignore input. Exactly what your pause handler does; reuse it.
  2. After the promise settles — resolve or reject — thaw. Put it in finally so a BRIDGE_ERROR can’t leave the game frozen.
  3. If you report playTime in updateScore, exclude the time the ad or dialog was up so your clock agrees with the platform’s.

A game that relies on a platform pause here keeps running behind the ad or dialog: the timer ticks down, enemies move, and the player comes back to a game-over screen.

Tip — UI pacing without racing the reward. If you want to react when the flow takes unusually long (show a hint, log telemetry), put the clock in your UI layer with Promise.race — but always keep honoring the SDK promise, so a late videoPlayed: true still grants the reward. Never treat “slow” as “failed”: the player may be mid-ad, or the app may have been backgrounded.

const result = gamee.showRewardedVideo();

const slow = new Promise((resolve) => setTimeout(() => resolve('slow'), 60_000));
if ((await Promise.race([result, slow])) === 'slow') {
  ui.showStillWaitingHint(); // purely cosmetic — the call below still decides
}

const { videoPlayed } = await result; // resolves whenever the player finishes
if (videoPlayed) grantReward();

The same pattern applies to purchaseItemWithGems, whose reply is also player-paced.

At a glance#

MethodArgsReturnsCapShape
init{ capabilities }GameInitResponsedata-returning
gameReadyvoidsignal
gameStartvoidsignal
gameOver{ saveStateData?, rewardIds?, metadata? }?voidsignal
gameSaveStatedata: object | stringvoidsaveStatesignal
updateScorenumber | { score, playTime?, checksum?, metadata? }voidsignal
updateMissionProgressprogress: number (0–100)voidmissionssignal
requestPausevoidsignal
logEventstring | { name, value? } (≤ 24 / ≤ 160 chars)voidlogEventssignal
purchaseItemWithGems{ gemsCost, itemName }{ success }gemsdata-returning
loadRewardedVideo{ videoLoaded: boolean }rewardedAdsdata-returning
showRewardedVideo{ videoPlayed: boolean }rewardedAdsdata-returning