success: false and an error object containing a machine-readable code, a human-readable message, and the HTTP status code.
Error response format
Always
false for error responses.Error codes
| Code | HTTP status | Description |
|---|---|---|
UNAUTHORIZED | 401 | No authentication header provided. Include Authorization: Bearer hg_live_YOUR_KEY or X-API-Key: hg_live_YOUR_KEY. |
INVALID_KEY_PREFIX | 401 | API key format is invalid. Keys must start with hg_live_ or hg_admin_. |
KEY_NOT_FOUND | 401 | API key not found or has been revoked. Generate a new key at Settings → API Keys. |
INVALID_TOKEN | 401 | Session token is malformed, expired, or has been revoked. Refresh the session and retry. |
FORBIDDEN | 403 | The authenticated user does not have permission to access this resource or perform this action. |
NOT_FOUND | 404 | The requested resource does not exist or the user does not have access to it. |
VALIDATION_ERROR | 400 | The request body is missing required fields, contains invalid data, or has malformed JSON. |
AGENT_NOT_FOUND | 404 | The specified genie (agent) does not exist or the user does not have access to it. |
INVALID_ACTION | 400 | The action value is not supported for the specified resource. |
RATE_LIMIT_EXCEEDED | 429 | Too many requests. API keys are limited to 60 requests/minute. Wait before retrying. |
INTERNAL_ERROR | 500 | An unexpected server error occurred. If this persists, contact support. |
Handling errors in code
With ApiService
ApiService.invoke() throws on error. Wrap calls in try/catch:
With fetch
When usingfetch directly, check the success field in the response body:
With TanStack Query
When using TanStack Query (React Query), errors propagate through the query’serror state:
Retry strategy
Common error scenarios
401 — Missing or expired token
401 — Missing or expired token
The most common cause is an expired access token. Supabase tokens typically expire after 1 hour. Use
supabase.auth.refreshSession() to get a new token.400 — Invalid action for resource
400 — Invalid action for resource
Each resource supports a specific set of actions. Sending an unsupported action (e.g.,
action: "archive" to a resource that does not support it) returns INVALID_ACTION. Check the resource’s documentation in the API reference for supported actions.403 — Insufficient permissions
403 — Insufficient permissions
The user’s role does not allow the requested operation. For example, a
consumer user cannot create genies. See Introduction for the role permission matrix.404 — Resource not found
404 — Resource not found
The record either does not exist or belongs to another user. Non-admin users can only access their own resources. Verify the
id value and confirm the user has access.429 — Rate limit exceeded
429 — Rate limit exceeded
Back off and retry with exponential delay. A simple implementation:

