Skip to main content
Glama

Redeem Prepared Gift Code

horizon_redeem_gift_code
Idempotent

Consumes a saved V2 gift-code intent once and returns authoritative campaign and player state on replay, letting uncertain redemptions be retried without preparing a new sequence.

Instructions

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

Input Schema

NameRequiredDescriptionDefault
codeNoObsolete V1 argument, rejected with UPGRADE_REQUIRED; use the original saved intent
intentNoRequired V2 recovery object: the exact seven fields durably saved from horizon_prepare_gift_code; never retarget or advance it
userIdNoObsolete V1 argument, rejected with UPGRADE_REQUIRED; the original owner is inside intent
sessionTokenYesCurrent accessToken of the intent's original user, sent only as a Bearer header
idempotencyIdNoObsolete arbitrary V1 ID, never translated to a V2 sequence; rejected without HTTP

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed6 schema fields changedv1.9.1
    • changedInput schema / properties / code / description
      Previous value: -"Gift code as the player typed it (max 50 characters)"New value: +"Obsolete V1 argument, rejected with UPGRADE_REQUIRED; use the original saved intent"
    • addedInput schema / properties / idempotencyId
      Added value: +{
      +  "description": "Obsolete arbitrary V1 ID, never translated to a V2 sequence; rejected without HTTP",
      +  "type": "string"
      +}
    • addedInput schema / properties / intent
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Required V2 recovery object: the exact seven fields durably saved from horizon_prepare_gift_code; never retarget or advance it",
      +  "properties": {
      +    "campaignId": {
      +      "format": "uuid",
      +      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$",
      +      "type": "string"
      +    },
      +    "code": {
      +      "maxLength": 50,
      +      "minLength": 1,
      +      "type": "string"
      +    },
      +    "configRevision": {
      +      "maxLength": 19,
      +      "pattern": "^(0|[1-9][0-9]*)$",
      +      "type": "string"
      +    },
      +    "expectedCount": {
      +      "maxLength": 19,
      +      "pattern": "^(0|[1-9][0-9]*)$",
      +      "type": "string"
      +    },
      +    "projectScope": {
      +      "pattern": "^[a-f0-9]{64}$",
      +      "type": "string"
      +    },
      +    "protocolVersion": {
      +      "const": 2,
      +      "type": "number"
      +    },
      +    "userId": {
      +      "format": "uuid",
      +      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "protocolVersion",
      +    "projectScope",
      +    "userId",
      +    "code",
      +    "campaignId",
      +    "expectedCount",
      +    "configRevision"
      +  ],
      +  "type": "object"
      +}
    • changedInput schema / properties / sessionToken / description
      Previous value: -"accessToken from horizon_signin_email or horizon_signin_anonymous for this userId; sent as a Bearer session"New value: +"Current accessToken of the intent's original user, sent only as a Bearer header"
    • changedInput schema / properties / userId / description
      Previous value: -"Player user ID (UUID) from horizon_signup_* or horizon_signin_*"New value: +"Obsolete V1 argument, rejected with UPGRADE_REQUIRED; the original owner is inside intent"
    • changedInput schema / required
      Previous value: -[
      -  "code",
      -  "userId",
      -  "sessionToken"
      -]New value: +[
      +  "sessionToken"
      +]
  2. Changed5 schema fields changedv1.6.0
    • changedInput schema / properties / code / description
      Previous value: -"Gift code to redeem (max 50 characters)"New value: +"Gift code as the player typed it (max 50 characters)"
    • addedInput schema / properties / code / minLength
      Added value: +1
    • addedInput schema / properties / sessionToken
      Added value: +{
      +  "description": "accessToken from horizon_signin_email or horizon_signin_anonymous for this userId; sent as a Bearer session",
      +  "maxLength": 256,
      +  "minLength": 1,
      +  "type": "string"
      +}
    • changedInput schema / properties / userId / description
      Previous value: -"User ID (UUID) returned by a horizon_signup_* or horizon_signin_* tool"New value: +"Player user ID (UUID) from horizon_signup_* or horizon_signin_*"
    • changedInput schema / required
      Previous value: -[
      -  "code",
      -  "userId"
      -]New value: +[
      +  "code",
      +  "userId",
      +  "sessionToken"
      +]
  3. Changed1 schema field changedv1.5.5
    • changedInput schema / properties / userId / description
      Previous value: -"User ID (UUID)"New value: +"User ID (UUID) returned by a horizon_signup_* or horizon_signin_* tool"
  4. First observedv1.5.4

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Although annotations already establish non-read-only, open-world, idempotent, and non-destructive behavior, the description adds substantial context: atomic reward commit, shared logical sequence slots on identical retries, no automatic retry/preparation, replay semantics, and what to do on uncertain outcomes. It also maps authentication and rate-limit failures to concrete next steps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose, usage, requirements, side effects, returns, and errors, which is appropriate for a complex idempotent recovery tool. It is very dense and repeats the 'never prepare or advance automatically' guidance in both the Returns and Errors sections, so it is not maximally concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, but the description supplies the return shape, replay-specific return behavior, error mapping, authentication requirements, and recovery guidance. Given the complexity of the mutation/idempotency semantics, it is complete enough for an agent to call and interpret results correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already defines all five parameters and nested intent fields. The description still adds useful semantic constraints: the intent must be the exact saved seven-field object, obsolete V1 arguments are rejected locally, and sessionToken must belong to the intent's original user. Slight ambiguity remains because 'Requires: userId' could be confused with the obsolete top-level userId, though the intent context clarifies it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a precise verb and resource: consuming the persisted V2 campaign/player sequence and returning authoritative state on replay. It explicitly distinguishes this tool from `horizon_prepare_gift_code` and `horizon_validate_gift_code`, so an agent can identify its role without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-to-use guidance: only for consuming or retrying the exact seven-field intent previously returned by `horizon_prepare_gift_code` and durably saved. It also gives explicit when-not-to-use guidance, including not preparing or advancing after uncertainty, and clarifies that validate alone does not produce an intent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Deploy Server

Other Tools