horizOn

io.github.ProjectMakersDEPublished by GitHub account ProjectMakersDEv1.9.1Updated Oct 29, 2026

Docs, live API tools and prompts for the horizOn game backend in Godot, Unity and Unreal.

Overview

AI-generated overview

MCP server for the horizOn game backend: documentation resources, workflow prompts and live player/admin API tools for Godot, Unity and Unreal projects.

What you can do
  • Read bundled horizOn documentation resources and quickstart guides for Godot, Unity and Unreal, plus API reference material
  • Run workflow prompts that walk through feature integration, auth setup, connection debugging and feature explanations
  • Manage player accounts and sessions: anonymous or email signup, sign-in, session checks
  • Work with leaderboards, cloud saves, remote config, localization, news, gift codes, profiles, player values, statistics, achievements, friends and validated runs
  • With an Account Key, administer the dashboard: projects and API keys, remote config, news, email templates, gift codes, users, leaderboards, cloud saves, crash reports, feedback, logs, SMTP and Validated…
When to use it
Use it when building a game or app on the horizOn backend and you want an assistant to look up its docs, generate integration code for a chosen engine, or exercise the live API against a real project.
Requirements
Runs locally via npx from the npm package horizon-mcp (Node.js). HORIZON_API_KEY is required for the live API tools; documentation resources work without it. HORIZON_BASE_URL is optional and defaults to the hosted service. HORIZON_ACCOUNT_API_KEY is optional and enables the dashboard admin tools. Session-bound tools also need a player sign-in and the returned access token. Network access to the horizOn API is required.
Before you install
Two secrets are involved: HORIZON_API_KEY and HORIZON_ACCOUNT_API_KEY, the latter granting scoped dashboard administration and shown only once at creation. Many tools write or replace data: cloud saves replace the previous save, profile updates replace the whole profile, gift codes are consumed, offers and value adjustments debit or credit balances, and validated submits consume tickets. Admin tools can delete records and export evidence packages to local files. Persisted operation IDs must be…

Installation

In SourceWeft

  1. Open horizOn in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

horizOn MCP Server

[npm version] [npm downloads] [License: MIT]

MCP server for horizOn Backend-as-a-Service

Gives AI coding assistants documentation, live API tools, and workflow prompts for game and app development.


Quick Install

Add to your MCP client configuration (Claude Desktop, Cursor, etc.):

json
{  "mcpServers": {    "horizOn": {      "command": "npx",      "args": ["-y", "horizon-mcp"],      "env": {        "HORIZON_API_KEY": "your-api-key-here"      }    }  }}

Features

The server exposes 29 documentation resources, 120 player tools and 4 workflow prompts. An Account Key enables additional scoped admin tools. These counts come from the registered MCP resources, tools and prompts.

Resources

Documentation resources are served directly from the MCP server. No API key required.

URIDescription
horizon://docs/marketplaceAtomic original-item escrow, exact prices, protected Inbox returns and scoped recovery.
horizon://docs/chatDirect/group/project text, metadata-only realtime, incremental snapshots, original receipts and scoped moderation.
horizon://docs/matchesOpaque turn state, exact revisions, immutable reports, bounded deadlines and original ranked-run recovery.
horizon://docs/shared-objectsOpaque bounded world data, current permissions, exact revisions and trusted ordinary game notices.
horizon://docs/itemsUnique inventory, bounded item properties and atomic server-owned purchases
horizon://docs/groupsGuilds, roles, bounded member pages and revision-safe membership actions
horizon://docs/friendsAtomic social relationships, explicit revisions and exact public friend-code lookup
horizon://docs/achievementsVersioned definitions, permanent completion bits and immediate atomic value rewards
horizon://docs/inboxSession inbox, protected rewards, immutable broadcasts, server clock and safe publication retries
horizon://docs/statisticsAtomic session counters, safe integer batches, explicit original IDs and cache/UTC recovery. SDK and admin examples
horizon://docs/player-valuesAtomic balances and offers, stable operation IDs, all three SDKs, safe retries and support corrections
horizon://overviewWhat is horizOn, core concepts (Account vs User), features, tier system, API structure, and SDKs
horizon://docs/authAuthentication methods (Anonymous, Email, Google), endpoints, SDK code examples, and common errors
horizon://docs/leaderboardLeaderboard score submission, top entries, user rank, entries around user, player profile per entry, validated only boards, with SDK examples
horizon://docs/cloud-saveCloud save/load for JSON and binary data, tier size limits, SDK examples
horizon://docs/remote-configServer-side key-value configuration: feature flags, game balance, A/B testing. SDK examples
horizon://docs/localizationServer-side localized strings across 15 languages: per-key translations, single/all fetch, available languages. SDK examples
horizon://docs/newsIn-game news and announcements with language filtering. SDK examples
horizon://docs/gift-codesGift code validation and redemption, cosmetic grants, server-owned value rewards, compact V2 original intents and exact counter strings. SDK examples
horizon://docs/player-profilePlayer avatar, frame and badges from a per-project cosmetics catalog, unlocks via gift code grants, profile in leaderboard entries. SDK examples
horizon://docs/validated-actionsServer-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, start context, evidence upload, admin evidence review with sus packages and package export, rejection codes. SDK examples
horizon://docs/feedbackBug reports, feature requests, and general feedback submission. SDK examples
horizon://docs/user-logsServer-side event and error tracking. Requires BASIC tier or higher. SDK examples
horizon://docs/crash-reportingCrash report submission, session tracking, fingerprinting, breadcrumbs, and auto-regression detection. SDK examples
horizon://api/referenceComplete API reference for all horizOn App API endpoints with request/response schemas
horizon://quickstart/godotStep-by-step guide to integrate horizOn in Godot with GDScript examples
horizon://quickstart/unityStep-by-step guide to integrate horizOn in Unity with C# examples
horizon://docs/email-sendingTransactional and event-based email delivery to registered users. Templates, scheduling, status tracking, and SMTP integration. SDK examples
horizon://quickstart/unrealStep-by-step guide to integrate horizOn in Unreal Engine 5.5+ with the official horizOn SDK plugin. C++ and Blueprint examples

