Skip to Content
DocsTikTok interaction

Build a TikTok game in Combos

Build Gift Arena: a small game where the streamer fights a boss and viewers supply energy, healing, and damage. You will get a complete project, a local gift simulator, a Combos publishing path, and the handoff required for real TikTok gifts. Uses Combos SDK 1.1.0.

Play the demo · Download the complete project

Real TikTok interaction currently has no available activation path. You can complete local development, simulation, and Combos publishing now. Publishing a post does not enable real gifts. The later integration materials and LIVE acceptance steps prepare for a future platform activation process; they are not an application flow you can complete today.

1. Declare gifts as game effects

Start with the rules, before writing connection code. In this example the player starts with 70 HP and 40 energy; the boss has 100 HP. An attack costs 10 energy, deals 10 damage, and triggers 8 damage in return if the boss survives. Viewers help through these three effects:

In-game giftStable instructionEffect for count = "1"Effect for count = "3"
Batterygift_battery+20 energy+60 energy
Healgift_heal+15 HP+45 HP
Flashgift_flash−10 boss HP−30 boss HP
// rules.js — this game's contract export const GIFT_CATALOG = Object.freeze({ gift_battery: { target: 'energy', perCount: 20, max: 100 }, gift_heal: { target: 'hp', perCount: 15, max: 100 }, gift_flash: { target: 'bossHp', perCount: -10, max: 100 }, });

This declaration lives in your game code. It is neither an SDK registration call nor a TikTok gift catalog. Battery/Heal/Flash are this example’s effect names, not real TikTok gift names or IDs. Do not assume a Rose or any price automatically maps to one of them.

Set these policies before integration: this game accepts integer counts 1–1000, caps HP/energy at 100 and boss HP at 0, and applies effects without consuming a player turn. A capped effect is successful even if the value cannot increase further. New commands after victory/defeat return false; start a new round to accept more. These are example game rules, not platform limits. For your game, explicitly design stacking, cooldowns, round transitions and expensive effects, and give the same rules to the person configuring the mapping.

2. Understand the game–platform relationship

Viewer → TikTok gift mapping → Combos → SDK onCommand → game effect → boolean result → Combos → TikTok acknowledgment.

OwnerResponsibility
Your gameDeclare supported instructions; render and commit effects; deduplicate; return the actual outcome
Combos host and SDKLogin and launch binding; session renewal; command transport, heartbeat, reconnection and result delivery
Combos / TikTok integration contactRegister the intended game entry and authorized accounts; configure the launch path and actual gift-to-instruction mapping

One mapped interaction might produce instruction: "gift_flash", count: "3". Your game applies 30 damage. count is the mapped command quantity, not a coin price or necessarily the number of gifts. Confirm the mapping’s quantity rule, including combos, during registration. The game does not read launchData, sign TikTok requests, create a WebSocket, or implement webhooks itself.

3. Implement the command contract

type TTLiveCommand = { messageId: string; instruction: string; count: string; timestamp: string; };
FieldWhat to do
messageIdTreat as an opaque deduplication key. The same message must not apply the effect twice
instructionMatch the stable string in your own catalog; reject unsupported instructions
countDecimal integer string. Validate first; only convert to Number after bounding it safely
timestampSource command time as a string. It is not an identity, deduplication key or ordering guarantee

The public command has no viewer ID, nickname or real gift ID. Do not build a per-viewer leaderboard from fields that this API does not supply.

Return true after the effect is committed, false for a known rejection, and throw if the outcome cannot be confirmed, such as a storage failure. An unknown outcome stays unacknowledged and may be retried. Catching every error and returning true loses gifts; returning false after an uncertain partial effect reports an unproven failure.

The SDK can resend pending results within a document. Your game must handle reloads too. The example saves game state and the message result in one IndexedDB transaction, waits for commit, then returns the boolean. A duplicate returns the saved boolean. A new round preserves receipts. The live save is scoped to the Combos account/game and separated from practice.

Read connection status

