Unlock Manual Achievement
horizon_unlock_achievementUnlocks one configured manual achievement once for an authenticated player when a game event matches its rule; requires userId, sessionToken, and stable key. Repeating the key never grants twice.
Instructions
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).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | Stable configured achievement key; never replace it to retry an unlock | |
| userId | Yes | Signed-in player UUID matching the session | |
| sessionToken | Yes | Player accessToken, sent only as Authorization Bearer |