Player tools

Live API tools that call the horizOn backend. Requires a valid API key.

horizon_submit_score, horizon_save_cloud_data, horizon_load_cloud_data, horizon_prepare_gift_code, horizon_redeem_gift_code, horizon_get_profile, horizon_set_profile, horizon_start_run, horizon_submit_validated, horizon_get_state and horizon_upload_evidence also need the player's session: sign in first and pass the returned accessToken as sessionToken.

The four player-value tools also require the same player session. Never generate another operation ID automatically after an uncertain result.

Every tool declares MCP annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint), so clients can tell reads from writes. Examples of destructive tools include horizon_save_cloud_data (replaces the save), horizon_set_profile (replaces the whole profile), horizon_submit_validated (consumes the ticket, can spend balances) and horizon_cancel_email, plus horizon_purchase_player_value_offer and horizon_adjust_player_value (debit or credit exactly once per persisted operation ID). Many read tools that return an object also declare an outputSchema and return structuredContent next to the JSON text. Each description names when to use the tool, which sibling to use instead, what it returns and how to recover from its errors.

ToolDescription
horizon_test_connectionTest connection to the horizOn API (health check)
horizon_signup_anonymousCreate a new anonymous user account
horizon_signup_emailCreate a new user account with email and password
horizon_signin_emailSign in with email and password
horizon_signin_anonymousSign in with an anonymous token
horizon_check_authCheck whether a user session is still valid
horizon_list_leaderboardsList available leaderboard boards for multi-board calls
horizon_submit_scoreSubmit a score to the leaderboard (403 VALIDATED_SUBMIT_REQUIRED on validated only boards)
horizon_get_leaderboard_topGet the top leaderboard entries with each player's profile, optionally by board key
horizon_get_user_rankGet a user's leaderboard rank, optionally by board key
horizon_get_leaderboard_aroundGet leaderboard entries around a user's position, optionally by board key
horizon_save_cloud_dataSave cloud data for a user, optionally only at an expectedRevision (409 on conflict)
horizon_load_cloud_dataLoad cloud save data for a user, with its revision
horizon_get_remote_configGet a single remote config value by key
horizon_get_all_remote_configsGet all remote config values
horizon_get_localizationGet a single localized string by key, optionally for a specific language
horizon_get_all_localizationsGet all localized strings, optionally for a specific language
horizon_get_localization_languagesList the languages that have localizations for the app
horizon_get_newsGet news articles with optional language filtering
horizon_validate_gift_codeValidate a gift code without redeeming it
horizon_prepare_gift_codeRead-only V2 preparation; persist all seven original intent fields before consume
horizon_redeem_gift_codeExplicit consume/retry of that saved intent; current state on replay, no automatic replacement or V1 translation
horizon_get_profileGet a player's profile (avatar, frame, badges), unlocks and the cosmetics catalog
horizon_set_profileReplace a player's whole profile (avatar, frame, up to 3 badges)
horizon_get_player_valuesRead balances and operation window with the active player session
horizon_get_player_value_offersRead configured offers for the player
horizon_purchase_player_value_offerPurchase atomically with a caller-persisted operation ID
horizon_adjust_player_valueAdjust within explicitly enabled limits with a stable ID and reason
horizon_start_runStart a server-checked run: single-use ticket with a server seed, optionally bound to a board and with a start context (game, content, simulation and replay format versions, content digest, initial state as base64)
horizon_submit_validatedSubmit a run result with the ticket and the SHA-256 input log hash (given, or computed locally from base64 bytes or text), optionally with earned server-owned values; returns sus (accepted but over a soft threshold); rejections name their code
horizon_get_stateRead the player's server-owned values (balance, earned today, daily cap per value key); read only
horizon_upload_evidenceUpload the input log (text or base64, encoded locally) of a run whose submit result asked for evidence; rejections name their code
horizon_get_statisticsReads a player's statistics snapshot and server operation window.
horizon_get_statistics_definitionsReads the project's statistics catalog conditionally by version.
horizon_update_statisticsApplies one explicit atomic session batch with a caller-persisted operation ID.
horizon_get_achievementsReads visible achievement definitions and permanent completion bits.
horizon_unlock_achievementUnlocks one configured manual achievement once for the authenticated player.
horizon_deliver_achievement_rewardsReads compatibility reward status for up to eight original achievement keys.
horizon_get_friendsReads friends, incoming/outgoing requests, blocks and current limits.
horizon_find_playerFinds one public player by exact UUID or canonical H- friend code in this project.
horizon_send_friend_requestSends Friend Request using the reviewed player revision.
horizon_accept_friend_requestAccepts Friend Request using the reviewed player revision.
horizon_decline_friend_requestDeclines Friend Request using the reviewed player revision.
horizon_cancel_friend_requestCancels Friend Request using the reviewed player revision.
horizon_remove_friendRemoves Friend using the reviewed player revision.
horizon_block_playerBlocks Player using the reviewed player revision.
horizon_unblock_playerUnblocks Player using the reviewed player revision.
horizon_get_groupsReads my groups using a matching player session.
horizon_get_groupReads group using a matching player session.
horizon_get_group_membersReads group members using a matching player session.
horizon_get_group_pendingReads group pending requests using a matching player session.
horizon_create_groupCreates a fresh server-identified group and its leader atomically.
horizon_update_groupReplaces the complete group metadata and private JSON object.
horizon_join_groupApplies the explicit join group action using the reviewed group revision.
horizon_request_group_joinApplies the explicit request group join action using the reviewed group revision.
horizon_invite_group_playerApplies the explicit invite group player action using the reviewed group revision.
horizon_accept_group_inviteApplies the explicit accept group invite action using the reviewed group revision.
horizon_decline_group_inviteApplies the explicit decline group invite action using the reviewed group revision.
horizon_cancel_group_inviteApplies the explicit cancel group invite action using the reviewed group revision.
horizon_accept_group_requestApplies the explicit accept group request action using the reviewed group revision.
horizon_decline_group_requestApplies the explicit decline group request action using the reviewed group revision.
horizon_cancel_group_requestApplies the explicit cancel group request action using the reviewed group revision.
horizon_leave_groupApplies the explicit leave group action using the reviewed group revision.
horizon_remove_group_memberApplies the explicit remove group member action using the reviewed group revision.
horizon_set_group_member_roleApplies the explicit set group member role action using the reviewed group revision.
horizon_transfer_group_leadershipApplies the explicit transfer group leadership action using the reviewed group revision.
horizon_delete_groupApplies the explicit delete group action using the reviewed group revision.
horizon_get_itemsReads the player's bounded unique item inventory.
horizon_get_item_catalogReads one bounded item template page, including archived templates.
horizon_adjust_itemAdjusts Item Properties using the reviewed inventory revision.
horizon_equip_itemSets Item Equipped State using the reviewed inventory revision.
horizon_discard_itemDiscards Item using the reviewed inventory revision.
horizon_get_shared_collectionsReads one permanent collection catalog page.
horizon_get_shared_usageReads the current player's count and creation precondition for one collection.
horizon_get_shared_objectReads one object under current permissions.
horizon_query_shared_objectsReads one bounded metadata-selected object page.
horizon_create_shared_objectCreates one server-ID object using the original owner-usage revision.
horizon_update_shared_objectReplaces one object's opaque bytes and configured search data under its exact revision.
horizon_delete_shared_objectDeletes one exact-revision object and refunds its stored charge.
horizon_get_matchesReads the player's bounded active, invited and recent match summaries.
horizon_get_match_limitsReads the player's five-tier limits and project capabilities.
horizon_find_open_matchesReads one strength-filtered open-lobby page under current blocks and active-owner checks.
horizon_get_matchReads one currently authorized match snapshot.
horizon_create_matchCreates one server-ID lobby under the original player-ledger revision.
horizon_join_matchExecutes join match under the exact original revision.
horizon_decline_match_inviteExecutes decline match invitation under the exact original revision.
horizon_start_matchExecutes start match under the exact original revision.
horizon_submit_match_turnExecutes submit match turn under the exact original revision.
horizon_advance_match_timeoutExecutes advance match timeout under the exact original revision.
horizon_leave_matchExecutes leave match under the exact original revision.
horizon_cancel_matchExecutes cancel match lobby under the exact original revision.
horizon_report_match_resultRecords this participant's immutable report for the frozen final state.
horizon_start_match_ranked_runCreates or recovers one original match-bound validated run after complete consensus.
horizon_get_chat_limitsReads five-tier bounds, current moderation and hosted capabilities.
horizon_open_chat_channelOpens deterministic direct, group or project chat under current permissions.
horizon_sync_chat_channelReads an authorized incremental snapshot after subscription resync/event or explicit user action.
horizon_send_chat_messageSends plain text once or explicitly replays the exact original operation.
horizon_get_chat_operationReads the current player's retained original send receipt.
horizon_report_chat_messageReports one currently visible message with the original reason.
horizon_get_marketplace_limitsReads current own marketplace state or configured limits.
horizon_get_marketplaceReads current own marketplace state or configured limits.
horizon_get_marketplace_rulesReads one revision-consistent bounded rule page.
horizon_query_marketplace_listingsReads one bounded active-listing page by item and price.
horizon_get_marketplace_listingReads one authorized listing or original own operation receipt.
horizon_get_marketplace_operationReads one authorized listing or original own operation receipt.
horizon_create_marketplace_listingLists one original unequipped item at the explicitly approved price and fee configuration.
horizon_buy_marketplace_listingPurchases the exact listing under its original revision, currency and price.
horizon_cancel_marketplace_listingCancels the original listing revision into a protected pending item return.
horizon_retry_marketplace_returnAttempts one explicitly requested pending return delivery for the current return owner.
horizon_get_inboxReads targeted messages and eligible project broadcasts, counters and server polling interval.
horizon_mark_inbox_readMarks an inbox entry read for the authenticated player.
horizon_claim_inboxClaims an inbox reward once for the authenticated player.
horizon_remove_inboxRemoves an eligible inbox entry for the authenticated player.
horizon_submit_feedbackSubmit user feedback (bug reports, feature requests)
horizon_create_logCreate a server-side log entry (INFO, WARN, ERROR)
horizon_create_crash_reportSubmit a crash report (grouped by fingerprint, with regression detection)
horizon_create_crash_sessionRegister a game session for the crash-free rate
horizon_send_emailSend a transactional email to a registered user from a template
horizon_cancel_emailCancel a pending or scheduled email
horizon_get_email_statusGet the status of a sent or scheduled email