getTTLiveClient() returns one client per game document. getLiveStatus() checks it; onStatusChange() immediately emits current status, then changes. Status contains state, reason, action, and confirmedAtMs (last confirmed start/heartbeat in milliseconds; 0 means unknown).

  • connecting: starting. connected: interaction session confirmed.
  • recovering: let the SDK reconnect. unknown: no current confirmation; it does not mean the broadcast ended.
  • ended: the interaction session ended. Follow action: wait, none, or relaunch_game. For relaunch_game, reopen this game from LIVE Studio; do not restart the broadcast just because of a connection issue.

4. Run the complete project

Prepare and launch

Download and extract the ZIP. You need a current browser and Python 3 for the local static server; Node and npm are not required. Keep the extracted tiktok-arena folder intact:

cd tiktok-arena python3 -m http.server 8080 --bind 127.0.0.1

Open http://127.0.0.1:8080/ and choose Start practice. Do not double-click index.html: JavaScript modules need an HTTP origin. The online demo works without installing anything. The game’s language selector supports the same ten languages as this site.

FileRead or change it for…
rules.jsGift declaration, combat rules, count validation and deduplication
storage.jsAtomic game-state and receipt storage
connection.jsSDK capability checks, login, connection and cancellation
game.jsThe shared live/practice handler and UI
index.html, style.css, draw.js, i18n.jsLayout, canvas artwork and ten-language UI

Three reproducible demos

Start a new round before each of the first two rows. The recovery row continues the second demo without resetting. The initial values are HP 70, energy 40, boss HP 100. Every gift button creates a new message; Repeat last message reuses its ID.

DemoActionsExpected result
Single giftsCount 1; click Battery, Heal, FlashEnergy 60, HP 85, boss HP 90; each result true
Stacked gifts and replayCount 3; click Flash, then RepeatBoss HP 70 after both deliveries; second result true, duplicate: true
Recovery and rejectionRefresh after the previous demo, Start practice, Repeat; then Unknown instructionBoss HP still 70; unknown instruction returns false, state unchanged

Also try count 0, 1.5, 1001, and 9007199254740993: no effect and false. Test a win with a fresh round and Flash ×10, then send a new gift: it is rejected until a new round. Play with Attack and Charge to exercise normal combat. The Last delivery panel shows the input, result and final values. These are synthetic local commands; they never buy gifts or send TikTok ACKs.

5. Connect the same game inside Combos

Keep the supplied connection.js and game.js when publishing. Combos injects window.combos; do not install an imaginary npm SDK or add a second SDK script. The Connect Combos LIVE button does the following:

  1. Calls init() and checks the getTTLiveSession capability and client getter. That capability name is not a public method to call.
  2. Runs checkSession() and, if needed, login() from the button action. Cancellation stops the flow; successful login continues the same action.
  3. Uses getUserInfo() to scope the local save. The IDs are not credentials or server-side authorization proof.
  4. Subscribes to status, then calls getTTLiveClient().connect({ onCommand }) with the same handler used in practice.
  5. Keeps Disconnect / cancel usable while connection retries are pending. Cancellation or leaving the document unsubscribes and calls disconnect().

The core handler below is already implemented in the download; the full version also refreshes the UI. store.update() is the transaction in storage.js, not an SDK API:

import { executeCommand } from './rules.js'; // `store` is the account/game-scoped store opened by prepareStore(). function commandHandler(store) { return async (command) => { const { result } = await store.update((saved) => executeCommand(saved, command), ); return result; // State + receipt committed; no catch-and-return-false. }; }

connect() can stay pending while retrying; a resolved promise alone does not prove a real gift worked. Practice controls are hidden in LIVE mode. Verify both the visible effect and its execution result in a registered session.

6. Publish this project to Combos

Install the official Combos CLI . In the demo, click Save cover PNG. Place the resulting cover.png next to the tiktok-arena folder. From that parent folder, run:

