{"codes":[{"code":1001,"title":"Unauthorized","http_status":401,"domain":"auth","trigger":"JWT middleware present but claims missing or extraction failed; used by non-auth handlers"},{"code":1002,"title":"Email Already Exists","http_status":409,"domain":"auth","trigger":"Registration attempted with an email address already in use"},{"code":1003,"title":"Invalid Credentials","http_status":401,"domain":"auth","trigger":"Email/password combination is incorrect"},{"code":1004,"title":"Invalid Token","http_status":401,"domain":"auth","trigger":"Terminal: refresh token or personal access token does not exist (401). Also 400 for an invalid or expired verification/reset token, and 404 from DELETE /v1/auth/pats/{id} for an unknown token. Expired refresh tokens use 1007","alternate_http_statuses":[400,404]},{"code":1005,"title":"Missing Claims","http_status":401,"domain":"auth","trigger":"JWT present but claims absent; used by auth-package handlers (login, logout, refresh)"},{"code":1006,"title":"Registration Cooldown","http_status":429,"domain":"auth","trigger":"Registration attempted too soon after a previous attempt with the same email"},{"code":1007,"title":"Token Expired","http_status":401,"domain":"auth","trigger":"Terminal: refresh token has passed its 30-day TTL. Sign in again"},{"code":1008,"title":"Email Not Verified","http_status":403,"domain":"auth","trigger":"Watch pairing attempted before the email address was verified. Verify the email, then retry"},{"code":1009,"title":"Insufficient Scope","http_status":403,"domain":"auth","trigger":"The access token's scope (e.g. wear) does not permit this route"},{"code":1010,"title":"Token Rotated","http_status":401,"domain":"auth","trigger":"Refresh token was rotated away past its replay window. Treated as token reuse: the token's whole rotation chain is revoked. Re-read stored tokens and retry once; a 1011 on that retry means sign in again"},{"code":1011,"title":"Token Revoked","http_status":401,"domain":"auth","trigger":"Terminal: refresh token was revoked by logout or password reset. Sign in again"},{"code":1012,"title":"Device Not Found","http_status":401,"domain":"auth","trigger":"The refresh token is valid but its device_id is not registered for this user. Re-register the device and retry — do not discard the refresh token"},{"code":1013,"title":"Personal Access Token Expired","http_status":401,"domain":"auth","trigger":"Terminal: the personal access token has passed its expiry. Create a new one in the webapp"},{"code":1014,"title":"Personal Access Token Permission Denied","http_status":403,"domain":"auth","trigger":"The personal access token lacks the permission this route needs, or the route is never reachable with a PAT (auth, devices, profile, app settings, feedback, sync, WebSocket)"},{"code":1015,"title":"Personal Access Token Limit Reached","http_status":409,"domain":"auth","trigger":"The user already holds the maximum number of active personal access tokens. Revoke one first"},{"code":1016,"title":"Sign-in Link Invalid","http_status":401,"domain":"auth","trigger":"Terminal: the Sign-in Link is unknown, expired, already used, replaced by a newer request, or burned by 5 wrong codes. Request a new one"},{"code":1017,"title":"Sign-in Code Wrong","http_status":401,"domain":"auth","trigger":"The Sign-in Link code does not match. Not terminal: retry; the 5th miss burns the link and answers 1016"},{"code":2001,"title":"Timer Not Found","http_status":404,"domain":"timer","trigger":"Reserved. GET /v1/timer/state answers 204 No Content, not this code, when no timer is running","reserved":true},{"code":2002,"title":"Invalid Timer State","http_status":422,"domain":"timer","trigger":"Reserved. Timer state transition is not allowed","reserved":true},{"code":3001,"title":"Invalid Sync Since","http_status":400,"domain":"sync","trigger":"The since query param is not a valid RFC3339 timestamp or is in the future"},{"code":3002,"title":"Sync Conflict","http_status":409,"domain":"sync","trigger":"Reserved. Concurrent write conflict during the removed POST /v1/sync/reconcile; POST /v1/sync/delta reports conflicts per item instead","reserved":true},{"code":3003,"title":"Invalid Entity Type","http_status":400,"domain":"sync","trigger":"Reserved. Was the unknown entity field of POST /v1/sync/reconcile, removed in #1224","reserved":true},{"code":3004,"title":"Reconcile Failed","http_status":500,"domain":"sync","trigger":"Reserved. Was a POST /v1/sync/reconcile failure, removed in #1224","reserved":true},{"code":4001,"title":"Task Not Found","http_status":404,"domain":"tasks","trigger":"Task ID does not exist for this user or has been soft-deleted"},{"code":4002,"title":"Activity Not Found","http_status":404,"domain":"activities","trigger":"Activity ID does not exist for this user or has been soft-deleted"},{"code":4003,"title":"Already Exists","http_status":409,"domain":"tasks","trigger":"Create rejected because the ID (or name) is taken. Shared by tasks, work sessions, log entries, decisions and goal entries; resources added later use 4014"},{"code":4004,"title":"Stats Not Found","http_status":404,"domain":"stats","trigger":"No pre-computed stats snapshot exists yet for the requested year or user"},{"code":4005,"title":"Goal Not Found","http_status":404,"domain":"goals","trigger":"No horizon goal, goal entry or period note matches the request, or goal entries are disabled on this server. Resources added later use 4013"},{"code":4006,"title":"Cannot Delete Built-in Activity","http_status":403,"domain":"activities","trigger":"Attempt to delete a built-in activity; only user-owned activities can be soft-deleted"},{"code":4007,"title":"Session Not Found","http_status":404,"domain":"sessions","trigger":"Work session ID does not exist for this user or has been soft-deleted"},{"code":4008,"title":"Feature Flag Not Found","http_status":404,"domain":"admin","trigger":"Reserved. Was a missing name on the feature-flag admin API, removed in #1225","reserved":true},{"code":4009,"title":"Log Entry Not Found","http_status":404,"domain":"log-entries","trigger":"Log entry ID does not exist for this user; entries are hard-deleted, so a removed one is simply gone"},{"code":4010,"title":"External Ref Already Exists","http_status":409,"domain":"tasks","trigger":"A task with this external_ref already exists for the user, soft-deleted tasks included; the ref stays reserved after delete"},{"code":4012,"title":"Decision Not Found","http_status":404,"domain":"decisions","trigger":"Decision ID does not exist for this user or has been soft-deleted"},{"code":4011,"title":"Task Not Skippable","http_status":400,"domain":"tasks","trigger":"POST /v1/tasks/{id}/skip on a task that is not due today or overdue, or is done or archived; the reason is in detail"},{"code":4013,"title":"Resource Not Found","http_status":404,"domain":"resources","trigger":"Generic not-found for resources added after #1193; older resources keep their own code"},{"code":4014,"title":"Resource Already Exists","http_status":409,"domain":"resources","trigger":"Generic already-exists for resources added after #1193; older resources keep 4003 or their own code"},{"code":4015,"title":"Precondition Failed","http_status":412,"domain":"resources","trigger":"PUT sent If-Match naming a version the row has moved past (another write landed first). The ETag header carries the current version; re-read, reapply, retry. Without If-Match the write is unconditional"},{"code":5001,"title":"Validation Failed","http_status":400,"domain":"validation","trigger":"Request body fails field-level validation; mixed required + format errors"},{"code":5002,"title":"Missing Required Field","http_status":400,"domain":"validation","trigger":"A required query param or body field is absent"},{"code":5003,"title":"Invalid Format","http_status":400,"domain":"validation","trigger":"A field is present but has the wrong type, format, or value range. Also 422 from goal-entry endpoints for a business-rule violation (period full, entry not carryable)","alternate_http_statuses":[422]},{"code":5004,"title":"Payload Too Large","http_status":413,"domain":"validation","trigger":"Request body exceeds the 1 MiB limit; split it rather than resend it"},{"code":5005,"title":"Route Not Found","http_status":404,"domain":"validation","trigger":"No /v1 route matches the request path"},{"code":5006,"title":"Method Not Allowed","http_status":405,"domain":"validation","trigger":"The /v1 path exists but not for this method; the Allow header lists the methods it takes"},{"code":6001,"title":"Rate Limit Exceeded","http_status":429,"domain":"rate-limit","trigger":"Too many HTTP requests or WebSocket messages from this client"},{"code":7001,"title":"Invalid Admin Key","http_status":401,"domain":"admin","trigger":"Reserved. Was a missing or wrong key on the admin API, removed in #1225","reserved":true},{"code":9001,"title":"Internal Server Error","http_status":500,"domain":"internal","trigger":"Unexpected database or server failure; retry with exponential back-off"},{"code":9002,"title":"Request Timeout","http_status":408,"domain":"internal","trigger":"Request body did not arrive within the server read timeout; retry unchanged"},{"code":9003,"title":"Service Unavailable","http_status":503,"domain":"internal","trigger":"A write could not reserve its sync notification; nothing was written, retry with back-off"}],"batch_codes":[{"code":"entity_not_found","trigger":"Targeted entity does not exist for this user or has been soft-deleted"},{"code":"unknown_entity_operation","trigger":"Unknown entity type or operation combination in the batch event"},{"code":"invalid_event_data","trigger":"Event payload cannot be parsed as the declared entity type. Permanent — do not retry"},{"code":"transient_error","trigger":"Request was cancelled or timed out before the write landed. Retry the event"},{"code":"internal_error","trigger":"Unexpected server or database failure while applying the event. Retry with back-off"}],"endpoints":{"DELETE /v1/activities/{id}":[1001,4002,4006,5003,9001],"DELETE /v1/auth/account":[1005,9001],"DELETE /v1/auth/pats":[1005,1014,9001],"DELETE /v1/auth/pats/{id}":[1004,1005,1014,5003,9001],"DELETE /v1/decisions/{id}":[1001,4012,5003,9001],"DELETE /v1/horizon-goals/entries/{entryID}":[1001,4005,5003,9001],"DELETE /v1/horizon-goals/{horizon}":[1001,5003,9001],"DELETE /v1/log-entries/{id}":[1001,4009,5003,9001],"DELETE /v1/period-notes/{horizon}/{period_start}":[1001,4005,5001,5003,9001],"DELETE /v1/sessions/{id}":[1001,4007,5003,9001],"DELETE /v1/tasks/{id}":[1001,4001,5003,9001],"DELETE /v1/timer/state":[1001,5002,9001],"GET /v1/activities":[1001,5003,9001],"GET /v1/activities/icons":[],"GET /v1/auth/pats":[1005,1014,9001],"GET /v1/auth/verify-email":[1004,5002,9001],"GET /v1/config":[],"GET /v1/daily-snapshots":[1001,5001,5002,5003,9001],"GET /v1/decisions":[1001,5003,9001],"GET /v1/decisions/prompts":[],"GET /v1/decisions/{id}":[1001,4012,5003,9001],"GET /v1/error-codes":[],"GET /v1/horizon-goals":[1001,9001],"GET /v1/horizon-goals/{horizon}/history":[1001,5003,9001],"GET /v1/horizon-goals/{horizon}/timeline":[1001,5001,5003,9001],"GET /v1/horizon-goals/{id}/entries":[1001,4005,5003,9001],"GET /v1/log-entries":[1001,5003,9001],"GET /v1/period-notes":[1001,5001,5003,9001],"GET /v1/profile":[1001,9001],"GET /v1/profile/recommend":[1001,9001],"GET /v1/sessions":[1001,5003,9001],"GET /v1/settings/app":[1001,9001],"GET /v1/stats/all-time":[1001,4004,9001],"GET /v1/stats/snapshot":[1001,4004,5002,5003,9001],"GET /v1/sync/pull":[1001,3001,9001],"GET /v1/tasks":[1001,5003,9001],"GET /v1/tasks/{id}/completions":[1001,5003,9001],"GET /v1/timer/settings":[1001,9001],"GET /v1/timer/state":[1001,9001],"GET /v1/ws":[1001,5002,5003,6001,9001],"PATCH /v1/auth/account/display-name":[1005,5003,9001],"PATCH /v1/horizon-goals/entries/{entryID}":[1001,4005,5002,5003,9001],"PATCH /v1/profile":[1001,5003,9001],"POST /v1/activities":[1001,5003,9001],"POST /v1/auth/device-refresh":[1004,1007,1010,1011,1012,5003,9001],"POST /v1/auth/device-token":[1005,1008,5003,9001],"POST /v1/auth/forgot-password":[5003],"POST /v1/auth/login":[1003,5003,6001,9001],"POST /v1/auth/logout":[1005,9001],"POST /v1/auth/logout-all":[1005,9001],"POST /v1/auth/password":[1003,1005,5003,9001],"POST /v1/auth/pats":[1003,1005,1008,1014,1015,5001,5002,5003,9001],"POST /v1/auth/refresh":[1004,1007,1010,1011,1012,5003,9001],"POST /v1/auth/register":[1002,1006,5003,9001],"POST /v1/auth/resend-verification":[1005,9001],"POST /v1/auth/reset-password":[1004,5003,9001],"POST /v1/auth/sign-in-link":[5003],"POST /v1/auth/sign-in-link/redeem":[1016,1017,5002,5003,9001],"POST /v1/auth/verify-email":[1004,5003,9001],"POST /v1/decisions":[1001,4003,5001,5002,5003,9001],"POST /v1/events":[5003],"POST /v1/feedback":[1001,5003,9001],"POST /v1/horizon-goals/entries/carry":[1001,4005,5001,5002,5003,9001],"POST /v1/horizon-goals/{horizon}":[1001,5001,5003,9001],"POST /v1/horizon-goals/{id}/entries":[1001,4003,4005,5002,5003,9001],"POST /v1/log-entries":[1001,4003,5001,5002,5003,9001],"POST /v1/profile/recompute":[1001,9001],"POST /v1/profile/reset":[1001,9001],"POST /v1/sessions":[1001,4001,4003,5001,5002,5003,9001],"POST /v1/sync/batch":[1001,5001,5002,5003,5004,9001,9002,9003],"POST /v1/sync/delta":[1001,5004,9001,9002,9003],"POST /v1/tasks":[1001,4003,4010,5001,5002,5003,9001],"POST /v1/tasks/{id}/skip":[1001,4001,4011,5003,9001],"PUT /v1/activities/{id}":[1001,4002,5003,9001],"PUT /v1/decisions/{id}":[1001,4012,5001,5002,5003,9001],"PUT /v1/devices/{device_id}/fcm-token":[1001,5002,5003,9001],"PUT /v1/log-entries/{id}":[1001,4009,5001,5002,5003,9001],"PUT /v1/period-notes/{horizon}/{period_start}":[1001,5001,5002,5003,9001],"PUT /v1/sessions/{id}":[1001,4001,4007,4015,5003,9001],"PUT /v1/settings/app":[1001,5003,9001],"PUT /v1/tasks/{id}":[1001,4001,4015,5003,9001],"PUT /v1/timer/settings":[1001,5003,9001],"PUT /v1/timer/state":[1001,5003,9001]}}