Prompts (4 prompts)

Workflow prompts that guide AI assistants through common horizOn tasks.

PromptDescription
integrate-featureGenerate integration code for a specific horizOn feature in your game engine
setup-authStep-by-step guide to set up horizOn authentication in your project
debug-connectionDiagnose and fix horizOn connection issues
explain-featureGet a detailed explanation of any horizOn feature

Configuration

VariableRequiredDescription
HORIZON_API_KEYYes (for tools)Your horizOn API key. Get one at horizon.pm
HORIZON_BASE_URLNoAPI base URL. Defaults to https://horizon.pm
HORIZON_ACCOUNT_API_KEYNoAccount Key for additional scoped dashboard admin tools

Resources (documentation) work without an API key. Only the live API tools require authentication. Session-bound tools also require the matching player session and declare userId and sessionToken in their input schemas.

Feature availability follows the selected backend and project configuration. Realtime, chat, Validated Actions and ranked match validation require hosted horizOn. The self-hosted simpleServer supports a subset of the REST APIs. MCP tools make explicit HTTP calls and do not create a background WebSocket connection, polling loop or automatic trading/retry process.

Admin Tools (v1.2+)

With an Account Key (creatable in your horizOn Dashboard -> API Keys -> Create -> Account Key), the MCP server exposes additional tools that let Claude manage your dashboard -- projects, remote config, news, email templates, gift codes, users, leaderboards, cloud-save data, crash reports, feedback, user logs, SMTP, and Validated Actions (rules, runs, player values and the evidence review).

