Start Validated Run
horizon_start_runStarts a server-validated run for leaderboards requiring server-checked scores, issuing a single-use ticket and seed.
Instructions
Starts a server-checked run (Validated Actions): issues a single-use ticket with a server seed and starts the server's run timer. Use when: before a round whose score or earned currency must be checked by the server, and always for boards marked validatedOnly in horizon_list_leaderboards. Not for: normal boards where the client may write its own score (use horizon_submit_score) and reading balances (use horizon_get_state). Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Pass leaderboardKey to bind the ticket to a board (it must exist; 'default' is created on first use). Optionally declare the start context (gameVersion, contentVersion, simulationVersion, replayFormatVersion, contentDigest, initialStateBase64); the server binds it with its own start values (rule version, cloud save, balances, seed) into the run, and a sus run keeps it in its review package. Side effects: issues a new ticket per call and counts against the run limits per player and per account; unused tickets simply expire. Returns: {runId, ticket, seed, leaderboardKey, issuedAt, expiresAt, expiresInSeconds}. Seed the game's deterministic randomness with seed, record the input log, then send the result with horizon_submit_validated and the unchanged ticket before expiresAt. Errors: Errors carry a stable code in the body and the error result names it: 400 for a bad context field, 400 INITIAL_STATE_INVALID_ENCODING (initialState not standard base64), 413 INITIAL_STATE_TOO_LARGE (decoded initialState above the plan's evidenceMaxBytes), 401 SESSION_REQUIRED, 403 SESSION_FORBIDDEN, 404 PLAYER_NOT_FOUND or LEADERBOARD_NOT_FOUND, 429 RUN_RATE_LIMITED (per player and hour) or RUN_CAPACITY_REACHED (account per UTC hour; do not retry automatically, the wait can be an hour), 503 VALIDATED_ACTIONS_UNAVAILABLE (server has no ticket key). After 401 sign in again; after 403 SESSION_FORBIDDEN pass the userId that signed in. Needs HORIZON_API_KEY. Every failure returns an error result (isError) with the HTTP status and body: a 401 that horizon_test_connection also returns means HORIZON_API_KEY is wrong, 429 means the account's per-minute rate limit was reached (wait a minute, then retry).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| userId | Yes | Player user ID (UUID) from horizon_signup_* or horizon_signin_* | |
| gameVersion | No | Game build version, for example "1.4.2" (1 to 64 printable ASCII characters), stored in the run's start context. Optional | |
| sessionToken | Yes | accessToken from horizon_signin_email or horizon_signin_anonymous for this userId; sent as a Bearer session | |
| contentDigest | No | SHA-256 of the game content the run uses, 64 hex characters (sent in lower case). Optional | |
| contentVersion | No | Version of the game content (levels, balancing data) the run uses (1 to 64 printable ASCII characters), stored in the run's start context. Optional | |
| leaderboardKey | No | Board key to bind the ticket to, from horizon_list_leaderboards (1 to 64 characters: a-z, 0-9, _ and -). Omit for an unbound ticket (currency only runs, or choose the board at submit). | |
| simulationVersion | No | Version of the deterministic simulation that replays the input log (1 to 64 printable ASCII characters), stored in the run's start context. Optional | |
| initialStateBase64 | No | Bytes the simulation starts from as standard base64 (sent as context.initialState); decoded at most the plan's evidenceMaxBytes (32,768 bytes by default). Optional | |
| replayFormatVersion | No | Format version of the recorded input log (1 to 64 printable ASCII characters), stored in the run's start context. Optional |