combos --version combos account login combos post create --dir ./tiktok-arena --title 'Gift Arena' --cover ./cover.png --platform pc --screen-orientation landscape --allow-recommend=false combos post get

Complete the browser login using the intended publishing account. Open the returned share link and test the game inside its Combos player. Preserve the generated combos.json binding; update the same post from this directory with:

combos post update --dir ./tiktok-arena --platform pc

This sample is a static PC landscape game. The upload directory must contain index.html at its root and all relative assets. Publishing does not enable TT. A normal share link without the registered LIVE Studio launch context can run practice but cannot manufacture a real interaction session. See H5 publishing for the full publishing workflow.

7. Prepare materials for future integration

There is currently no available activation entry or confirmed onboarding process for real TikTok interaction. Game/account registration and real-gift mapping must wait for platform guidance; neither the SDK nor the CLI provides a public self-service registration API. Prepare the following materials for that future process. This is a preparation checklist, not an open application:

SupplyRequired detail
GamePublished Combos share URL, bound Post/project ID, game name and PC landscape target
Test accessThe intended test/streamer account, via the approved onboarding channel; never a password or session token
Effect catalogThe three instruction strings, per-count effects, 1–1000 quantity rule, caps and behavior after round end
Mapping requestWhich approved TikTok gift maps to each instruction, the quantity/combination rule and expected game result
Acceptance planSingle gift, combo, redelivery/recovery and ended-session cases below

Ask the contact to confirm the exact registered launch entry, game/account eligibility and completed gift mapping before testing. The actual TikTok gift IDs, names and prices must come from that configured catalog. For an agreed Flash ×3 mapping, the game should receive:

{ "instruction": "gift_flash", "count": "3" }

Do not put TikTok secrets, CAS tokens or manually constructed launchData in the game. Those are handled by the platform. If registration is not complete, you have a published Combos game and a working simulator; real TikTok acceptance is still pending.

8. Validate real LIVE after activation becomes available

These steps become executable only after the platform provides activation and confirms the game entry, eligible account, and gift mapping. At present, complete the local simulator and Combos publication checks above; do not treat them as real LIVE acceptance.

  1. Use the approved account and open the registered game entry in TikTok LIVE Studio. In the game, connect Combos LIVE and confirm connected.
  2. With the test participant’s agreement, trigger one configured test interaction. Record messageId, instruction/count, the before/after values, and the returned result. Ask the integration contact to confirm the platform received the corresponding ACK. Do not include credentials or viewer personal data in the record.
  3. Repeat for the configured combo quantity. Confirm count × effect, caps, and no duplicated effect on redelivery. Compare with the local demos above.
  4. Exercise a temporary network interruption and recovery; the same known command must not apply twice. Refresh within the supported host flow and confirm state/receipt recovery; if the host asks for relaunch, follow it.
  5. End the interaction and check ended / relaunch_game. Test cancel while connecting and leaving the game. Stale commands must not create another effect.

Browser storage protects this example only within the same browser/origin/account/game. It does not provide cross-device recovery or a trusted economy. Do not clear it during LIVE. At 10,000 receipts the sample stops accepting new commands rather than evicting old results. For persistent rewards or production scale, commit the effect and receipt in your own authoritative backend and define retention from confirmed outcomes.

When it does not work

SymptomNext action
unsupported_hostOpen the game in the supported Combos player; check init() capabilities and SDK availability
login_cancelled / missing_profileSign in using the intended account, then retry the connection
tt_not_launched, ended, or relaunch_gameConfirm registration/account eligibility and reopen the registered game from LIVE Studio
Connected, but no effectCheck the gift mapping, exact instruction/count and round state; ask the contact to trace the message ID
false resultCheck unknown instructions, invalid counts or an ended round; this is a known game rejection
invalid_save, receipt_capacity, storage_blocked, or operation_failedStop LIVE testing; inspect browser storage availability and console locally. Preserve receipts, diagnose before restarting, and do not convert uncertainty into a successful ACK

SDK reference · Account and localization

Last updated on