How to get your Account Key

  1. Log in to your horizOn Dashboard
  2. Navigate to API Keys in the sidebar
  3. Click Create API Key
  4. Select Account Key as the key type
  5. Choose whether the key can access the entire account, a single Project API Key, or selected feature groups
  6. Click Create -- your key will be shown once. Copy it immediately.
  7. Add the key to your MCP configuration (see Setup below)

Setup

Add both keys to your MCP client configuration:

json
{  "mcpServers": {    "horizOn": {      "command": "npx",      "args": ["-y", "horizon-mcp"],      "env": {        "HORIZON_API_KEY": "your-project-key (for player-facing tools)",        "HORIZON_ACCOUNT_API_KEY": "your-account-key (for dashboard tools)"      }    }  }}

Both can be set together or individually. Admin tools only register when the account key is set -- otherwise the server exposes only the original player-facing tools.

Scope

Account Keys inherit your account's tier (FREE/BASIC/PLUS/PRO/ENTERPRISE) -- they grant no extra privileges. A key can be full-account, limited to a single Project API Key, limited to selected feature groups, or both. Platform-admin-only endpoints (Blog, Banner, System-Config) are automatically unreachable. A handful of ultra-sensitive endpoints (account deletion, credentials change, key management itself, subscription cancel) require a dashboard session and cannot be called via an Account Key.

When a key is project-scoped, the backend enforces that scope on direct HTTP calls too. Account-wide endpoints or ID-only endpoints that cannot prove project context are rejected for project-scoped keys.

Tool Groups

Admin tools carry the same annotations as the player tools: list, get and statistics tools are read only, update and delete tools are marked destructive.

PrefixDescription
horizon_admin_statistics_*, horizon_admin_achievements_*Configure definitions and inspect owned player progression
horizon_admin_friends_*, horizon_admin_groups_*Inspect scoped relationships, groups and configured limits
horizon_admin_items_*, horizon_admin_shared_*Manage item catalogs, owned collections and explicit cleanup
horizon_admin_match_*, horizon_admin_matches_*, horizon_admin_chat_*Inspect asynchronous matches and manage hosted chat/moderation
horizon_admin_marketplace_*, horizon_admin_inbox_*Manage marketplace rules, scoped operations and durable inbox notices
horizon_admin_localization_*Manage scoped localization entries
horizon_admin_player_values_*Read/replace catalogue with If-Match, inspect minimal guards and correct balances with an original note/hash
horizon_admin_projects_*Project API key management (create/update/regenerate/revoke/delete)
horizon_admin_remoteconfig_*Remote config CRUD
horizon_admin_news_*Multilingual news (titles/messages as {lang: content})
horizon_admin_emailtemplates_*Multilingual email templates with variables
horizon_admin_giftcodes_*Gift code CRUD + revoke
horizon_admin_users_*User management + statistics (no full-list needed)
horizon_admin_leaderboard_*Leaderboard entries + statistics
horizon_admin_cloudsave_*Cloud save data + statistics
horizon_admin_crashes_*Crash groups, reports, statistics
horizon_admin_feedback_*Read user feedback
horizon_admin_userlogs_*Read user logs
horizon_admin_smtp_*Account SMTP configuration (password always returned masked)
horizon_admin_validated_evidence_*Validated Actions evidence review: list (top N records or, with sus: true, sus packages), quota, metadata (with susPackage), log download (base64 or hashes only), package export (ZIP written to a local file, with the integrity headers), delete
horizon_admin_validated_rules_*, _usage_get, _runs_list, _state_*Validated Actions configuration: rule set per Project API key (get, replace, delete), run capacity of the hour, recent runs with rejection codes (filter sus), server-owned player values (read, support correction)

What is horizOn?

horizOn is a multi-tenant Backend-as-a-Service platform built for game and app developers. It provides a managed backend so developers can focus on building their game or app instead of server infrastructure.

Core features:

  • Authentication (Anonymous, Email, Google, Apple)
  • Leaderboards
  • Cloud Save
  • Remote Config
  • Localization
  • News and Announcements
  • Gift Codes
  • Player Profile (avatar, frame, badges)
  • Player Values (atomic configured purchases, safe adjustments, minimal public replay guards)
  • Statistics, inbox rewards and achievements
  • Friends, blocklists and groups
  • Item catalogs, unique inventory and marketplace escrow/trades
  • Shared objects with scoped permissions and asynchronous matches
  • Hosted chat, with realtime managers provided by the native SDKs
  • Validated Actions (server-checked runs, validated only leaderboards, server-owned currency)
  • User Feedback
  • User Logs
  • Crash Reporting
  • Email Sending

Learn more at horizon.pm. Install this MCP server via npm.

