| 400 | invalid_request | Request body failed schema validation; check details | No — fix the payload |
| 400 | invalid_topup_amount | Top-up is outside 5–500 range or not whole cents | No — fix the amount |
| 400 | invalid_scope | API key scope is not in the allowed list | No |
| 400 | invalid_cidr | CIDR notation is malformed | No |
| 400 | key_not_active | Only active keys can be rotated | No |
| 400 | not_a_replacement | The key is not a replacement in a rotation | No |
| 400 | invalid_workspace_settings | Workspace settings update failed validation | No |
| 400 | invalid_workspace_icon | Icon upload or refresh failed | No |
| 400 | invalid_signature | Stripe webhook signature verification failed | No |
| 401 | invalid_key | API key is absent, revoked, pending, or expired grace | No |
| 401 | invalid_credentials | Email or password is wrong | Yes — with corrected credentials |
| 403 | signup_not_allowed | Email domain is not in the allowed list | No |
| 403 | csrf_forbidden | Session cookie CSRF token is missing or invalid | No |
| 403 | ip_forbidden | Client IP is outside the key’s allowedCidrs | No — check the key’s CIDR |
| 403 | metering_forbidden | Operation token is invalid for this operation | No |
| 404 | workspace_not_found | Workspace does not exist, is not accessible, or key’s bound workspace does not match | No |
| 404 | key_not_found | API key does not exist in the workspace | No |
| 404 | delivery_not_found | API key delivery record not found | No |
| 404 | job_not_found | Job does not exist or is not accessible | No |
| 404 | chat_thread_not_found | Chat thread does not exist | No |
| 404 | recommendation_not_found | Recommendation not found | No |
| 409 | workspace_exists | Workspace slug is already taken | No |
| 409 | email_exists | Account with this email already exists | No |
| 409 | username_exists | Username is already in use | No |
| 409 | username_unavailable | Username is reserved or taken | No |
| 409 | job_already_running | One running measurement per brand slot is occupied | Yes — poll and retry after completion |
| 409 | pipeline_capacity_reached | Worker cap (GEO_MAX_PIPELINE_JOBS) reached; no more jobs can start | Yes — retry after backoff |
| 409 | insufficient_credits | Credits are too low to start or continue an operation | No — top up credits |
| 409 | stopped_credits | Operation stopped mid-stream because a credit lease was refused | Yes — retry the operation |
| 409 | metering_conflict | Idempotency key was reused with different input, or a CAS conflict | No |
| 409 | idempotency_conflict | Idempotency key was already used with a different request | No |
| 409 | invalid_state | Resource state does not allow the requested transition | No |
| 409 | rotation_in_progress | Key already has a replacement pending | No |
| 409 | delivery_expired | 10-minute delivery window has passed | No — create a new key |
| 409 | operator_provider_not_configured | Provider is not configured for this operator | No |
| 409 | mock_topup_disabled | Mock top-ups are disabled when Stripe is configured | No |
| 409 | route_not_registered | Route is not in the API route registry | No |
| 409 | stale_state | Recommendation transition CAS failed (stale expectedVersion) | Yes — re-fetch and retry |
| 409 | invalid_transition | Recommendation action is not valid from current status | No |
| 429 | rate_limited | Generic rate limit hit | Yes — exponential backoff |
| 429 | research_rate_limited | Research on-demand start limit (1/hour/workspace) | Yes — retry after the window |
| 429 | verification_cooldown | Verification email resend cooldown not elapsed | Yes — wait and retry |
| 503 | auth_unavailable | Authentication is unavailable (missing server key) | Yes — retry |
| 503 | delivery_unavailable | Key delivery encryption is unavailable | Yes — retry |
| 503 | entropy_unavailable | Unable to generate a unique API key | Yes — retry |
| 503 | billing_unavailable | Stripe billing is not configured | No |
| 503 | email_delivery_unavailable | Email delivery service is unavailable | Yes — retry |
| 500 | internal_error | Unexpected server error | Yes — retry |