horizOn MCP Server
OfficialServer Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| HORIZON_API_KEY | Yes | Your horizOn API key. Required for live API tools. Get one at horizon.pm | |
| HORIZON_BASE_URL | No | API base URL. Defaults to https://horizon.pm | https://horizon.pm |
| HORIZON_ACCOUNT_API_KEY | No | Your horizOn Account Key for admin tools. Optional. Admin tools only register when this is set. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| prompts | {
"listChanged": true
} |
| resources | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| horizon_test_connectionA | Checks that HORIZON_API_KEY and HORIZON_BASE_URL reach the horizOn API by fetching the app's remote configs; takes no input. Use when: first during setup, and whenever other tools fail, to tell a configuration problem from a problem of the call itself. Not for: checking a player's session (use horizon_check_auth) or reading config values for the game (use horizon_get_all_remote_configs). Side effects: None (read only). Returns: {success: true, data} where data holds the app's remote configs; success means key and URL work. Errors: A network error means HORIZON_BASE_URL is wrong or unreachable: check the URL (default https://horizon.pm). 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). |
| horizon_signup_anonymousA | Creates a new anonymous (guest) player account that needs only a display name and returns its anonymousToken. Use when: a player starts without email, for example on first launch of a game with guest play. Not for: players who sign up with email and password (use horizon_signup_email) or returning guests (use horizon_signin_anonymous with the stored anonymousToken). Side effects: creates one new player account per call; calling it again creates another account, it never finds an existing one. Sign-up starts no session. Returns: {userId, username, isAnonymous: true, anonymousToken, createdAt}. Store anonymousToken on the device: it is the only way back into this account. Then call horizon_signin_anonymous to get the accessToken that session tools need. Errors: 400 for an invalid displayName: fix the name and retry. 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). |
| horizon_signup_emailA | Creates a new player account with email, password and display name; the account starts unverified and without a session. Use when: a new player registers with email so the account can be recovered on other devices. Not for: existing accounts (use horizon_signin_email) and guest play without email (use horizon_signup_anonymous). Side effects: creates one player account and sends the verification email. It does not sign in. Returns: the new user with userId and isVerified: false. After the player verified the email address, call horizon_signin_email to get the accessToken. Errors: 409 when the email already belongs to an account: sign in with horizon_signin_email instead. 400 for an invalid email, a password outside 8 to 128 characters or a common password, or a bad name: fix the value and retry. 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). |
| horizon_signin_emailA | Signs in an existing email account with email and password and starts a player session (accessToken). Use when: a registered, verified player logs in, before any tool that needs sessionToken (submit score, cloud save, gift code redeem, profile, validated runs). Not for: guest accounts (use horizon_signin_anonymous), new players (use horizon_signup_email) or checking an existing token (use horizon_check_auth). Side effects: creates a new session on every call; older sessions stay valid. Returns: {userId, username, email, accessToken, authStatus, message}. Pass userId and accessToken (as sessionToken) to the session tools; the token stays valid for one hour after its last use. Errors: 401 for a wrong password or unknown email: ask the player to check the credentials. 403 (NOT_VERIFIED) for an unverified email: the player must confirm the verification email first. 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). |
| horizon_signin_anonymousA | Signs in an anonymous (guest) account with its stored anonymousToken and starts a player session (accessToken). Use when: a returning guest opens the game, or right after horizon_signup_anonymous, before any tool that needs sessionToken. Not for: email accounts (use horizon_signin_email) or creating a guest (use horizon_signup_anonymous). Requires: the anonymousToken returned by horizon_signup_anonymous for this account. Side effects: creates a new session on every call; older sessions stay valid. Returns: {userId, username, accessToken, authStatus, message}. Pass userId and accessToken (as sessionToken) to the session tools; the token stays valid for one hour after its last use. Errors: 404 for an unknown anonymousToken: the account is lost, create a new one with horizon_signup_anonymous. 429 also comes from the per-token limit (5 attempts per minute) and the per-IP limit (30 per minute): wait a minute. 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). |
| horizon_check_authA | Checks whether a player's session token (accessToken) is still valid for the given user. Use when: before a session tool when the token may have expired, or when a game resumes, to decide whether the player must sign in again. Not for: testing the API key or base URL (use horizon_test_connection) or getting a new token (use horizon_signin_email or horizon_signin_anonymous). Requires: userId and the accessToken from horizon_signin_email or horizon_signin_anonymous. Side effects: a valid check refreshes the session's one hour idle timeout; nothing else changes. Returns: {userId, isAuthenticated, authStatus, message}. An invalid or expired token is not an HTTP error: isAuthenticated is false, so sign in again with horizon_signin_*. Errors: 400 for a malformed userId or token: pass the values from the sign-in result. 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). |
| horizon_list_leaderboardsA | Lists the leaderboard boards of this API key with their keys, sort order and whether they accept only validated runs. Use when: first, when a game has several boards (weekly, per level) or before submitting, to learn the leaderboardKey values and whether a board is validatedOnly. Not for: reading entries (use horizon_get_leaderboard_top, horizon_get_user_rank or horizon_get_leaderboard_around). Side effects: None (read only). Returns: {boards: [{key, name, sortOrder, isActive, scoreCount, validatedOnly}], totalElements}. Pass a key as leaderboardKey to the submit, top, rank and around tools; without it they use the default board. validatedOnly true means scores are accepted only through horizon_start_run plus horizon_submit_validated. Errors: 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). |
| horizon_submit_scoreA | Submits a player's score to a leaderboard; the board keeps only each player's best score (higher on DESC boards, lower on ASC boards). Use when: a round ends on a normal board. Then call horizon_get_user_rank to show the new position. Not for: boards marked validatedOnly in horizon_list_leaderboards (use horizon_start_run and horizon_submit_validated) and reading scores (use horizon_get_leaderboard_top). Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: replaces the player's entry only when the new score beats it; a worse or equal score, or the same call again, changes nothing. Returns: {success: true} (also when the score did not beat the best one). Errors: 403 VALIDATED_SUBMIT_REQUIRED on a validatedOnly board, nothing written: switch to horizon_start_run and horizon_submit_validated, do not retry. 403 PLAYER_BANNED when a moderator banned the player from the board: final, do not retry. 404 for an unknown leaderboardKey: list valid keys with horizon_list_leaderboards. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_leaderboard_topA | Returns the top entries of a leaderboard from position 1, each with the player's profile, plus the requesting player's own entry when they are outside the list. Use when: a game shows a global top list (top 10, top 100). Not for: one player's position alone (use horizon_get_user_rank) or the players around them (use horizon_get_leaderboard_around). Requires: a userId from horizon_signup_* or horizon_signin_* (used to append the player's own entry); no session token. Side effects: None (read only). Returns: {entries: [{position, username, score, profile}]} in board order. When the userId is not among them, the player's own entry with the real position is added at the end. An empty board returns an empty list. profile is {avatarId, frameId, badges} (IDs from the cosmetics catalog; null or [] when not set, set with horizon_set_profile). Errors: 404 for an unknown leaderboardKey: list valid keys with horizon_list_leaderboards. 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). |
| horizon_get_user_rankA | Returns one player's own position, score and profile on a leaderboard. Use when: after horizon_submit_score, or to show 'your rank' in the game. Not for: a list of entries (use horizon_get_leaderboard_top or horizon_get_leaderboard_around). Requires: a userId from horizon_signup_* or horizon_signin_*; no session token. Side effects: None (read only). Returns: {position, username, score, profile}. profile is {avatarId, frameId, badges} (IDs from the cosmetics catalog; null or [] when not set, set with horizon_set_profile). Errors: 404 when the player has no score on this board yet (submit one first) or the leaderboardKey is unknown (check horizon_list_leaderboards). 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). |
| horizon_get_leaderboard_aroundA | Returns the leaderboard entries directly above and below a player's own position, including the player, each with profile. Use when: a game shows 'you and your rivals' instead of the global top. Not for: the global top list (use horizon_get_leaderboard_top) or the position alone (use horizon_get_user_rank). Requires: a userId from horizon_signup_* or horizon_signin_*; no session token. Side effects: None (read only). Returns: {entries: [{position, username, score, profile}]} in board order. profile is {avatarId, frameId, badges} (IDs from the cosmetics catalog; null or [] when not set, set with horizon_set_profile). Errors: 404 for an unknown leaderboardKey: list valid keys with horizon_list_leaderboards. 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). |
| horizon_save_cloud_dataA | Stores a player's save game as one string (usually JSON) on the server, replacing the player's previous save. Use when: the game saves progress so it survives reinstalls and can be loaded on another device. Pass expectedRevision (the revision from horizon_load_cloud_data or the last save) so a save from another device is never overwritten silently. Not for: reading the save (use horizon_load_cloud_data) or server-owned currency that players must not edit (use Validated Actions: horizon_submit_validated and 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. Side effects: overwrites the player's single save slot; the old save is gone. With expectedRevision it only writes while the save is still at that revision. Saving the same data again changes nothing. Returns: {success: true, dataSizeBytes, revision}. revision is the new revision: pass it as expectedRevision to the next save. Errors: 409 (only with expectedRevision) when another device saved first: nothing was written, load the current save and revision, decide, then save again. 403 when the data exceeds the tier limit (defaults FREE 1 KB, BASIC 5 KB, PRO 20 KB, ENTERPRISE 250 KB): shrink the save or upgrade. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_load_cloud_dataA | Reads a player's save game that was stored with horizon_save_cloud_data. Use when: the game starts or the player switches devices and needs the saved progress. Not for: writing (use horizon_save_cloud_data) or balances of server-owned values (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. Side effects: None (read only). Returns: {found, saveData, revision}. found false with saveData null means the player never saved: this is normal on first start, so initialize default data. revision is the save's server revision (0 = empty slot, 1 after the first save): pass it as expectedRevision to horizon_save_cloud_data. revision null means the server sent none (unknown state, for example a self-hosted simpleServer), not an empty slot. Errors: 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_remote_configA | Reads one remote config value by key (a feature flag or balance value set in the horizOn dashboard) as a string. Use when: the game needs a single value, for example to check one feature flag. Not for: loading many values at start (use horizon_get_all_remote_configs, one request instead of many). Side effects: None (read only). Returns: {configKey, configValue, found}. Values are always strings: parse numbers and booleans yourself. An unknown key is not an error: found is false and configValue null, so fall back to a default. Errors: 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). |
| horizon_get_all_remote_configsA | Reads every remote config value of the app in one call as a key to string map. Use when: at game start, to cache all flags and balance values at once. Not for: a single value (use horizon_get_remote_config) or checking the API key only (use horizon_test_connection). Side effects: None (read only). Returns: {configs, total}, where configs maps each key to its string value; an app without configs returns an empty map and total 0. Errors: 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). |
| horizon_get_localizationA | Reads one translated string by key in one language (default: the app's default language). Use when: the game needs a single text, for example a dynamic message. Not for: loading the UI texts at start (use horizon_get_all_localizations) or finding out which languages exist (use horizon_get_localization_languages). Side effects: None (read only). Returns: {localizationKey, value, language, found}. A missing key or translation is not an error: found is false and value null, so show a fallback text. Errors: 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). |
| horizon_get_all_localizationsA | Reads all translated strings of one language as a key to text map (default: the app's default language). Use when: at game start or on a language switch, to load every UI text at once. Not for: a single key (use horizon_get_localization). Side effects: None (read only). Returns: {translations, language, total}; translations is empty (total 0) when the language has no strings. Errors: 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). |
| horizon_get_localization_languagesA | Lists the languages that have at least one translation for the app. Use when: before horizon_get_localization or horizon_get_all_localizations, to pick a valid lang or build a language menu. Not for: the texts themselves (use horizon_get_all_localizations). Side effects: None (read only). Returns: {languages, total}, where languages holds ISO 639-1 codes such as 'en' or 'de'; empty when the app has no translations. Errors: 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). |
| horizon_get_newsA | Lists the published in-game news of the app (announcements, patch notes) created in the horizOn dashboard, newest first. Use when: a game shows a news feed or a message of the day, optionally filtered to the player's language. Not for: configuration values (use horizon_get_remote_config) or UI translations (use horizon_get_localization). Side effects: None (read only). Returns: an array of {id, title, message, releaseDate, languageCode} with only published entries whose release date has passed; an empty array means there is no news. Without languageCode, entries of all languages are returned. Errors: 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). |
| horizon_validate_gift_codeA | Checks whether a gift code is currently valid for a player without consuming or preparing it. Use when: showing an early validity message; horizon_prepare_gift_code prepares a consumable V2 identity. Not for: claiming rewards (use horizon_redeem_gift_code with an already persisted intent). Requires: userId from horizon_signup_* or horizon_signin_*; no session token. Side effects: None (read only). Returns: {valid}; a validity check reserves nothing and cannot recover an uncertain redemption. Errors: 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). |
| horizon_prepare_gift_codeA | Reads a compact V2 campaign identity and exact current sequence without reserving or consuming a redemption. Use when: starting an explicit new action after prior outcomes are resolved; persist the returned intent before horizon_redeem_gift_code. Not for: recovering an uncertain action; retry its saved original intent with horizon_redeem_gift_code instead. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: None (read only); no server intent or reservation is stored. Returns: {valid,intent}; intent is null when invalid, otherwise exactly protocolVersion,projectScope,userId,code,campaignId,expectedCount,configRevision. Counts/revisions are exact Int64 decimal strings; projectScope binds the local host/project without exposing credentials. Persist all seven fields, never the session token. Errors: 409 UPGRADE_REQUIRED closes V1; MIGRATION_REQUIRED needs operator migration; COUNT_AHEAD, CAMPAIGN_CHANGED, COUNTER_EXHAUSTED and STATE_CONFLICT require explicit reconciliation. Keep the original intent on every uncertain outcome, never prepare or advance automatically. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_redeem_gift_codeA | Consumes the original persisted V2 campaign/player sequence once and returns current authoritative state on replay. Use when: an explicit consume or retry of the exact seven-field intent previously returned by horizon_prepare_gift_code and durably saved. Not for: preparing or advancing a counter after uncertainty; horizon_validate_gift_code alone does not produce an intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Fresh redemption and rewards commit atomically. Identical intent retries share one logical sequence slot. No automatic retry or preparation occurs. Returns: {success,campaignId,count,configRevision,alreadyApplied,replayed,giftData,grantedValues,grantedUnlocks,playerValues}. Fresh count is expectedCount+1 at the original revision. Replay has current count/state, null giftData and empty grants. Replace balances from playerValues; never add rewards locally. Remove only this exact confirmed intent; malformed replies leave it unresolved. Errors: 409 UPGRADE_REQUIRED closes V1; MIGRATION_REQUIRED needs operator migration; COUNT_AHEAD, CAMPAIGN_CHANGED, COUNTER_EXHAUSTED and STATE_CONFLICT require explicit reconciliation. Keep the original intent on every uncertain outcome, never prepare or advance automatically. V1 arguments return local UPGRADE_REQUIRED without HTTP; mixed forms return INVALID_REQUEST. A changed local host/project returns PROJECT_SCOPE_CHANGED. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_profileA | Returns a player's profile (avatar, frame, badges), the player's unlocks and the cosmetics catalog of the API key with an available flag per entry. Use when: before horizon_set_profile, to show the selection screen and learn which IDs the player may pick. Not for: changing the profile (use horizon_set_profile) or showing other players' profiles (leaderboard entries already carry them). Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: None (read only). Returns: {userId, profile: {avatarId, frameId, badges}, unlocks, cosmetics: [{id, type, locked, available}], limits: {maxBadges, maxUnlocks}}. available true means this player may select the entry. Errors: 401 SESSION_REQUIRED for a missing or expired session: sign in again. 403 SESSION_FORBIDDEN for a session of another user: pass the userId that signed in. 404 PLAYER_NOT_FOUND for an unknown userId. 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). |
| horizon_set_profileA | Sets a player's avatar, frame and displayed badges. This REPLACES THE WHOLE PROFILE: an omitted, null or empty slot is cleared. Use when: the player confirms a new look. Pass the current values from horizon_get_profile for the slots that should stay. Not for: reading the profile or the catalog (use horizon_get_profile). Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Every ID must be in the API key's catalog, have the type of its slot and be free or unlocked for the player; at most 3 distinct badges. Side effects: overwrites all three slots; the same call again changes nothing more. The profile shows up in leaderboard entries. Returns: the same body as horizon_get_profile after the change. Errors: The error result names the stable code. 400 INVALID_BADGES, INVALID_COSMETIC_ID, COSMETIC_NOT_FOUND or COSMETIC_TYPE_MISMATCH: pick IDs of the right type from horizon_get_profile. 403 COSMETIC_LOCKED: the cosmetic is locked and the player has not unlocked it (unlocks come from gift code grants). 401 SESSION_REQUIRED for a missing or expired session: sign in again. 403 SESSION_FORBIDDEN for a session of another user: pass the userId that signed in. 404 PLAYER_NOT_FOUND for an unknown userId. 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). |
| horizon_get_player_valuesA | Returns the player's server-owned balances, UTC daily counters and operation replay window. Use when: displaying balances or recovering a timed-out horizon_adjust_player_value operation. Not for: changing balances (use horizon_adjust_player_value or horizon_purchase_player_value_offer). Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: May lazily initialize missing configured values once; does not change existing balances. Returns: {userId, definitionVersion, revision, day, values, operationWindow: {serverTime, oldestAcceptedAt}} Errors: 409 STATE_CONFLICT: refresh state and retry the SAME operation ID and payload. OPERATION_CONFLICT: do not reuse an ID for a different action. OPERATION_EXPIRED: reconcile state/history; never silently generate another ID. INSUFFICIENT_BALANCE, MAX_BALANCE_REACHED or DAILY_LIMIT_REACHED leaves the whole operation unapplied. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_player_value_offersA | Returns configured purchase offers and the player's value definitions for the current project. Use when: preparing a purchase with horizon_purchase_player_value_offer. Not for: buying an offer (use horizon_purchase_player_value_offer). Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: May lazily initialize missing configured values once; does not change existing balances. Returns: {definitionVersion, serverTime, definitions, offers: [{key, name, active, costs, rewards, purchasesPerDay}]} Errors: 409 STATE_CONFLICT: refresh state and retry the SAME operation ID and payload. OPERATION_CONFLICT: do not reuse an ID for a different action. OPERATION_EXPIRED: reconcile state/history; never silently generate another ID. INSUFFICIENT_BALANCE, MAX_BALANCE_REACHED or DAILY_LIMIT_REACHED leaves the whole operation unapplied. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_purchase_player_value_offerA | Purchases one configured offer with atomic costs and value/item rewards, retaining only a minimal public duplicate guard. Use when: a player confirms an offer returned by horizon_get_player_value_offers. Not for: choosing arbitrary costs or rewards; only the server's configured offer is accepted. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Persist operationId before the first request. Side effects: Debits and credits together once. Same ID and body replay without another debit; no automatic retries or new IDs. Returns: Current state with operation:{operationId,replayed,alreadyApplied,applied,items}. Fresh success contains committed deltas and new item references; replay has empty applied/items. Never add an old reward delta locally. Errors: 409 STATE_CONFLICT: refresh state and retry the SAME operation ID and payload. OPERATION_CONFLICT: do not reuse an ID for a different action. OPERATION_EXPIRED: reconcile state/history; never silently generate another ID. INSUFFICIENT_BALANCE, MAX_BALANCE_REACHED or DAILY_LIMIT_REACHED leaves the whole operation unapplied. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_adjust_player_valueA | Adjusts one player value within explicitly enabled project rules and per-call and daily limits. Use when: the configured game permits a direct value adjustment; use horizon_get_player_values to inspect the result. Not for: trusted rewards or arbitrary grants; client adjustment is disabled by default. Purchases use horizon_purchase_player_value_offer. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. This definition must enable adjustment. Side effects: Applies the signed amount once per operationId. The minimal guard binds the original reason/payload hash without copying the reason. Never creates an ID or retries automatically. Returns: Current state with replayed/alreadyApplied. Fresh success includes its delta; replay has empty applied/items. Errors: ADJUST_NOT_ALLOWED or ADJUST_ABOVE_LIMIT: change the game flow or project rules. 409 STATE_CONFLICT: refresh state and retry the SAME operation ID and payload. OPERATION_CONFLICT: do not reuse an ID for a different action. OPERATION_EXPIRED: reconcile state/history; never silently generate another ID. INSUFFICIENT_BALANCE, MAX_BALANCE_REACHED or DAILY_LIMIT_REACHED leaves the whole operation unapplied. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_start_runA | 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, balances, seed) into the run, and a sus run keeps it in its review package. The server never reads the cloud save; send the start state a replay needs as initialStateBase64. 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). |
| horizon_submit_validatedA | Submits the result of a run started with horizon_start_run; the server checks ticket and server-only rules before it writes the score and earned values. Use when: a validated run ends: send the ticket, the claimed score (and stage) and the SHA-256 commitment of the input log. Not for: runs without a ticket (use horizon_submit_score on normal boards) 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. The ticket from horizon_start_run and exactly one of inputLogHash (a ready SHA-256), inputLogBase64 (raw log bytes, hashed locally) or inputLog (UTF-8 text, hashed locally); the log itself is never sent. score is required when a board is targeted (the ticket's board, or leaderboardKey) and ignored otherwise. Send earned ({key, amount}[]) only when the API key's rules define values: positive amounts earn, negative amounts spend. Side effects: consumes the ticket (single use, also when rejected); an accepted run writes the score (best score kept) and changes the balances of earned values. The same ticket cannot be submitted twice. Returns: {accepted, runId, leaderboardKey, score, bestScore, isNewHighScore, rank, durationSeconds, state, evidence, sus} plus inputLogHash (the hash that was sent). sus is true when the run was accepted but crossed a soft threshold of the rules (the flag names stay on the server); the run counts normally and the server keeps a review package. Rejected runs are never sus; an older server without the field reads as false. state is the player's server-owned values after the run: {day, values: [{key, balance, earnedToday, dailyCap, requested, credited}]}, every value key of the rules sorted by key; requested (amount sent) and credited (amount applied) appear only for the keys in earned. credited < requested on a positive amount means dailyCap or maxBalance clamped it (not an error). For a spend, credited is either requested or 0 (a concurrent run of the same player used the balance first): grant a purchase only when credited == requested. state is null when the rules define no values or the state write failed. evidence is null, or {required: true, runId, uploadBefore, maxBytes} when the server asks for the input log (the run became the player's row and is flagged or lands in the board's evidence top N, or the run is sus): upload exactly the logged bytes with horizon_upload_evidence before uploadBefore (24 hours); a log that was only hashed via inputLogHash must be kept by the caller. Errors: Rejections carry a stable code (never the rule values) and the error result names it: 400 SCORE_REQUIRED (board targeted without score) or PLAYER_NAME_REQUIRED; 401 SESSION_REQUIRED; 403 SESSION_FORBIDDEN, PLAYER_BANNED (banned from the board by a moderator, final; the ticket is not used) or SCORE_LIMIT_REACHED (ticket used up); 404 PLAYER_NOT_FOUND or LEADERBOARD_NOT_FOUND; 422 TICKET_INVALID, TICKET_EXPIRED, TICKET_FOREIGN, TICKET_CONSUMED, LEADERBOARD_MISMATCH; 422 rule codes STAGE_REQUIRED, STAGE_UNKNOWN, SCORE_ABOVE_MAX, SCORE_BELOW_MIN, STAGE_SCORE_ABOVE_MAX, STAGE_SCORE_BELOW_MIN, DURATION_TOO_SHORT, SCORE_RATE_TOO_HIGH and value codes UNKNOWN_VALUE_KEY (key not defined in the rules' values, also when the rules define none), DUPLICATE_VALUE_KEY, EARNED_ABOVE_MAX (above maxPerRun), EARNED_BELOW_MIN (below minPerRun), INSUFFICIENT_BALANCE (spend larger than the balance) (the ticket is consumed, start a new run); 503 VALIDATED_ACTIONS_UNAVAILABLE. After a 422 rule or value code or SCORE_LIMIT_REACHED the ticket is spent; after 401, 404, 429 or 503 the same ticket may be sent again. Local errors (no request sent, ticket kept): INVALID_INPUT_LOG_HASH when the hash input was missing, doubled or malformed, DUPLICATE_VALUE_KEY when earned lists a key twice. 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). |
| horizon_get_stateA | Returns the player's server-owned values (Validated Actions): balance, today's earnings and daily cap per value key, such as currency or loot counters. Use when: the game shows the wallet or checks whether a spend is possible before starting a run. Not for: changing balances: nothing writes a balance directly, only accepted runs through horizon_submit_validated with earned. Also not for the save game (use horizon_load_cloud_data). Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: None (read only). Returns: {userId, day, values: [{key, balance, earnedToday, dailyCap}]}: every value key defined in the API key's rules, sorted by key (balance 0 when never earned); values is empty when the rules define no values. day is the current UTC day, earnedToday the positive credit on that day (0 after midnight UTC), dailyCap null without a daily cap; the other value rules stay hidden. Games may mirror the values into cloud save for offline display but must never send them back. Errors: The error result names the stable code: 401 SESSION_REQUIRED (sign in again), 403 SESSION_FORBIDDEN (pass the userId that signed in), 404 PLAYER_NOT_FOUND, 429 without code (account request limit, wait). 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). |
| horizon_upload_evidenceA | Uploads the input log of a validated run after horizon_submit_validated answered with evidence.required = true (evidence review). Use when: only when a submit result carries evidence.required: true, before evidence.uploadBefore (24 hours). Not for: runs without an evidence request (the server answers 404 EVIDENCE_NOT_REQUESTED) and sending the log with the submit (the submit takes only its hash). Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. The runId from the submit result and the raw input log as exactly one of inputLogBase64 (raw bytes as base64) or inputLog (UTF-8 text). Its SHA-256 must equal the inputLogHash sent with the run, so pass the same bytes or text that were hashed at submit; at most evidence.maxBytes (32,768 bytes by default). Side effects: stores the log for the developer's review; one upload per run (a second one gets 409). Returns: {runId, status: "UPLOADED", bytes} plus inputLogHash (the SHA-256 of the uploaded bytes, for comparison with the submit). Errors: Errors carry a stable code in the body and the error result names it: 400 EVIDENCE_INVALID_ENCODING (not standard base64), 401 SESSION_REQUIRED, 403 SESSION_FORBIDDEN, 404 EVIDENCE_NOT_REQUESTED (no request for this run and player; also for a run of another player), 409 EVIDENCE_ALREADY_UPLOADED, 410 EVIDENCE_EXPIRED (window passed, slot freed), 413 EVIDENCE_TOO_LARGE (decoded log above maxBytes), 422 EVIDENCE_HASH_MISMATCH (SHA-256 of the log differs from the run's inputLogHash; the request stays open, retry with the correct bytes until uploadBefore), 429 without code (account request limit). Only 422 and network errors are worth a retry; the others are final. Local error (no request sent): INVALID_INPUT_LOG when the log input was missing, doubled, empty or not base64. 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). |
| horizon_get_statisticsA | Reads a player's statistics snapshot and server operation window. Use when: explicit loading, reconnect recovery or checking an uncertain batch before retrying its original ID. Not for: writing counters; use horizon_update_statistics with the original durable ID. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: None (read only). Returns: {userId, definitionVersion, definitions, revision, values, operationWindow, operationId?, replayed?, newlyUnlocked}. definitions null means unchanged since definitionVersion; keep the cached definitions. Errors: 401 SESSION_REQUIRED: sign in again; 403 SESSION_FORBIDDEN: use the matching player. 409 OPERATION_CONFLICT means the ID was already used for a different payload. 410 OPERATION_EXPIRED rejects an expired/evicted unknown ID. Never replace an uncertain ID automatically. 422 UNKNOWN_STATISTIC/UPDATE_ABOVE_LIMIT/VALUE_OVERFLOW rejects the whole batch. 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). |
| horizon_get_statistics_definitionsA | Reads the project's statistics catalog conditionally by version. Use when: showing counter labels, modes, reset policies and optional report bounds. Not for: loading player counter values; use horizon_get_statistics. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: None (read only). Returns: {definitionVersion, definitions}; definitions null means unchanged, an empty array means an empty catalog. Errors: 401 SESSION_REQUIRED: sign in again; 403 SESSION_FORBIDDEN: use the matching player. 409 OPERATION_CONFLICT means the ID was already used for a different payload. 410 OPERATION_EXPIRED rejects an expired/evicted unknown ID. Never replace an uncertain ID automatically. 422 UNKNOWN_STATISTIC/UPDATE_ABOVE_LIMIT/VALUE_OVERFLOW rejects the whole batch. 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). |
| horizon_update_statisticsA | Applies one explicit atomic session batch with a caller-persisted operation ID. Use when: reporting completed session counters, or retrying exactly the same durable ID and payload after an uncertain timeout. Not for: automatically generating another ID for a failed/unknown outcome, or one HTTP call per counter. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Persist the original operationId and unchanged updates before sending. ID is <13-digit Unix milliseconds>:; use the snapshot server operation time for clock alignment. Side effects: Updates all counters atomically. A retained same-ID same-payload receipt replays; changed payload conflicts. Eight receipts and a persistent eviction floor can reject delayed out-of-order unknown IDs even within 24 hours; nothing is rebooked. Returns: The current statistics snapshot with operationId and replayed. Errors: 401 SESSION_REQUIRED: sign in again; 403 SESSION_FORBIDDEN: use the matching player. 409 OPERATION_CONFLICT means the ID was already used for a different payload. 410 OPERATION_EXPIRED rejects an expired/evicted unknown ID. Never replace an uncertain ID automatically. 422 UNKNOWN_STATISTIC/UPDATE_ABOVE_LIMIT/VALUE_OVERFLOW rejects the whole batch. 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). |
| horizon_get_achievementsA | Reads visible achievement definitions and permanent completion bits. Use when: loading progress or refreshing after newlyUnlocked statistics or realtime invalidation. Not for: changing balances or revealing locked hidden achievements. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: None (read only). Does not grant anything. Returns: {userId,revision,definitionVersion,definitions,progress,limits,serverTime}. definitions=null retains matching cached definitions; [] clears them. Scope caches to host/project/player/session. Compact progress has rewardState=complete, nullable unknown unlockedAt and no pendingReward/inboxEntryId copy. Legacy unsettled originals remain visible until verified cold settlement. Errors: 409 STATE_CONFLICT: reconcile and retry the same key. ACHIEVEMENT_NOT_MANUAL: report the configured statistic instead. MIGRATION_REQUIRED preserves legacy reward originals for the verified cold operator; it never authorizes a replacement reward or Inbox delivery. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_unlock_achievementA | Unlocks one configured manual achievement once for the authenticated player. Use when: an explicit game event meets this manual achievement's rule. Not for: statistic achievements or client-chosen reward amounts. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Commits the permanent completion bit and configured Player Values rewards in one transaction, immediately. No new Inbox or reward-history copy. Repeating the same key never grants twice, including after archival. This tool does not retry automatically. Returns: {achievements,newlyUnlocked,replayed,deliveryResults:[]}. On success explicitly refresh Player Values to replace the balance cache; do not claim or add a reward locally. Errors: 409 STATE_CONFLICT: reconcile and retry the same key. ACHIEVEMENT_NOT_MANUAL: report the configured statistic instead. MIGRATION_REQUIRED preserves legacy reward originals for the verified cold operator; it never authorizes a replacement reward or Inbox delivery. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_deliver_achievement_rewardsA | Reads compatibility reward status for up to eight original achievement keys. Use when: diagnosing an older unsettled reward without changing its original identity. Not for: delivering or claiming new achievement rewards; new unlocks credit immediately. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read-only compatibility POST; creates no reward, delivery or grant. Legacy pending status returns MIGRATION_REQUIRED for verified cold settlement. Returns: {achievements,results:[{key,state,inboxEntryId,code}]}. New compact achievements are complete with no Inbox ID; never invent a new action from a legacy pending result. Errors: 409 STATE_CONFLICT: reconcile and retry the same key. ACHIEVEMENT_NOT_MANUAL: report the configured statistic instead. MIGRATION_REQUIRED preserves legacy reward originals for the verified cold operator; it never authorizes a replacement reward or Inbox delivery. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_friendsA | Reads friends, incoming/outgoing requests, blocks and current limits. Use when: opening a social screen or reconciling an uncertain mutation. Not for: polling for online presence or applying old snapshots to a new session. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: None (read only). Returns: Complete {userId,revision,friendCode,friends,incoming,outgoing,blocked,limits,serverTime} snapshot. Replace the matching host/project/player cache. lastActiveAt is the latest retained login, null when unknown; it is not online presence. Errors: 409 REVISION_CONFLICT or an uncertain response: get a new snapshot and reconcile intent, never silently replace expectedRevision and repeat. 404 FRIEND_REQUEST_NOT_FOUND means this request was removed or replaced; do not act on a newer ID. INBOX_FULL rejects the entire send/accept. Friend/request/block capacity limits reject additions while existing data remains removable. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_find_playerA | Finds one public player by exact UUID or canonical H- friend code in this project. Use when: a player intentionally shares their ID or friend code. Not for: email/name search, enumerating players or testing online presence. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: None (read only). Returns: {userId,friendCode,display:{name,profile}}. Unknown, inactive, deleted, foreign and blocked players share PLAYER_NOT_FOUND. Errors: 409 REVISION_CONFLICT or an uncertain response: get a new snapshot and reconcile intent, never silently replace expectedRevision and repeat. 404 FRIEND_REQUEST_NOT_FOUND means this request was removed or replaced; do not act on a newer ID. INBOX_FULL rejects the entire send/accept. Friend/request/block capacity limits reject additions while existing data remains removable. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_send_friend_requestA | Sends Friend Request using the reviewed player revision. Use when: the player explicitly requests this social action. Not for: automatic retries after timeout, automatic acceptance of crossed requests or changing expectedRevision without reconciling intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. A current snapshot revision. Side effects: Creates both pending request records and an ordinary recipient Inbox notice atomically. A crossed request still needs explicit acceptance. No automatic retry. Repeating the same revision cannot create a second effect. Returns: Complete {userId,revision,friendCode,friends,incoming,outgoing,blocked,limits,serverTime} snapshot. Replace the matching host/project/player cache. lastActiveAt is the latest retained login, null when unknown; it is not online presence. Errors: 409 REVISION_CONFLICT or an uncertain response: get a new snapshot and reconcile intent, never silently replace expectedRevision and repeat. 404 FRIEND_REQUEST_NOT_FOUND means this request was removed or replaced; do not act on a newer ID. INBOX_FULL rejects the entire send/accept. Friend/request/block capacity limits reject additions while existing data remains removable. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_accept_friend_requestA | Accepts Friend Request using the reviewed player revision. Use when: the player explicitly requests this social action. Not for: automatic retries after timeout, automatic acceptance of crossed requests or changing expectedRevision without reconciling intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. A current snapshot revision and its exact requestId. Side effects: Consumes the exact incoming request and any crossed request, creates the friendship on both sides and sends an ordinary confirmation atomically. No automatic retry. Repeating the same revision cannot create a second effect. Returns: Complete {userId,revision,friendCode,friends,incoming,outgoing,blocked,limits,serverTime} snapshot. Replace the matching host/project/player cache. lastActiveAt is the latest retained login, null when unknown; it is not online presence. Errors: 409 REVISION_CONFLICT or an uncertain response: get a new snapshot and reconcile intent, never silently replace expectedRevision and repeat. 404 FRIEND_REQUEST_NOT_FOUND means this request was removed or replaced; do not act on a newer ID. INBOX_FULL rejects the entire send/accept. Friend/request/block capacity limits reject additions while existing data remains removable. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_decline_friend_requestA | Declines Friend Request using the reviewed player revision. Use when: the player explicitly requests this social action. Not for: automatic retries after timeout, automatic acceptance of crossed requests or changing expectedRevision without reconciling intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. A current snapshot revision and its exact requestId. Side effects: Removes only this exact incoming request and the matching sender outgoing record. No automatic retry. Repeating the same revision cannot create a second effect. Returns: Complete {userId,revision,friendCode,friends,incoming,outgoing,blocked,limits,serverTime} snapshot. Replace the matching host/project/player cache. lastActiveAt is the latest retained login, null when unknown; it is not online presence. Errors: 409 REVISION_CONFLICT or an uncertain response: get a new snapshot and reconcile intent, never silently replace expectedRevision and repeat. 404 FRIEND_REQUEST_NOT_FOUND means this request was removed or replaced; do not act on a newer ID. INBOX_FULL rejects the entire send/accept. Friend/request/block capacity limits reject additions while existing data remains removable. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_cancel_friend_requestA | Cancels Friend Request using the reviewed player revision. Use when: the player explicitly requests this social action. Not for: automatic retries after timeout, automatic acceptance of crossed requests or changing expectedRevision without reconciling intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. A current snapshot revision and its exact requestId. Side effects: Removes only this exact outgoing request and the matching recipient incoming record. No automatic retry. Repeating the same revision cannot create a second effect. Returns: Complete {userId,revision,friendCode,friends,incoming,outgoing,blocked,limits,serverTime} snapshot. Replace the matching host/project/player cache. lastActiveAt is the latest retained login, null when unknown; it is not online presence. Errors: 409 REVISION_CONFLICT or an uncertain response: get a new snapshot and reconcile intent, never silently replace expectedRevision and repeat. 404 FRIEND_REQUEST_NOT_FOUND means this request was removed or replaced; do not act on a newer ID. INBOX_FULL rejects the entire send/accept. Friend/request/block capacity limits reject additions while existing data remains removable. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_remove_friendA | Removes Friend using the reviewed player revision. Use when: the player explicitly requests this social action. Not for: automatic retries after timeout, automatic acceptance of crossed requests or changing expectedRevision without reconciling intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. A current snapshot revision. Side effects: Removes the friendship on both sides. Pending requests and blocks remain unchanged. No automatic retry. Repeating the same revision cannot create a second effect. Returns: Complete {userId,revision,friendCode,friends,incoming,outgoing,blocked,limits,serverTime} snapshot. Replace the matching host/project/player cache. lastActiveAt is the latest retained login, null when unknown; it is not online presence. Errors: 409 REVISION_CONFLICT or an uncertain response: get a new snapshot and reconcile intent, never silently replace expectedRevision and repeat. 404 FRIEND_REQUEST_NOT_FOUND means this request was removed or replaced; do not act on a newer ID. INBOX_FULL rejects the entire send/accept. Friend/request/block capacity limits reject additions while existing data remains removable. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_block_playerA | Blocks Player using the reviewed player revision. Use when: the player explicitly requests this social action. Not for: automatic retries after timeout, automatic acceptance of crossed requests or changing expectedRevision without reconciling intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. A current snapshot revision. Side effects: Adds your block and removes friendship and both request directions atomically. Does not notify the blocked party. No automatic retry. Repeating the same revision cannot create a second effect. Returns: Complete {userId,revision,friendCode,friends,incoming,outgoing,blocked,limits,serverTime} snapshot. Replace the matching host/project/player cache. lastActiveAt is the latest retained login, null when unknown; it is not online presence. Errors: 409 REVISION_CONFLICT or an uncertain response: get a new snapshot and reconcile intent, never silently replace expectedRevision and repeat. 404 FRIEND_REQUEST_NOT_FOUND means this request was removed or replaced; do not act on a newer ID. INBOX_FULL rejects the entire send/accept. Friend/request/block capacity limits reject additions while existing data remains removable. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_unblock_playerA | Unblocks Player using the reviewed player revision. Use when: the player explicitly requests this social action. Not for: automatic retries after timeout, automatic acceptance of crossed requests or changing expectedRevision without reconciling intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. A current snapshot revision. Side effects: Removes only your block. Does not restore a friendship or request, and does not remove the other player's block. No automatic retry. Repeating the same revision cannot create a second effect. Returns: Complete {userId,revision,friendCode,friends,incoming,outgoing,blocked,limits,serverTime} snapshot. Replace the matching host/project/player cache. lastActiveAt is the latest retained login, null when unknown; it is not online presence. Errors: 409 REVISION_CONFLICT or an uncertain response: get a new snapshot and reconcile intent, never silently replace expectedRevision and repeat. 404 FRIEND_REQUEST_NOT_FOUND means this request was removed or replaced; do not act on a newer ID. INBOX_FULL rejects the entire send/accept. Friend/request/block capacity limits reject additions while existing data remains removable. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_groupsA | Reads my groups using a matching player session. Use when: opening a group screen or reconciling an uncertain action. Not for: unbounded group search, automatic pagination or using stale snapshots after a session change. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: None (read only). Returns: MyGroupsView with memberships, pending invitations/requests, revision, limits and serverTime. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_groupA | Reads group using a matching player session. Use when: opening a group screen or reconciling an uncertain action. Not for: unbounded group search, automatic pagination or using stale snapshots after a session change. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: None (read only). Returns: GroupView: public metadata for nonmembers, with data/myRole only for members. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_group_membersA | Reads group members using a matching player session. Use when: opening a group screen or reconciling an uncertain action. Not for: unbounded group search, automatic pagination or using stale snapshots after a session change. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Group membership. Side effects: None (read only). Returns: {groupId,revision,members,nextAfterUserId,serverTime}; one requested page under current memberPageSize. A changed revision between pages requires explicit reconciliation. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_group_pendingA | Reads group pending requests using a matching player session. Use when: opening a group screen or reconciling an uncertain action. Not for: unbounded group search, automatic pagination or using stale snapshots after a session change. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Leader/officer membership. Side effects: None (read only). Returns: {groupId,revision,invitations,joinRequests,serverTime}; complete retained entries, including after policy reductions. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_create_groupA | Creates a fresh server-identified group and its leader atomically. Use when: the player explicitly confirms the group settings. Not for: choosing/reusing a group ID or resending uncertain writes with a new revision. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. The current MyGroupsView revision. Side effects: Creates one group and membership within both limits. The retained player revision prevents duplicate creation on replay. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_update_groupA | Replaces the complete group metadata and private JSON object. Use when: the player explicitly confirms the group settings. Not for: choosing/reusing a group ID or resending uncertain writes with a new revision. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Leader/officer and the current group revision. Side effects: Changes metadata, private data and join mode. Existing pending requests remain. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_join_groupA | Applies the explicit join group action using the reviewed group revision. Use when: the player explicitly confirms this group action. Not for: replacing reviewed revisions/request IDs, bypassing a leader's block, or retrying automatically after uncertainty. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Current group revision and the exact pending requestId where applicable. Side effects: Joins an open group; checks member and player limits. No automatic retry. Same-revision replay cannot create a second effect. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_request_group_joinA | Applies the explicit request group join action using the reviewed group revision. Use when: the player explicitly confirms this group action. Not for: replacing reviewed revisions/request IDs, bypassing a leader's block, or retrying automatically after uncertainty. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Current group revision and the exact pending requestId where applicable. Side effects: Creates a join request and ordinary leader Inbox notice atomically. No automatic retry. Same-revision replay cannot create a second effect. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_invite_group_playerA | Applies the explicit invite group player action using the reviewed group revision. Use when: the player explicitly confirms this group action. Not for: replacing reviewed revisions/request IDs, bypassing a leader's block, or retrying automatically after uncertainty. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Current group revision and the exact pending requestId where applicable. Side effects: Leader/officer creates an invitation and ordinary recipient Inbox notice atomically. No automatic retry. Same-revision replay cannot create a second effect. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_accept_group_inviteA | Applies the explicit accept group invite action using the reviewed group revision. Use when: the player explicitly confirms this group action. Not for: replacing reviewed revisions/request IDs, bypassing a leader's block, or retrying automatically after uncertainty. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Current group revision and the exact pending requestId where applicable. Side effects: Consumes your exact invitation, rechecks limits/blocks and notifies the active issuer. No automatic retry. Same-revision replay cannot create a second effect. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_decline_group_inviteA | Applies the explicit decline group invite action using the reviewed group revision. Use when: the player explicitly confirms this group action. Not for: replacing reviewed revisions/request IDs, bypassing a leader's block, or retrying automatically after uncertainty. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Current group revision and the exact pending requestId where applicable. Side effects: Removes your exact pending invitation on both sides. No automatic retry. Same-revision replay cannot create a second effect. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_cancel_group_inviteA | Applies the explicit cancel group invite action using the reviewed group revision. Use when: the player explicitly confirms this group action. Not for: replacing reviewed revisions/request IDs, bypassing a leader's block, or retrying automatically after uncertainty. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Current group revision and the exact pending requestId where applicable. Side effects: Leader/officer cancels this exact invitation. No automatic retry. Same-revision replay cannot create a second effect. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_accept_group_requestA | Applies the explicit accept group request action using the reviewed group revision. Use when: the player explicitly confirms this group action. Not for: replacing reviewed revisions/request IDs, bypassing a leader's block, or retrying automatically after uncertainty. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Current group revision and the exact pending requestId where applicable. Side effects: Leader/officer admits this exact requester and sends their ordinary confirmation atomically. No automatic retry. Same-revision replay cannot create a second effect. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_decline_group_requestA | Applies the explicit decline group request action using the reviewed group revision. Use when: the player explicitly confirms this group action. Not for: replacing reviewed revisions/request IDs, bypassing a leader's block, or retrying automatically after uncertainty. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Current group revision and the exact pending requestId where applicable. Side effects: Leader/officer declines this exact request. No automatic retry. Same-revision replay cannot create a second effect. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_cancel_group_requestA | Applies the explicit cancel group request action using the reviewed group revision. Use when: the player explicitly confirms this group action. Not for: replacing reviewed revisions/request IDs, bypassing a leader's block, or retrying automatically after uncertainty. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Current group revision and the exact pending requestId where applicable. Side effects: Cancels your exact join request. No automatic retry. Same-revision replay cannot create a second effect. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_leave_groupA | Applies the explicit leave group action using the reviewed group revision. Use when: the player explicitly confirms this group action. Not for: replacing reviewed revisions/request IDs, bypassing a leader's block, or retrying automatically after uncertainty. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Current group revision and the exact pending requestId where applicable. Side effects: Leaves membership. A leader must transfer first, unless sole member with no pending entries. No automatic retry. Same-revision replay cannot create a second effect. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_remove_group_memberA | Applies the explicit remove group member action using the reviewed group revision. Use when: the player explicitly confirms this group action. Not for: replacing reviewed revisions/request IDs, bypassing a leader's block, or retrying automatically after uncertainty. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Current group revision and the exact pending requestId where applicable. Side effects: Leader removes an officer/member; an officer can remove only a member. No automatic retry. Same-revision replay cannot create a second effect. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_set_group_member_roleA | Applies the explicit set group member role action using the reviewed group revision. Use when: the player explicitly confirms this group action. Not for: replacing reviewed revisions/request IDs, bypassing a leader's block, or retrying automatically after uncertainty. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Current group revision and the exact pending requestId where applicable. Side effects: Leader sets another member's role to officer/member. No automatic retry. Same-revision replay cannot create a second effect. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_transfer_group_leadershipA | Applies the explicit transfer group leadership action using the reviewed group revision. Use when: the player explicitly confirms this group action. Not for: replacing reviewed revisions/request IDs, bypassing a leader's block, or retrying automatically after uncertainty. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Current group revision and the exact pending requestId where applicable. Side effects: Leader transfers leadership to an existing member, becoming an ordinary member. No automatic retry. Same-revision replay cannot create a second effect. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_delete_groupA | Applies the explicit delete group action using the reviewed group revision. Use when: the player explicitly confirms this group action. Not for: replacing reviewed revisions/request IDs, bypassing a leader's block, or retrying automatically after uncertainty. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Current group revision and the exact pending requestId where applicable. Side effects: Sole leader deletes the group only when no invitations/requests remain. No automatic retry. Same-revision replay cannot create a second effect. Returns: {groups:MyGroupsView,group:GroupView|null}. groups is the actor's complete snapshot, never the target's private state. group is null after leave/delete; nonmembers never receive private data. Replace only the matching host/project/player cache. Errors: Use horizon_get_groups and horizon_get_group_pending to reconcile state. 409 REVISION_CONFLICT or uncertain response: read and reconcile intent, never refresh the revision and repeat automatically. Pending decisions require the original requestId; REQUEST_NOT_FOUND means it was removed/replaced. INBOX_FULL rolls back the entire action. 403 rejects group role, session or bilateral block violations. 429 is reported without automatic retry. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_itemsA | Reads the player's bounded unique item inventory. Use when: opening inventory or reconciling an uncertain edit. Not for: polling or minting items; use horizon_get_item_catalog for templates. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: None (read only); an absent inventory is returned empty without writing. Returns: Complete {userId,revision,instances,limits,serverTime} inventory. Replace only the matching host/project/player cache. Instances carry server-generated UUIDs, properties, equipped and createdAt. Errors: 409 REVISION_CONFLICT or an uncertain response: use horizon_get_items and reconcile intent, never silently substitute a new revision and repeat. 404 ITEM_NOT_FOUND means this instance no longer exists. 422 ITEM_PROPERTY_NOT_ALLOWED/ITEM_PROPERTY_LIMIT_REACHED rejects the entire adjustment. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_item_catalogA | Reads one bounded item template page, including archived templates. Use when: showing item details or reviewing a catalog with explicit keyset pagination. Not for: automatically scanning the whole catalog or combining pages from different revisions. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: None (read only). Returns: {revision,definitions,nextAfterKey,total,limits,serverTime}. Retain the first revision for later pages; null cursor ends the list. Errors: 409 REVISION_CONFLICT or an uncertain response: use horizon_get_items and reconcile intent, never silently substitute a new revision and repeat. 404 ITEM_NOT_FOUND means this instance no longer exists. 422 ITEM_PROPERTY_NOT_ALLOWED/ITEM_PROPERTY_LIMIT_REACHED rejects the entire adjustment. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_adjust_itemA | Adjusts Item Properties using the reviewed inventory revision. Use when: the player explicitly requests this inventory action. Not for: automatic retries, client grants, changing instance IDs or revisions to force an uncertain action through. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. An exact reviewed inventory revision and instance UUID. Side effects: Applies all configured deltas atomically. Archived templates and properties without a rule cannot be adjusted. One HTTP attempt only. Returns: Complete {userId,revision,instances,limits,serverTime} inventory. Replace only the matching host/project/player cache. Instances carry server-generated UUIDs, properties, equipped and createdAt. Errors: 409 REVISION_CONFLICT or an uncertain response: use horizon_get_items and reconcile intent, never silently substitute a new revision and repeat. 404 ITEM_NOT_FOUND means this instance no longer exists. 422 ITEM_PROPERTY_NOT_ALLOWED/ITEM_PROPERTY_LIMIT_REACHED rejects the entire adjustment. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_equip_itemA | Sets Item Equipped State using the reviewed inventory revision. Use when: the player explicitly requests this inventory action. Not for: automatic retries, client grants, changing instance IDs or revisions to force an uncertain action through. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. An exact reviewed inventory revision and instance UUID. Side effects: Sets this instance's equipped boolean; it does not enforce game-specific slot rules. One HTTP attempt only. Returns: Complete {userId,revision,instances,limits,serverTime} inventory. Replace only the matching host/project/player cache. Instances carry server-generated UUIDs, properties, equipped and createdAt. Errors: 409 REVISION_CONFLICT or an uncertain response: use horizon_get_items and reconcile intent, never silently substitute a new revision and repeat. 404 ITEM_NOT_FOUND means this instance no longer exists. 422 ITEM_PROPERTY_NOT_ALLOWED/ITEM_PROPERTY_LIMIT_REACHED rejects the entire adjustment. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_discard_itemA | Discards Item using the reviewed inventory revision. Use when: the player explicitly requests this inventory action. Not for: automatic retries, client grants, changing instance IDs or revisions to force an uncertain action through. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. An exact reviewed inventory revision and instance UUID. Side effects: Permanently removes this instance. The original source guards consumption; replay cannot recreate a discarded item and no recipient receipt is added. One HTTP attempt only. Returns: Complete {userId,revision,instances,limits,serverTime} inventory. Replace only the matching host/project/player cache. Instances carry server-generated UUIDs, properties, equipped and createdAt. Errors: 409 REVISION_CONFLICT or an uncertain response: use horizon_get_items and reconcile intent, never silently substitute a new revision and repeat. 404 ITEM_NOT_FOUND means this instance no longer exists. 422 ITEM_PROPERTY_NOT_ALLOWED/ITEM_PROPERTY_LIMIT_REACHED rejects the entire adjustment. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_shared_collectionsA | Reads one permanent collection catalog page. Use when: explicit world-map/async-PvP object access after reading horizon://docs/shared-objects. Not for: background polling, automatic page traversal, interpreting opaque bytes or using this as a combat validator. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only; retain catalogRevision across pages. Returns: {revision,definitions,nextAfterKey,limits,serverTime} Errors: 409 revision/state/permission conflict or lost response: explicitly reread owned objects/usage and reconcile original intent, never automatically retry with newer revisions or a replacement ID. 404 does not distinguish missing/private/expired data. 422 retains existing data on quota/archive failure. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_shared_usageA | Reads the current player's count and creation precondition for one collection. Use when: explicit world-map/async-PvP object access after reading horizon://docs/shared-objects. Not for: background polling, automatic page traversal, interpreting opaque bytes or using this as a combat validator. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only; absent revision/count are zero without writing. Returns: {userId,collection,revision,count,limits,pollAfterSeconds,serverTime} Errors: 409 revision/state/permission conflict or lost response: explicitly reread owned objects/usage and reconcile original intent, never automatically retry with newer revisions or a replacement ID. 404 does not distinguish missing/private/expired data. 422 retains existing data on quota/archive failure. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_shared_objectA | Reads one object under current permissions. Use when: explicit world-map/async-PvP object access after reading horizon://docs/shared-objects. Not for: background polling, automatic page traversal, interpreting opaque bytes or using this as a combat validator. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only; respect pollAfterSeconds for refresh. Returns: {object,pollAfterSeconds,serverTime}; object contains opaque dataBase64 and original identity/revision. Errors: 409 revision/state/permission conflict or lost response: explicitly reread owned objects/usage and reconcile original intent, never automatically retry with newer revisions or a replacement ID. 404 does not distinguish missing/private/expired data. 422 retains existing data on quota/archive failure. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_query_shared_objectsA | Reads one bounded metadata-selected object page. Use when: explicit world-map/async-PvP object access after reading horizon://docs/shared-objects. Not for: background polling, automatic page traversal, interpreting opaque bytes or using this as a combat validator. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only POST. At most 256 candidates, 50 objects and 1 MiB decoded bytes. Empty page with cursor is valid. Random is nonuniform, at most two indexed ranges. Returns: {objects,nextCursor,pollAfterSeconds,serverTime}; explicit next-cursor may proceed immediately, refresh honors interval. Errors: 409 revision/state/permission conflict or lost response: explicitly reread owned objects/usage and reconcile original intent, never automatically retry with newer revisions or a replacement ID. 404 does not distinguish missing/private/expired data. 422 retains existing data on quota/archive failure. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_create_shared_objectA | Creates one server-ID object using the original owner-usage revision. Use when: explicit world-map/async-PvP object access after reading horizon://docs/shared-objects. Not for: background polling, automatic page traversal, interpreting opaque bytes or using this as a combat validator. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Commits object, usage and quota atomically. Retain original If-Match after a lost response. One HTTP attempt. Returns: {object,usage,pollAfterSeconds,serverTime} Errors: 409 revision/state/permission conflict or lost response: explicitly reread owned objects/usage and reconcile original intent, never automatically retry with newer revisions or a replacement ID. 404 does not distinguish missing/private/expired data. 422 retains existing data on quota/archive failure. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_update_shared_objectA | Replaces one object's opaque bytes and configured search data under its exact revision. Use when: explicit world-map/async-PvP object access after reading horizon://docs/shared-objects. Not for: background polling, automatic page traversal, interpreting opaque bytes or using this as a combat validator. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Current owner/group permission required; owner/group/expiry stay immutable. One HTTP attempt. Returns: {object,usage,pollAfterSeconds,serverTime} Errors: 409 revision/state/permission conflict or lost response: explicitly reread owned objects/usage and reconcile original intent, never automatically retry with newer revisions or a replacement ID. 404 does not distinguish missing/private/expired data. 422 retains existing data on quota/archive failure. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_delete_shared_objectA | Deletes one exact-revision object and refunds its stored charge. Use when: explicit world-map/async-PvP object access after reading horizon://docs/shared-objects. Not for: background polling, automatic page traversal, interpreting opaque bytes or using this as a combat validator. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Destructive; owner cleanup remains possible after group leave/archive. Owner usage revision remains to prevent creation ABA. One HTTP attempt. Returns: {objectId,deleted,usage,pollAfterSeconds,serverTime}; repeated completed delete is OBJECT_NOT_FOUND. Errors: 409 revision/state/permission conflict or lost response: explicitly reread owned objects/usage and reconcile original intent, never automatically retry with newer revisions or a replacement ID. 404 does not distinguish missing/private/expired data. 422 retains existing data on quota/archive failure. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_matchesA | Reads the player's bounded active, invited and recent match summaries. Use when: explicit asynchronous multiplayer actions after reading horizon://docs/matches. Not for: automatic polling, page traversal, timeout progression, invented winners or automatic rewards. Reconcile with horizon_get_matches and horizon_get_match. Consent and game consensus do not validate honest gameplay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only. Respect pollAfterSeconds on refresh. Retained state is not truncated after System Config reductions. Returns: {userId,revision,active,invites,recent,pendingResults,limits,pollAfterSeconds,serverTime}; minimal pendingResults retain matchId,finalStateRevision,ownRankedRunId and expiresAt independently of completed detail history. Errors: 404 hides private/missing/expired matches. 409 REVISION_CONFLICT or STATE_CONFLICT: explicitly reread and reconcile the original intent, never replace the revision or automatically resubmit. RESULT_CONFLICT preserves the original report. RUN_EXPIRED/RUN_ALREADY_USED never allow replacement ranked runs. 501 FEATURE_NOT_SUPPORTED is explicit for simpleServer ranked mode. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_match_limitsA | Reads the player's five-tier limits and project capabilities. Use when: explicit asynchronous multiplayer actions after reading horizon://docs/matches. Not for: automatic polling, page traversal, timeout progression, invented winners or automatic rewards. Reconcile with horizon_get_matches and horizon_get_match. Consent and game consensus do not validate honest gameplay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only. Respect pollAfterSeconds on refresh. Retained state is not truncated after System Config reductions. Returns: {limits,config,capabilities,pollAfterSeconds,serverTime}; limits include activeMatches,stateBytes,retainedMatches,pendingInvites,settlementMatches,historyRetentionSeconds,rankedSettlementSeconds. Zero completed history is valid. Errors: 404 hides private/missing/expired matches. 409 REVISION_CONFLICT or STATE_CONFLICT: explicitly reread and reconcile the original intent, never replace the revision or automatically resubmit. RESULT_CONFLICT preserves the original report. RUN_EXPIRED/RUN_ALREADY_USED never allow replacement ranked runs. 501 FEATURE_NOT_SUPPORTED is explicit for simpleServer ranked mode. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_find_open_matchesA | Reads one strength-filtered open-lobby page under current blocks and active-owner checks. Use when: explicit asynchronous multiplayer actions after reading horizon://docs/matches. Not for: automatic polling, page traversal, timeout progression, invented winners or automatic rewards. Reconcile with horizon_get_matches and horizon_get_match. Consent and game consensus do not validate honest gameplay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only, at most256 metadata candidates and50 results. Empty cursor pages are valid. No game state is returned. Returns: {matches,nextCursor,pollAfterSeconds,serverTime} Errors: 404 hides private/missing/expired matches. 409 REVISION_CONFLICT or STATE_CONFLICT: explicitly reread and reconcile the original intent, never replace the revision or automatically resubmit. RESULT_CONFLICT preserves the original report. RUN_EXPIRED/RUN_ALREADY_USED never allow replacement ranked runs. 501 FEATURE_NOT_SUPPORTED is explicit for simpleServer ranked mode. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_matchA | Reads one currently authorized match snapshot. Use when: explicit asynchronous multiplayer actions after reading horizon://docs/matches. Not for: automatic polling, page traversal, timeout progression, invented winners or automatic rewards. Reconcile with horizon_get_matches and horizon_get_match. Consent and game consensus do not validate honest gameplay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only. Invited players receive lobby metadata with dataBase64=null, participants receive original bytes and reports. Returns: {match,pollAfterSeconds,serverTime} Errors: 404 hides private/missing/expired matches. 409 REVISION_CONFLICT or STATE_CONFLICT: explicitly reread and reconcile the original intent, never replace the revision or automatically resubmit. RESULT_CONFLICT preserves the original report. RUN_EXPIRED/RUN_ALREADY_USED never allow replacement ranked runs. 501 FEATURE_NOT_SUPPORTED is explicit for simpleServer ranked mode. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_create_matchA | Creates one server-ID lobby under the original player-ledger revision. Use when: explicit asynchronous multiplayer actions after reading horizon://docs/matches. Not for: automatic polling, page traversal, timeout progression, invented winners or automatic rewards. Reconcile with horizon_get_matches and horizon_get_match. Consent and game consensus do not validate honest gameplay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Reserves active and settlement capacity plus bounded invite slots atomically. Completed detail history is separate; FREE defaults to zero. Lost response: reconcile horizon_get_matches with the original intent. Returns: {match,playerRevision,pollAfterSeconds,serverTime} Errors: 404 hides private/missing/expired matches. 409 REVISION_CONFLICT or STATE_CONFLICT: explicitly reread and reconcile the original intent, never replace the revision or automatically resubmit. RESULT_CONFLICT preserves the original report. RUN_EXPIRED/RUN_ALREADY_USED never allow replacement ranked runs. 501 FEATURE_NOT_SUPPORTED is explicit for simpleServer ranked mode. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_join_matchA | Executes join match under the exact original revision. Use when: explicit asynchronous multiplayer actions after reading horizon://docs/matches. Not for: automatic polling, page traversal, timeout progression, invented winners or automatic rewards. Reconcile with horizon_get_matches and horizon_get_match. Consent and game consensus do not validate honest gameplay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Start requires the creator and every joined UUID exactly once. Turn requires the current unexpired actor. Timeout advances only one turn. Active leave forfeits without selecting a winner. Lobby cancel is creator-only. Full Inbox retains a durable notice without undoing a committed move. Returns: {match,pollAfterSeconds,serverTime}; departing lobby actors receive metadata only and lose point-read access. Errors: 404 hides private/missing/expired matches. 409 REVISION_CONFLICT or STATE_CONFLICT: explicitly reread and reconcile the original intent, never replace the revision or automatically resubmit. RESULT_CONFLICT preserves the original report. RUN_EXPIRED/RUN_ALREADY_USED never allow replacement ranked runs. 501 FEATURE_NOT_SUPPORTED is explicit for simpleServer ranked mode. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_decline_match_inviteA | Executes decline match invitation under the exact original revision. Use when: explicit asynchronous multiplayer actions after reading horizon://docs/matches. Not for: automatic polling, page traversal, timeout progression, invented winners or automatic rewards. Reconcile with horizon_get_matches and horizon_get_match. Consent and game consensus do not validate honest gameplay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Start requires the creator and every joined UUID exactly once. Turn requires the current unexpired actor. Timeout advances only one turn. Active leave forfeits without selecting a winner. Lobby cancel is creator-only. Full Inbox retains a durable notice without undoing a committed move. Returns: {match,pollAfterSeconds,serverTime}; departing lobby actors receive metadata only and lose point-read access. Errors: 404 hides private/missing/expired matches. 409 REVISION_CONFLICT or STATE_CONFLICT: explicitly reread and reconcile the original intent, never replace the revision or automatically resubmit. RESULT_CONFLICT preserves the original report. RUN_EXPIRED/RUN_ALREADY_USED never allow replacement ranked runs. 501 FEATURE_NOT_SUPPORTED is explicit for simpleServer ranked mode. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_start_matchA | Executes start match under the exact original revision. Use when: explicit asynchronous multiplayer actions after reading horizon://docs/matches. Not for: automatic polling, page traversal, timeout progression, invented winners or automatic rewards. Reconcile with horizon_get_matches and horizon_get_match. Consent and game consensus do not validate honest gameplay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Start requires the creator and every joined UUID exactly once. Turn requires the current unexpired actor. Timeout advances only one turn. Active leave forfeits without selecting a winner. Lobby cancel is creator-only. Full Inbox retains a durable notice without undoing a committed move. Returns: {match,pollAfterSeconds,serverTime}; departing lobby actors receive metadata only and lose point-read access. Errors: 404 hides private/missing/expired matches. 409 REVISION_CONFLICT or STATE_CONFLICT: explicitly reread and reconcile the original intent, never replace the revision or automatically resubmit. RESULT_CONFLICT preserves the original report. RUN_EXPIRED/RUN_ALREADY_USED never allow replacement ranked runs. 501 FEATURE_NOT_SUPPORTED is explicit for simpleServer ranked mode. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_submit_match_turnA | Executes submit match turn under the exact original revision. Use when: explicit asynchronous multiplayer actions after reading horizon://docs/matches. Not for: automatic polling, page traversal, timeout progression, invented winners or automatic rewards. Reconcile with horizon_get_matches and horizon_get_match. Consent and game consensus do not validate honest gameplay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Start requires the creator and every joined UUID exactly once. Turn requires the current unexpired actor. Timeout advances only one turn. Active leave forfeits without selecting a winner. Lobby cancel is creator-only. Full Inbox retains a durable notice without undoing a committed move. Returns: {match,pollAfterSeconds,serverTime}; departing lobby actors receive metadata only and lose point-read access. Errors: 404 hides private/missing/expired matches. 409 REVISION_CONFLICT or STATE_CONFLICT: explicitly reread and reconcile the original intent, never replace the revision or automatically resubmit. RESULT_CONFLICT preserves the original report. RUN_EXPIRED/RUN_ALREADY_USED never allow replacement ranked runs. 501 FEATURE_NOT_SUPPORTED is explicit for simpleServer ranked mode. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_advance_match_timeoutA | Executes advance match timeout under the exact original revision. Use when: explicit asynchronous multiplayer actions after reading horizon://docs/matches. Not for: automatic polling, page traversal, timeout progression, invented winners or automatic rewards. Reconcile with horizon_get_matches and horizon_get_match. Consent and game consensus do not validate honest gameplay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Start requires the creator and every joined UUID exactly once. Turn requires the current unexpired actor. Timeout advances only one turn. Active leave forfeits without selecting a winner. Lobby cancel is creator-only. Full Inbox retains a durable notice without undoing a committed move. Returns: {match,pollAfterSeconds,serverTime}; departing lobby actors receive metadata only and lose point-read access. Errors: 404 hides private/missing/expired matches. 409 REVISION_CONFLICT or STATE_CONFLICT: explicitly reread and reconcile the original intent, never replace the revision or automatically resubmit. RESULT_CONFLICT preserves the original report. RUN_EXPIRED/RUN_ALREADY_USED never allow replacement ranked runs. 501 FEATURE_NOT_SUPPORTED is explicit for simpleServer ranked mode. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_leave_matchA | Executes leave match under the exact original revision. Use when: explicit asynchronous multiplayer actions after reading horizon://docs/matches. Not for: automatic polling, page traversal, timeout progression, invented winners or automatic rewards. Reconcile with horizon_get_matches and horizon_get_match. Consent and game consensus do not validate honest gameplay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Start requires the creator and every joined UUID exactly once. Turn requires the current unexpired actor. Timeout advances only one turn. Active leave forfeits without selecting a winner. Lobby cancel is creator-only. Full Inbox retains a durable notice without undoing a committed move. Returns: {match,pollAfterSeconds,serverTime}; departing lobby actors receive metadata only and lose point-read access. Errors: 404 hides private/missing/expired matches. 409 REVISION_CONFLICT or STATE_CONFLICT: explicitly reread and reconcile the original intent, never replace the revision or automatically resubmit. RESULT_CONFLICT preserves the original report. RUN_EXPIRED/RUN_ALREADY_USED never allow replacement ranked runs. 501 FEATURE_NOT_SUPPORTED is explicit for simpleServer ranked mode. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_cancel_matchA | Executes cancel match lobby under the exact original revision. Use when: explicit asynchronous multiplayer actions after reading horizon://docs/matches. Not for: automatic polling, page traversal, timeout progression, invented winners or automatic rewards. Reconcile with horizon_get_matches and horizon_get_match. Consent and game consensus do not validate honest gameplay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Start requires the creator and every joined UUID exactly once. Turn requires the current unexpired actor. Timeout advances only one turn. Active leave forfeits without selecting a winner. Lobby cancel is creator-only. Full Inbox retains a durable notice without undoing a committed move. Returns: {match,pollAfterSeconds,serverTime}; departing lobby actors receive metadata only and lose point-read access. Errors: 404 hides private/missing/expired matches. 409 REVISION_CONFLICT or STATE_CONFLICT: explicitly reread and reconcile the original intent, never replace the revision or automatically resubmit. RESULT_CONFLICT preserves the original report. RUN_EXPIRED/RUN_ALREADY_USED never allow replacement ranked runs. 501 FEATURE_NOT_SUPPORTED is explicit for simpleServer ranked mode. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_report_match_resultA | Records this participant's immutable report for the frozen final state. Use when: explicit asynchronous multiplayer actions after reading horizon://docs/matches. Not for: automatic polling, page traversal, timeout progression, invented winners or automatic rewards. Reconcile with horizon_get_matches and horizon_get_match. Consent and game consensus do not validate honest gameplay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt, original finalStateRevision/result/winnerIds on explicit retry. All accepted players must agree for confirmed. Missing reports become unconfirmed, disagreements disputed. No automatic reward. Returns: {match,replayed,pollAfterSeconds,serverTime} Errors: 404 hides private/missing/expired matches. 409 REVISION_CONFLICT or STATE_CONFLICT: explicitly reread and reconcile the original intent, never replace the revision or automatically resubmit. RESULT_CONFLICT preserves the original report. RUN_EXPIRED/RUN_ALREADY_USED never allow replacement ranked runs. 501 FEATURE_NOT_SUPPORTED is explicit for simpleServer ranked mode. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_start_match_ranked_runA | Creates or recovers one original match-bound validated run after complete consensus. Use when: explicit asynchronous multiplayer actions after reading horizon://docs/matches. Not for: automatic polling, page traversal, timeout progression, invented winners or automatic rewards. Reconcile with horizon_get_matches and horizon_get_match. Consent and game consensus do not validate honest gameplay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Server rechecks the original configured board and binds match/final revision. Recovery preserves runId, seed and expiry; never replaces consumed/expired tickets. This short post-match validation is not retrospective game simulation. Returns: Existing StartRunResponse with original ticket, runId, seed, expiry and context status; submit through the existing validated-actions endpoint. Errors: 404 hides private/missing/expired matches. 409 REVISION_CONFLICT or STATE_CONFLICT: explicitly reread and reconcile the original intent, never replace the revision or automatically resubmit. RESULT_CONFLICT preserves the original report. RUN_EXPIRED/RUN_ALREADY_USED never allow replacement ranked runs. 501 FEATURE_NOT_SUPPORTED is explicit for simpleServer ranked mode. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_chat_limitsA | Reads five-tier bounds, current moderation and hosted capabilities. Use when: explicit hosted chat actions after reading horizon://docs/chat. Not for: automatic sends, repeated polling, rich-text rendering or exposing moderation credentials. Use horizon_get_chat_operation to reconcile original sends, then horizon_send_chat_message only for the explicit identical replay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only, including during FREE/mute/ban. No polling timer. Returns: {limits,capabilities,moderation,serverTime} Errors: 404 hides private/missing/expired channels or source messages. 409 OPERATION_CONFLICT/OPERATION_EXPIRED or STATE_CONFLICT requires explicit original-intent reconciliation. Never replace an unknown send UUID/time/text. 429 does not schedule a retry. CHAT_MUTED/CHAT_BANNED restrict current chat access. 501 NOT_SUPPORTED means simpleServer has no chat or polling fallback. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_open_chat_channelA | Opens deterministic direct, group or project chat under current permissions. Use when: explicit hosted chat actions after reading horizon://docs/chat. Not for: automatic sends, repeated polling, rich-text rendering or exposing moderation credentials. Use horizon_get_chat_operation to reconcile original sends, then horizon_send_chat_message only for the explicit identical replay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Existing live open is a no-op. A new/expired channel allocates a fresh epoch under quota/rate gates. Subscribe before first sync/send. Returns: {channel,serverTime} Errors: 404 hides private/missing/expired channels or source messages. 409 OPERATION_CONFLICT/OPERATION_EXPIRED or STATE_CONFLICT requires explicit original-intent reconciliation. Never replace an unknown send UUID/time/text. 429 does not schedule a retry. CHAT_MUTED/CHAT_BANNED restrict current chat access. 501 NOT_SUPPORTED means simpleServer has no chat or polling fallback. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_sync_chat_channelA | Reads an authorized incremental snapshot after subscription resync/event or explicit user action. Use when: explicit hosted chat actions after reading horizon://docs/chat. Not for: automatic sends, repeated polling, rich-text rendering or exposing moderation credentials. Use horizon_get_chat_operation to reconcile original sends, then horizon_send_chat_message only for the explicit identical replay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read-only POST, one HTTP attempt. Complete visible ID order plus unknown immutable text. Known IDs are valid only for the exact cached epoch and complete authorized cache. No periodic polling. Returns: {channel,visibleMessageIds,messages,moderation,serverTime}; hide cache on disconnect/permission change and apply only a complete matching snapshot. Errors: 404 hides private/missing/expired channels or source messages. 409 OPERATION_CONFLICT/OPERATION_EXPIRED or STATE_CONFLICT requires explicit original-intent reconciliation. Never replace an unknown send UUID/time/text. 429 does not schedule a retry. CHAT_MUTED/CHAT_BANNED restrict current chat access. 501 NOT_SUPPORTED means simpleServer has no chat or polling fallback. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_send_chat_messageA | Sends plain text once or explicitly replays the exact original operation. Use when: explicit hosted chat actions after reading horizon://docs/chat. Not for: automatic sends, repeated polling, rich-text rendering or exposing moderation credentials. Use horizon_get_chat_operation to reconcile original sends, then horizon_send_chat_message only for the explicit identical replay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Persist project+player operationId/issuedAt/channel/full text before sending. The original live message provides its receipt; replay never recreates expired/deleted text. Direct/group windows are15 messages/30seconds, project windows20/seven days. A monotone player time fence rejects unknown older sends; no per-player message/receipt copy. Returns: {receipt,replayed,serverTime} Errors: 404 hides private/missing/expired channels or source messages. 409 OPERATION_CONFLICT/OPERATION_EXPIRED or STATE_CONFLICT requires explicit original-intent reconciliation. Never replace an unknown send UUID/time/text. 429 does not schedule a retry. CHAT_MUTED/CHAT_BANNED restrict current chat access. 501 NOT_SUPPORTED means simpleServer has no chat or polling fallback. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_chat_operationA | Reads the current player's retained original send receipt. Use when: explicit hosted chat actions after reading horizon://docs/chat. Not for: automatic sends, repeated polling, rich-text rendering or exposing moderation credentials. Use horizon_get_chat_operation to reconcile original sends, then horizon_send_chat_message only for the explicit identical replay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only, with current identity while the original message remains. A missing/expired receipt does not prove a send never committed and cannot authorize a new ID. No historical per-player copy is retained. Returns: {receipt,serverTime}, metadata only Errors: 404 hides private/missing/expired channels or source messages. 409 OPERATION_CONFLICT/OPERATION_EXPIRED or STATE_CONFLICT requires explicit original-intent reconciliation. Never replace an unknown send UUID/time/text. 429 does not schedule a retry. CHAT_MUTED/CHAT_BANNED restrict current chat access. 501 NOT_SUPPORTED means simpleServer has no chat or polling fallback. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_report_chat_messageA | Reports one currently visible message with the original reason. Use when: explicit hosted chat actions after reading horizon://docs/chat. Not for: automatic sends, repeated polling, rich-text rendering or exposing moderation credentials. Use horizon_get_chat_operation to reconcile original sends, then horizon_send_chat_message only for the explicit identical replay. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Retains one immutable shared report snapshot under current project capacity. Same-original replay uses that retained report; after removal, a still-visible original message may be reported only by another explicit action under current permission/rate checks (one new report/player/minute). Missing original messages cannot reopen reports. No per-player receipt history or implicit retry. Returns: {reportId,status,replayed,serverTime} Errors: 404 hides private/missing/expired channels or source messages. 409 OPERATION_CONFLICT/OPERATION_EXPIRED or STATE_CONFLICT requires explicit original-intent reconciliation. Never replace an unknown send UUID/time/text. 429 does not schedule a retry. CHAT_MUTED/CHAT_BANNED restrict current chat access. 501 NOT_SUPPORTED means simpleServer has no chat or polling fallback. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_marketplace_limitsA | Reads current own marketplace state or configured limits. Use when: explicit marketplace actions after reading horizon://docs/marketplace. Not for: automatic trading, price polling or generated replacement operations. Use horizon_get_marketplace_operation to reconcile the original intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only. No automatic refresh or polling. Returns: {limits,capabilities,config,serverTime} Errors: 409 conflicts require explicit reconciliation, never fresh revisions or operation IDs on an unknown outcome. Missing OPERATION_NOT_FOUND does not prove nonexecution. 422 capacity/balance/daily-limit errors preserve atomicity. 429 schedules no retry. Full Inbox returns pending without losing the original item. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_marketplaceB | Reads current own marketplace state or configured limits. Use when: explicit marketplace actions after reading horizon://docs/marketplace. Not for: automatic trading, price polling or generated replacement operations. Use horizon_get_marketplace_operation to reconcile the original intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only. No automatic refresh or polling. Returns: {state,serverTime} Errors: 409 conflicts require explicit reconciliation, never fresh revisions or operation IDs on an unknown outcome. Missing OPERATION_NOT_FOUND does not prove nonexecution. 422 capacity/balance/daily-limit errors preserve atomicity. 429 schedules no retry. Full Inbox returns pending without losing the original item. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_marketplace_rulesA | Reads one revision-consistent bounded rule page. Use when: explicit marketplace actions after reading horizon://docs/marketplace. Not for: automatic trading, price polling or generated replacement operations. Use horizon_get_marketplace_operation to reconcile the original intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only. Preserve catalogRevision and after for explicit subsequent pages. Returns: {revision,rules,nextCursor,serverTime} Errors: 409 conflicts require explicit reconciliation, never fresh revisions or operation IDs on an unknown outcome. Missing OPERATION_NOT_FOUND does not prove nonexecution. 422 capacity/balance/daily-limit errors preserve atomicity. 429 schedules no retry. Full Inbox returns pending without losing the original item. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_query_marketplace_listingsA | Reads one bounded active-listing page by item and price. Use when: explicit marketplace actions after reading horizon://docs/marketplace. Not for: automatic trading, price polling or generated replacement operations. Use horizon_get_marketplace_operation to reconcile the original intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only, up to 256 candidates and 50 returned listings. An empty page can carry a continuation cursor. Returns: {listings,nextCursor,serverTime} Errors: 409 conflicts require explicit reconciliation, never fresh revisions or operation IDs on an unknown outcome. Missing OPERATION_NOT_FOUND does not prove nonexecution. 422 capacity/balance/daily-limit errors preserve atomicity. 429 schedules no retry. Full Inbox returns pending without losing the original item. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_marketplace_listingA | Reads one authorized listing or original own operation receipt. Use when: explicit marketplace actions after reading horizon://docs/marketplace. Not for: automatic trading, price polling or generated replacement operations. Use horizon_get_marketplace_operation to reconcile the original intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only. Missing receipts never authorize replacement IDs; retained receipts do not regrant items or currency. Returns: {listing,serverTime} Errors: 409 conflicts require explicit reconciliation, never fresh revisions or operation IDs on an unknown outcome. Missing OPERATION_NOT_FOUND does not prove nonexecution. 422 capacity/balance/daily-limit errors preserve atomicity. 429 schedules no retry. Full Inbox returns pending without losing the original item. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_marketplace_operationA | Reads one authorized listing or original own operation receipt. Use when: explicit marketplace actions after reading horizon://docs/marketplace. Not for: automatic trading, price polling or generated replacement operations. Use horizon_get_marketplace_operation to reconcile the original intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Read only. Missing receipts never authorize replacement IDs; retained receipts do not regrant items or currency. Returns: {receipt,serverTime} Errors: 409 conflicts require explicit reconciliation, never fresh revisions or operation IDs on an unknown outcome. Missing OPERATION_NOT_FOUND does not prove nonexecution. 422 capacity/balance/daily-limit errors preserve atomicity. 429 schedules no retry. Full Inbox returns pending without losing the original item. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_create_marketplace_listingA | Lists one original unequipped item at the explicitly approved price and fee configuration. Use when: explicit marketplace actions after reading horizon://docs/marketplace. Not for: automatic trading, price polling or generated replacement operations. Use horizon_get_marketplace_operation to reconcile the original intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Persist all original fields before sending under project/player/feature. Atomically removes the exact inventory instance into escrow. Never recalculate revisions after a lost response. Returns: {receipt,listing,replayed,serverTime}; listing can be null on retained replay after terminal audit purge Errors: 409 conflicts require explicit reconciliation, never fresh revisions or operation IDs on an unknown outcome. Missing OPERATION_NOT_FOUND does not prove nonexecution. 422 capacity/balance/daily-limit errors preserve atomicity. 429 schedules no retry. Full Inbox returns pending without losing the original item. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_buy_marketplace_listingA | Purchases the exact listing under its original revision, currency and price. Use when: explicit marketplace actions after reading horizon://docs/marketplace. Not for: automatic trading, price polling or generated replacement operations. Use horizon_get_marketplace_operation to reconcile the original intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Atomic buyer debit, seller net credit, fee and original item transfer. Persist the original intent before sending. Competing buyers cannot both settle. Returns: {receipt,listing,replayed,serverTime} Errors: 409 conflicts require explicit reconciliation, never fresh revisions or operation IDs on an unknown outcome. Missing OPERATION_NOT_FOUND does not prove nonexecution. 422 capacity/balance/daily-limit errors preserve atomicity. 429 schedules no retry. Full Inbox returns pending without losing the original item. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_cancel_marketplace_listingA | Cancels the original listing revision into a protected pending item return. Use when: explicit marketplace actions after reading horizon://docs/marketplace. Not for: automatic trading, price polling or generated replacement operations. Use horizon_get_marketplace_operation to reconcile the original intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt with the persisted original UUID/time/revision. Cancel and receipt replay remain available while trading is disabled. Claim through Inbox, never mint a replacement item. Returns: {receipt,listing,replayed,serverTime} Errors: 409 conflicts require explicit reconciliation, never fresh revisions or operation IDs on an unknown outcome. Missing OPERATION_NOT_FOUND does not prove nonexecution. 422 capacity/balance/daily-limit errors preserve atomicity. 429 schedules no retry. Full Inbox returns pending without losing the original item. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_retry_marketplace_returnA | Attempts one explicitly requested pending return delivery for the current return owner. Use when: explicit marketplace actions after reading horizon://docs/marketplace. Not for: automatic trading, price polling or generated replacement operations. Use horizon_get_marketplace_operation to reconcile the original intent. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: One HTTP attempt. Full Inbox leaves durable pending escrow; successful delivery still needs Inbox claim with inventory space. Does not recreate or claim the original item. Returns: {listing,delivery:pending|delivered|returned,serverTime} Errors: 409 conflicts require explicit reconciliation, never fresh revisions or operation IDs on an unknown outcome. Missing OPERATION_NOT_FOUND does not prove nonexecution. 422 capacity/balance/daily-limit errors preserve atomicity. 429 schedules no retry. Full Inbox returns pending without losing the original item. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_get_inboxA | Reads targeted messages and eligible project broadcasts, counters and server polling interval. Use when: displaying notifications or refreshing after realtime invalidation. Not for: choosing rewards or writing messages from the player client. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: None (read only). Returns: {userId,cursor,revision,broadcastRevision,serverTime,pollAfterSeconds,unchanged,entries,counts,limits}. unchanged=true has empty entries: keep the cached entries. A changed snapshot replaces them completely. Errors: 409 STATE_CONFLICT: retry the same entry ID. UNCLAIMED_REWARD: claim before removal. MAX_BALANCE_REACHED/DAILY_LIMIT_REACHED/INVENTORY_FULL leaves the reward or original item unclaimed. ENTRY_NOT_FOUND after removal/cleanup never grants again. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_mark_inbox_readA | Marks an inbox entry read for the authenticated player. Use when: an explicit player action on an entry returned by horizon_get_inbox. Not for: changing the recipient or inventing attachment amounts. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Marks this entry read without claiming its reward. Returns: Updated complete inbox snapshot. Errors: 409 STATE_CONFLICT: retry the same entry ID. UNCLAIMED_REWARD: claim before removal. MAX_BALANCE_REACHED/DAILY_LIMIT_REACHED/INVENTORY_FULL leaves the reward or original item unclaimed. ENTRY_NOT_FOUND after removal/cleanup never grants again. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_claim_inboxA | Claims an inbox reward once for the authenticated player. Use when: an explicit player action on an entry returned by horizon_get_inbox. Not for: changing the recipient or inventing attachment amounts. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Atomically marks the entry claimed and grants its configured values or restores its exact escrowed original item once. No automatic retries or new action IDs. Overdue unclaimed rewards remain claimable. Returns: {entryId,replayed,inbox,playerValues,items}. Replace the value cache with playerValues; item references are receipts, never instructions to mint an item. Explicitly refresh inventory after a claim. Never apply a reward delta again. Errors: 409 STATE_CONFLICT: retry the same entry ID. UNCLAIMED_REWARD: claim before removal. MAX_BALANCE_REACHED/DAILY_LIMIT_REACHED/INVENTORY_FULL leaves the reward or original item unclaimed. ENTRY_NOT_FOUND after removal/cleanup never grants again. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_remove_inboxA | Removes an eligible inbox entry for the authenticated player. Use when: an explicit player action on an entry returned by horizon_get_inbox. Not for: changing the recipient or inventing attachment amounts. Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: Removes ordinary or already-claimed entries. Unclaimed valuable attachments are protected. Removal does not create a new claim opportunity. Returns: Updated complete inbox snapshot. Errors: 409 STATE_CONFLICT: retry the same entry ID. UNCLAIMED_REWARD: claim before removal. MAX_BALANCE_REACHED/DAILY_LIMIT_REACHED/INVENTORY_FULL leaves the reward or original item unclaimed. ENTRY_NOT_FOUND after removal/cleanup never grants again. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: 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). |
| horizon_submit_feedbackA | Sends a message written by a player (bug report, feature request or comment) to the developer's feedback inbox in the horizOn dashboard. Use when: the player fills in a feedback or bug report form in the game. Not for: crashes and caught exceptions (use horizon_create_crash_report) or technical events the game logs by itself (use horizon_create_log). Requires: a userId from horizon_signup_* or horizon_signin_*; no session token. Side effects: creates one feedback entry per call; a repeat creates a duplicate. Returns: the text "ok" when the entry was stored. Errors: An unknown userId, or one of another API key, is rejected: pass the ID from the sign-in result. 403 when the account's feedback limit is reached: delete old feedback in the dashboard. 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). |
| horizon_create_logA | Writes one server-side log entry (INFO, WARN or ERROR) for a player, visible in the horizOn dashboard's user logs. Use when: the game records a technical event or a handled error for later debugging, for example a failed purchase or a slow load. Not for: crashes and exceptions with a stack trace (use horizon_create_crash_report) or messages written by players (use horizon_submit_feedback). Requires: a userId from horizon_signup_* or horizon_signin_* and the BASIC tier or higher; no session token. Side effects: creates one log entry per call; a repeat creates a duplicate. Returns: {id, createdAt} of the new entry. Errors: 403 on the FREE tier: logs need BASIC or higher, so upgrade or skip logging. 400 for an invalid userId: pass the ID from the sign-in result. 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). |
| horizon_create_crash_reportA | Submits one crash (CRASH), caught exception (NON_FATAL) or freeze (ANR) with device data to horizOn Crash Reporting, grouped by fingerprint. Use when: the game crashed (send on next start) or caught an exception worth tracking. Not for: technical events without a crash (use horizon_create_log) and messages written by players (use horizon_submit_feedback). Requires: a sessionId registered with horizon_create_crash_session for this app run; userId is optional. Side effects: adds one report per call (a repeat adds a duplicate) and marks the session as crashed. Reports with the same fingerprint form one group; a group marked resolved becomes REGRESSED when a newer app version crashes again. Returns: {id, groupId, createdAt}; groupId identifies the crash group in the dashboard. Errors: 400 when a required field is missing or too long: fix it and resend. 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). |
| horizon_create_crash_sessionA | Registers one app run (session) so horizOn can calculate the crash-free session rate. Use when: once at every app start, with a new unique sessionId; keep that ID for horizon_create_crash_report. Not for: reporting the crash itself (use horizon_create_crash_report) or player sign-in sessions (those come from horizon_signin_*). Side effects: records one session per call; a later crash report with the same sessionId marks it as crashed. Returns: {status: 'ok'}. Errors: 400 when a field is missing or too long: fix it and resend. 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). |
| horizon_send_emailA | Queues a transactional email from a dashboard template to one registered player, sent now or at a scheduled time through the developer's own SMTP server. Use when: the game triggers a message to a player, such as a welcome mail or a reminder. Not for: checking delivery (use horizon_get_email_status) or stopping a queued email (use horizon_cancel_email). Requires: an SMTP configuration and the template in the horizOn dashboard, and a recipient with a verified email address. Side effects: queues one new email per call; repeating the call sends the email again, so never repeat it to retry a status check. Returns: {id, status: 'pending', scheduledAt}; pass id to horizon_get_email_status to follow delivery or to horizon_cancel_email to stop it. Errors: 400 for an unknown templateSlug or a recipient without a verified email address: check the slug in the dashboard or pick another user. 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). |
| horizon_cancel_emailA | Cancels a queued email that is still pending (sent now or scheduled) so it is never delivered. Use when: a scheduled email is no longer wanted, for example the player already came back. Not for: emails that are already processing or sent (they cannot be recalled); check with horizon_get_email_status first when unsure. Requires: the emailId from horizon_send_email, sent with the same API key. Side effects: the email is never sent and cannot be restored; to send it later, call horizon_send_email again. Returns: {message: 'Email cancelled'}. Errors: An email that is not pending (already processing, sent, failed or cancelled) or belongs to another API key is rejected: read its state with horizon_get_email_status. 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). |
| horizon_get_email_statusA | Returns the delivery status (pending, processing, sent or failed) and details of one email queued with horizon_send_email. Use when: checking whether a sent or scheduled email was delivered, or why it failed. Not for: sending again (use horizon_send_email only for a new email) or stopping delivery (use horizon_cancel_email). Requires: the emailId from horizon_send_email. Side effects: None (read only). Returns: {id, status, templateSlug, userId, language, scheduledAt, processedAt, errorReason, createdAt}; errorReason explains a failed email (for example SMTP rejected it). Errors: An unknown emailId or one of another API key is rejected: pass the id returned by horizon_send_email. 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). |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| integrate-feature | Generate integration code for a specific horizOn feature in your game engine. |
| setup-auth | Step-by-step guide to set up horizOn authentication in your project. |
| debug-connection | Diagnose and fix horizOn connection issues. |
| explain-feature | Get a detailed explanation of any horizOn feature. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| docs-marketplace | Atomic original-item escrow, exact prices, protected Inbox returns and scoped recovery. |
| docs-chat | Direct/group/project text, metadata-only realtime, incremental snapshots, original receipts and scoped moderation. |
| docs-matches | Opaque turn state, exact revisions, immutable reports, bounded deadlines and original ranked-run recovery. |
| docs-shared-objects | Opaque bounded world data, current permissions, exact revisions and trusted ordinary game notices. |
| docs-items | Unique inventories, bounded property rules, revision-safe edits and atomic server-owned purchases. |
| docs-groups | Bounded guilds, roles, invitations, exact revisions and safe leadership transfer. |
| docs-friends | Atomic requests, friendships, blocks, exact public lookup and revision recovery. |
| docs-achievements | Versioned visible definitions, statistic/manual unlocks and durable Inbox rewards. |
| docs-inbox | Bounded snapshots, broadcasts, protected overdue rewards and atomic claim recovery. |
| docs-statistics | Atomic session counters, safe integers, explicit operation IDs, retries and SDK examples. |
| docs-player-values | Server-owned balances, atomic offer purchases, bounded idempotency, support corrections and safe client adjustments. |
| overview | What is horizOn, core concepts (Account vs User), features, tier system, API structure, and SDKs. |
| docs-auth | Authentication methods (Anonymous, Email, Google), endpoints, SDK code examples, and common errors. |
| docs-leaderboard | Leaderboard score submission, top entries, user rank, entries around user, player profile per entry, validated only boards, with SDK examples. |
| docs-cloud-save | Cloud save/load for JSON and binary data, tier size limits, SDK examples. |
| docs-remote-config | Server-side key-value configuration: feature flags, game balance, A/B testing. SDK examples. |
| docs-localization | Server-side localized strings across 15 languages: per-key translations, single/all fetch, available languages. SDK examples. |
| docs-news | In-game news and announcements with language filtering. SDK examples. |
| docs-gift-codes | Gift code validation and redemption for promotional rewards, including cosmetic unlocks via grants. SDK examples. |
| docs-player-profile | Player avatar, frame and badges from a per-project cosmetics catalog, unlocks via gift code grants, profile in leaderboard entries. SDK examples. |
| docs-validated-actions | Server-checked runs: single-use run tickets with a server seed, SHA-256 input log hash, server-only rules, validated only leaderboards, server-owned player state (currency, daily caps), run start context, evidence upload (input log), admin evidence review with sus packages and package export, rejection codes. SDK examples. |
| docs-feedback | Bug reports, feature requests, and general feedback submission. SDK examples. |
| docs-user-logs | Server-side event and error tracking. Requires BASIC tier or higher. SDK examples. |
| docs-crash-reporting | Crash report submission, session tracking, fingerprinting, breadcrumbs, and auto-regression detection. SDK examples. |
| api-reference | Complete API reference for all horizOn App API endpoints with request/response schemas. |
| quickstart-godot | Step-by-step guide to integrate horizOn in Godot with GDScript examples. |
| quickstart-unity | Step-by-step guide to integrate horizOn in Unity with C# examples. |
| docs-email-sending | Transactional and event-based email delivery to registered users. Templates, scheduling, status tracking, and SMTP integration. SDK examples. |
| quickstart-unreal | Step-by-step guide to integrate horizOn in Unreal Engine 5.5+ with the official horizOn SDK plugin. C++ and Blueprint examples. |
TDQS
Scored across 120 tools
Most tools map cleanly to a resource+action pair, and the descriptions are unusually explicit about 'Use when'/'Not for'. However, there are real collisions: horizon_get_marketplace and horizon_get_marketplace_limits share literally the same described purpose, and horizon_get_shared_collections vs horizon_get_shared_usage vs horizon_query_shared_objects have near-identical descriptions. With 120 tools, an agent must also distinguish many closely-related lifecycle verbs (e.g. start_match_ranked_run vs start_run vs start_match).
Every tool uses the horizon_namespace with a consistent snake_case verb_noun pattern (get_, create_, update_, delete_, list_, submit_, cancel_, accept_). Singular/plural resource names are used predictably (get_item vs get_items). No camelCase or ad-hoc verb mixing.
120 tools is far beyond what an agent can reliably navigate in one surface, placing it in the extreme-mismatch band. Even though the server legitimately spans many subsystems (accounts, groups, friends, inventory, marketplace, chat, matches, leaderboards, cloud save, stats), each domain could be exposed as a smaller focused endpoint set.
Coverage is remarkably thorough: full CRUD plus lifecycle and reconciliation for social, group, inventory, marketplace, chat, matches, leaderboards, validated runs, inbox, profile, cloud save, crash reporting, localization and email. Minor gaps exist (e.g. no explicit evidence-download/delete, limited chat moderation tooling), but nearly every workflow has a complete path with read-after-write recovery tools.