Supported Engines

  • Godot 4.5+ -- GDScript SDK
  • Unity 6 -- C# SDK
  • Unreal Engine 5.5+ -- C++ and Blueprint SDK

Development

bash
# Clone the repositorygit clone https://github.com/ProjectMakersDE/horizOn-mcp.gitcd horizOn-mcp
# Install dependenciesnpm install
# Start the server (development mode)npm run dev
# Build for productionnpm run build
# Run testsnpm test

License

MIT

Statistics tools

horizon_get_statistics, horizon_get_statistics_definitions and horizon_update_statistics expose explicit session counters. Persist the original timestamp:UUID and immutable batch before posting; after a timeout reuse that intent, never generate a replacement ID automatically. Read horizon://docs/statistics or use integrate-feature with feature=statistics for engine guidance. Four Account Key tools inspect/replace definitions with If-Match, inspect one owned player and read tier limits (horizon_admin_statistics_*). Statistics are separate from player values.

Inbox tools

Four player tools read, mark read, claim and remove inbox entries with the active session. Four horizon_admin_inbox_* tools manage immutable broadcasts or inspect an owned player with an INBOX-scoped Account Key. Read horizon://docs/inbox before publishing: persist the exact intent, use serverTime for new timestamps, and retain the original ID after an uncertain response. Protected rewards never silently expire or disappear.

Achievements

horizon_get_achievements, horizon_unlock_achievement and horizon_deliver_achievement_rewards expose permanent completion and immediate atomic Player Values rewards. The compatibility delivery tool only reads legacy status. Four horizon_admin_achievements_* tools manage the versioned catalog and inspect owned players with ACHIEVEMENTS scope. Read horizon://docs/achievements for hidden-definition caching, original-key replay and verified cold settlement of legacy originals. New unlocks create no personal Inbox reward/history copy. Engine prompts accept feature=achievements.

Friends

horizon_get_friends, horizon_find_player and seven explicit social-action tools preserve reviewed revisions and pending request IDs. Two read-only horizon_admin_friends_* tools inspect owned state and current limits. Read horizon://docs/friends; both engine prompts accept feature=friends. After an uncertain response, read and reconcile the snapshot before any new player-confirmed action.

Groups

Twenty player tools cover group snapshots, bounded member pages, pending entries, creation, metadata and fourteen explicit membership/role actions. Six read-only horizon_admin_groups_* tools inspect owned projects. All writes preserve reviewed revisions and pending IDs. Read horizon://docs/groups; both engine prompts accept feature=groups. Uncertain writes are never retried automatically.

Items

Five player tools read inventory/catalog and explicitly adjust, equip or discard an instance. Four horizon_admin_items_* tools inspect owned state, page the catalog, edit one template using If-Match and read tier limits. Player-value offers accept bounded itemRewards and grant them atomically with the debit. Read horizon://docs/items; both engine prompts accept feature=items.

Shared Objects

Seven player tools expose bounded opaque shared objects, typed queries and exact-revision writes. Ten horizon_admin_shared_* tools manage owned collections and explicit cleanup. A separate horizon_admin_inbox_send_ordinary tool uses INBOX scope for a trusted backend's durable notice intent. Read horizon://docs/shared-objects; both engine prompts accept feature=shared-objects. Native SDK/PHP/deployment readiness must be checked against the installed version.

Configured policies and technical frames

The new feature tools forward higher/lower current System Config policies rather than treating tier defaults as maxima. Groups expose eleven policies; explicit pages may exceed50 and the default page1 remains usable after lowering. PV supports256 lifetime identities, configured offer counts above1000 and up to256 correction keys. Achievement catalogs can exceed the former 500-key default within current active/lifetime policies and their1 MiB frame. Retained responses are passed through completely after reductions; MCP never truncates a result to a current quota.

Technical bounds stay separate: Shared has a1 MiB decoded object/query envelope and1402200-byte write frame; Matches accepts up to14999552 decoded state bytes (14648KiB) within its20003500-byte create/turn frame. Groups use the complete16 MiB BSON envelope and100663296-byte create/update HTTP frame, with configured name/description/data/depth policies. Fixed item property/template/ delta/grant formats, three Shared search fields and current Chat text/window bounds remain. Validation adds no limits fetch, pagination, retry or database request. These are representation bounds, not a throughput, memory-use or cluster-admission guarantee.

Asynchronous Matches

Fourteen player tools and seven scoped admin tools cover bounded lobbies, opaque turns, immutable result reports and original match-bound ranked-run recovery. Writes keep exact revisions and make one HTTP attempt. Consensus does not award automatic rewards. simpleServer supports ordinary REST and explicitly excludes ranked validation/realtime. Read horizon://docs/matches; engine prompts accept feature=matches.

Hosted Chat (TASK-1014)

Six app tools cover capabilities, deterministic channel open, incremental sync, original send, receipt reconciliation and reporting. Twelve CHAT-scoped admin tools expose word filters, metadata/messages, report moderation, mute/ban and bounded cleanup. Read horizon://docs/chat; engine prompts accept feature=chat. simpleServer explicitly returns 501 NOT_SUPPORTED for chat. These HTTP tools do not create a background WebSocket connection or polling loop. Use the existing native realtime managers for interactive feeds.

Marketplace

The ten player and fourteen scoped operator tools preserve original-item escrow, atomic currency settlement, exact original intent and lossless Inbox returns. Read horizon://docs/marketplace for routes, original revisions, five-tier limits and recovery. Engine prompts accept feature=marketplace. No automatic trading, price polling or retries.

Source: README.md at commit 216d21c

Tools

120

horizon_test_connection

Test Connection

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).

Takes no parameters.

horizon_signup_anonymous

Sign Up Anonymously

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).

ParametersdisplayNamerequired

horizon_signup_email

Sign Up with Email

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).

ParametersemailrequiredpasswordrequireddisplayNamerequired

horizon_signin_email

Sign In with Email

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).

Parametersemailrequiredpasswordrequired

horizon_signin_anonymous

Sign In Anonymously

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).

ParametersanonymousTokenrequired

horizon_check_auth

Check Authentication

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).

ParametersuserIdrequiredsessionTokenrequired

horizon_list_leaderboards

List Leaderboard Boards

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).

Takes no parameters.

horizon_submit_score

Submit Score

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).

ParametersscorerequireduserIdrequiredsessionTokenrequiredleaderboardKey

horizon_get_leaderboard_top

Get Leaderboard Top

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).

ParameterslimituserIdrequiredleaderboardKey

horizon_get_user_rank

Get User Rank

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).

ParametersuserIdrequiredleaderboardKey

horizon_get_leaderboard_around

Get Leaderboard Around User

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).

ParametersrangeuserIdrequiredleaderboardKey

horizon_save_cloud_data

Save Cloud Data

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).

ParametersdatarequireduserIdrequiredsessionTokenrequiredexpectedRevision

horizon_load_cloud_data

Load Cloud Data

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).

ParametersuserIdrequiredsessionTokenrequired

horizon_get_remote_config

Get Remote Config

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).

Parameterskeyrequired

horizon_get_all_remote_configs

Get All Remote Configs

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).

Takes no parameters.

horizon_get_localization

Get Localization

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).

Parameterskeyrequiredlang

horizon_get_all_localizations

Get All Localizations

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).

Parameterslang

horizon_get_localization_languages

Get Localization Languages

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).

Takes no parameters.

horizon_get_news

Get News

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).

ParameterslimitlanguageCode

horizon_validate_gift_code

Validate Gift Code

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).

ParameterscoderequireduserIdrequired

horizon_prepare_gift_code

Prepare Gift Code Intent

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).

ParameterscoderequireduserIdrequiredsessionTokenrequired

horizon_redeem_gift_code

Redeem Prepared Gift Code

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).

ParameterscodeintentuserIdsessionTokenrequiredidempotencyId

horizon_get_profile

Get Player Profile

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).

ParametersuserIdrequiredsessionTokenrequired

horizon_set_profile

Set Player Profile

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).

ParametersbadgesuserIdrequiredframeIdavatarIdsessionTokenrequired

horizon_get_player_values

Get Player Values

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).

ParametersuserIdrequiredsessionTokenrequired

horizon_get_player_value_offers

Get Player Value Offers

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).

ParametersuserIdrequiredsessionTokenrequired

horizon_purchase_player_value_offer

Purchase Player Value Offer

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).

ParametersuserIdrequiredofferKeyrequiredoperationIdrequiredsessionTokenrequired

horizon_adjust_player_value

Adjust Player Value

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).

ParameterskeyrequiredamountrequiredreasonrequireduserIdrequiredoperationIdrequiredsessionTokenrequired

horizon_start_run

Start Validated Run

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

ParametersuserIdrequiredgameVersionsessionTokenrequiredcontentDigestcontentVersionleaderboardKeysimulationVersioninitialStateBase64replayFormatVersion

horizon_submit_validated

Submit Validated Run

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 ei

ParametersscorestageearnedticketrequireduserIdrequiredinputLoginputLogHashsessionTokenrequiredinputLogBase64leaderboardKey

horizon_get_state

Get Player State

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).

ParametersuserIdrequiredsessionTokenrequired

horizon_upload_evidence

Upload Validated Run Evidence

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

ParametersrunIdrequireduserIdrequiredinputLogsessionTokenrequiredinputLogBase64

horizon_get_statistics

Get Player Statistics

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).

ParametersuserIdrequiredsessionTokenrequireddefinitionVersion

horizon_get_statistics_definitions

Get Statistics Definitions

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).

ParameterssessionTokenrequireddefinitionVersion

horizon_update_statistics

Update Player Statistics Batch

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>:<UUID>; 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).

ParametersuserIdrequiredupdatesrequiredoperationIdrequiredsessionTokenrequired

horizon_get_achievements

Get Player Achievements

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).

ParametersuserIdrequiredsessionTokenrequireddefinitionVersion

horizon_unlock_achievement

Unlock Manual Achievement

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).

ParameterskeyrequireduserIdrequiredsessionTokenrequired

horizon_deliver_achievement_rewards

Inspect Legacy Achievement Reward Status

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).

ParameterskeysrequireduserIdrequiredsessionTokenrequired

horizon_get_friends

Get Friends

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).

ParametersuserIdrequiredsessionTokenrequired

horizon_find_player

Find Player by Friend Code

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).

ParametersqueryrequireduserIdrequiredsessionTokenrequired

horizon_send_friend_request

Send Friend Request

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).

ParametersuserIdrequiredsessionTokenrequiredtargetUserIdrequiredexpectedRevisionrequired

horizon_accept_friend_request

Accept Friend Request

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).

ParametersuserIdrequiredrequestIdrequiredsessionTokenrequiredtargetUserIdrequiredexpectedRevisionrequired

horizon_decline_friend_request

Decline Friend Request

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).

ParametersuserIdrequiredrequestIdrequiredsessionTokenrequiredtargetUserIdrequiredexpectedRevisionrequired

horizon_cancel_friend_request

Cancel Friend Request

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).

ParametersuserIdrequiredrequestIdrequiredsessionTokenrequiredtargetUserIdrequiredexpectedRevisionrequired

horizon_remove_friend

Remove Friend

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).

ParametersuserIdrequiredsessionTokenrequiredtargetUserIdrequiredexpectedRevisionrequired

horizon_block_player

Block Player

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).

ParametersuserIdrequiredsessionTokenrequiredtargetUserIdrequiredexpectedRevisionrequired

horizon_unblock_player

Unblock Player

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).

ParametersuserIdrequiredsessionTokenrequiredtargetUserIdrequiredexpectedRevisionrequired

horizon_get_groups

Get My Groups

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).

ParametersuserIdrequiredsessionTokenrequired

horizon_get_group

Get Group

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).

ParametersuserIdrequiredgroupIdrequiredsessionTokenrequired

horizon_get_group_members

Get Group Members

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).

ParameterslimituserIdrequiredgroupIdrequiredafterUserIdsessionTokenrequired

horizon_get_group_pending

Get Group Pending Requests

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).

ParametersuserIdrequiredgroupIdrequiredsessionTokenrequired

horizon_create_group

Create Group

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).

ParametersdatarequirednamerequireduserIdrequiredjoinModerequireddescriptionrequiredsessionTokenrequiredexpectedPlayerRevisionrequired

horizon_update_group

Update Group

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).

ParametersdatarequirednamerequireduserIdrequiredgroupIdrequiredjoinModerequireddescriptionrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_join_group

join group

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).

ParametersuserIdrequiredgroupIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_request_group_join

request group join

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).

ParametersuserIdrequiredgroupIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_invite_group_player

invite group player

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).

ParametersuserIdrequiredgroupIdrequiredsessionTokenrequiredtargetUserIdrequiredexpectedRevisionrequired

horizon_accept_group_invite

accept group invite

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).

ParametersuserIdrequiredgroupIdrequiredrequestIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_decline_group_invite

decline group invite

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).

ParametersuserIdrequiredgroupIdrequiredrequestIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_cancel_group_invite

cancel group invite

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).

ParametersuserIdrequiredgroupIdrequiredrequestIdrequiredsessionTokenrequiredtargetUserIdrequiredexpectedRevisionrequired

horizon_accept_group_request

accept group request

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).

ParametersuserIdrequiredgroupIdrequiredrequestIdrequiredsessionTokenrequiredtargetUserIdrequiredexpectedRevisionrequired

horizon_decline_group_request

decline group request

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).

ParametersuserIdrequiredgroupIdrequiredrequestIdrequiredsessionTokenrequiredtargetUserIdrequiredexpectedRevisionrequired

horizon_cancel_group_request

cancel group request

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).

ParametersuserIdrequiredgroupIdrequiredrequestIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_leave_group

leave group

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).

ParametersuserIdrequiredgroupIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_remove_group_member

remove group member

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).

ParametersuserIdrequiredgroupIdrequiredsessionTokenrequiredtargetUserIdrequiredexpectedRevisionrequired

horizon_set_group_member_role

set group member role

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).

ParametersrolerequireduserIdrequiredgroupIdrequiredsessionTokenrequiredtargetUserIdrequiredexpectedRevisionrequired

horizon_transfer_group_leadership

transfer group leadership

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).

ParametersuserIdrequiredgroupIdrequiredsessionTokenrequiredtargetUserIdrequiredexpectedRevisionrequired

horizon_delete_group

delete group

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).

ParametersuserIdrequiredgroupIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_get_items

Get Player Inventory

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).

ParametersuserIdrequiredsessionTokenrequired

horizon_get_item_catalog

Get Item Catalog Page

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).

ParameterslimituserIdrequiredafterKeysessionTokenrequiredcatalogRevision

horizon_adjust_item

Adjust Item Properties

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).

ParametersuserIdrequiredchangesrequiredinstanceIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_equip_item

Set Item Equipped State

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).

ParametersuserIdrequiredequippedrequiredinstanceIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_discard_item

Discard Item

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).

ParametersuserIdrequiredinstanceIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_get_shared_collections

Get Shared Object Collections

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).

ParameterslimituserIdrequiredafterKeysessionTokenrequiredcatalogRevision

horizon_get_shared_usage

Get Shared Object Owner Usage

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).

ParametersuserIdrequiredcollectionrequiredsessionTokenrequired

horizon_get_shared_object

Get Shared Object

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).

ParametersuserIdrequiredobjectIdrequiredcollectionrequiredsessionTokenrequired

horizon_query_shared_objects

Query Shared Objects

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).

ParametersqueryrequireduserIdrequiredcollectionrequiredsessionTokenrequired

horizon_create_shared_object

Create Shared Object

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).

ParameterssearchrequireduserIdrequiredgroupIdpositioncollectionrequireddataBase64requiredsessionTokenrequiredexpectedRevisionrequired

horizon_update_shared_object

Update Shared Object

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).

ParameterssearchrequireduserIdrequiredobjectIdrequiredpositioncollectionrequireddataBase64requiredsessionTokenrequiredexpectedRevisionrequired

horizon_delete_shared_object

Delete Shared Object

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).

ParametersuserIdrequiredobjectIdrequiredcollectionrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_get_matches

Get My Matches

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).

ParametersuserIdrequiredsessionTokenrequired

horizon_get_match_limits

Get Match Limits

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).

ParametersuserIdrequiredsessionTokenrequired

horizon_find_open_matches

Find Open Matches

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).

ParameterslimitcursoruserIdrequiredmaxStrengthrequiredminStrengthrequiredsessionTokenrequired

horizon_get_match

Get Match

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).

ParametersuserIdrequiredmatchIdrequiredsessionTokenrequired

horizon_create_match

Create Match

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).

ParametersuserIdrequiredsettingsrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_join_match

Join Match

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).

ParametersuserIdrequiredmatchIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_decline_match_invite

Decline Match Invitation

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).

ParametersuserIdrequiredmatchIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_start_match

Start Match

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).

ParametersuserIdrequiredmatchIdrequiredturnOrderrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_submit_match_turn

Submit Match Turn

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).

ParametersfinishrequireduserIdrequiredmatchIdrequireddataBase64requiredsessionTokenrequiredexpectedRevisionrequired

horizon_advance_match_timeout

Advance Match Timeout

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).

ParametersuserIdrequiredmatchIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_leave_match

Leave Match

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).

ParametersuserIdrequiredmatchIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_cancel_match

Cancel Match Lobby

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).

ParametersuserIdrequiredmatchIdrequiredsessionTokenrequiredexpectedRevisionrequired

horizon_report_match_result

Report Match Result

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).

ParametersuserIdrequiredmatchIdrequiredwinnerIdsrequiredresultBase64requiredsessionTokenrequiredfinalStateRevisionrequired

horizon_start_match_ranked_run

Start or Recover Match Ranked Run

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).

ParametersuserIdrequiredmatchIdrequiredsessionTokenrequiredfinalStateRevisionrequired

horizon_get_chat_limits

Get Chat Limits

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).

ParametersuserIdrequiredsessionTokenrequired

horizon_open_chat_channel

Open Chat Channel

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).

ParameterskindrequiredpeerIduserIdrequiredgroupIdsessionTokenrequired

horizon_sync_chat_channel

Sync Chat Channel

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).

ParametersepochrequireduserIdrequiredchannelIdrequiredsessionTokenrequiredknownMessageIdsrequired

horizon_send_chat_message

Send Original Chat Message

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).

ParameterstextrequireduserIdrequiredissuedAtrequiredchannelIdrequiredoperationIdrequiredsessionTokenrequired

horizon_get_chat_operation

Get Original Chat Receipt

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).

ParametersuserIdrequiredoperationIdrequiredsessionTokenrequired

horizon_report_chat_message

Report Chat Message

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).

ParametersreasonrequireduserIdrequiredchannelIdrequiredmessageIdrequiredsessionTokenrequired

horizon_get_marketplace_limits

Get Marketplace Limits

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).

ParametersuserIdrequiredsessionTokenrequired

horizon_get_marketplace

Get Own Marketplace

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).

ParametersuserIdrequiredsessionTokenrequired

horizon_get_marketplace_rules

Get Marketplace Price Rules

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).

ParametersafterlimituserIdrequiredsessionTokenrequiredcatalogRevision

horizon_query_marketplace_listings

Query Marketplace Listings

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).

ParameterslimitcursoruserIdrequireditemKeymaxPriceminPricesessionTokenrequired

horizon_get_marketplace_listing

Get Marketplace Listing

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).

ParametersuserIdrequiredlistingIdrequiredsessionTokenrequired

horizon_get_marketplace_operation

Get Original Marketplace Receipt

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).

ParametersuserIdrequiredoperationIdrequiredsessionTokenrequired

horizon_create_marketplace_listing

Escrow Original Item for Sale

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).

ParameterspricerequireduserIdrequiredissuedAtrequiredinstanceIdrequiredoperationIdrequiredsessionTokenrequireddurationSecondsrequiredexpectedConfigRevisionrequiredexpectedInventoryRevisionrequired

horizon_buy_marketplace_listing

Buy Original Marketplace Item

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).

ParametersuserIdrequiredissuedAtrequiredlistingIdrequiredoperationIdrequiredsessionTokenrequiredexpectedPricerequiredexpectedCurrencyKeyrequiredexpectedListingRevisionrequired

horizon_cancel_marketplace_listing

Cancel Own Marketplace Listing

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).

ParametersuserIdrequiredissuedAtrequiredlistingIdrequiredoperationIdrequiredsessionTokenrequiredexpectedListingRevisionrequired

horizon_retry_marketplace_return

Attempt Original Item Return Delivery

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).

ParametersuserIdrequiredlistingIdrequiredsessionTokenrequired

horizon_get_inbox

Get Player Inbox

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).

ParameterssinceuserIdrequiredsessionTokenrequired

horizon_mark_inbox_read

Mark Inbox Entry Read

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).

ParametersuserIdrequiredentryIdrequiredsessionTokenrequired

horizon_claim_inbox

Claim Inbox Reward

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).

ParametersuserIdrequiredentryIdrequiredsessionTokenrequired

horizon_remove_inbox

Remove Inbox Entry

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).

ParametersuserIdrequiredentryIdrequiredsessionTokenrequired

horizon_submit_feedback

Submit Feedback

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).

ParametersemailtitlerequireduserIdrequiredmessagerequiredcategorydeviceInfo

horizon_create_log

Create Log

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).

ParameterstyperequireduserIdrequiredmessagerequirederrorCode

horizon_create_crash_report

Create Crash Report

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).

ParametersosrequiredtyperequireduserIdmessagerequiredplatformrequiredsessionIdrequiredappVersionrequiredcustomKeyssdkVersionrequiredstackTracebreadcrumbsdeviceModelrequired+2 more

horizon_create_crash_session

Create Crash Session

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).

ParametersuserIdplatformrequiredsessionIdrequiredappVersionrequired

horizon_send_email

Send Email

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).

ParametersuserIdrequiredlanguagerequiredvariablesrequiredscheduledAttemplateSlugrequired

horizon_cancel_email

Cancel Email

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).

ParametersemailIdrequired

horizon_get_email_status

Get Email Status

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).

ParametersemailIdrequired

Version history

7
  1. v1.9.1LatestOct 23, 2026
  2. v1.8.1Oct 10, 2026
  3. v1.8.0Oct 10, 2026
  4. v1.7.0Oct 2, 2026
  5. v1.6.0Oct 1, 2026
  6. v1.5.5Sep 29, 2026
  7. v1.5.4Sep 28, 2026

Score

90% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts
  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts