API authentication, errors, and limits
Authenticate API requests and handle validation, authorization, payload, and rate-limit failures.
Use this reference to choose the authentication mechanism an endpoint accepts and to implement predictable error recovery. Authentication is route-specific: do not assume that an API key works on an endpoint unless that endpoint is explicitly documented as using API-key middleware.
Authentication flow
Routes wrapped with API-key authentication give a supplied API key priority over the current Clerk session. A valid key establishes its key ID, organization ID, and scopes. If no key is present, those routes fall back to the signed-in session. Routes that call session authentication directly require the session and do not gain API-key support from this shared middleware.
Send an API key
For an endpoint documented as API-key enabled, send the key in one of these locations:
curl -H 'X-API-Key: ast_example_key' \
'https://studio.example.com/api/example'The query parameter exists for webhook callback scenarios. Prefer a header for ordinary API clients so credentials do not appear in URLs or URL logs. Never place a real key in source control or examples.
401 even when the request also has a valid session, because a supplied key is evaluated before the session fallback.The stricter requireApiKey middleware accepts X-API-Key and bearer credentials but does not fall back to a session. Omitting the key returns 401 with API key required. Provide via X-API-Key header or Bearer token.
Authentication errors
| Status | Error text | Meaning | Client action |
|---|---|---|---|
401 | Authentication required | The API-key-enabled route received neither a key nor a signed-in session. | Sign in, or provide a key if the endpoint supports one. |
401 | API key required. Provide via X-API-Key header or Bearer token. | The route requires an API key and does not allow session fallback. | Add X-API-Key or Authorization: Bearer …. |
401 | Invalid or expired API key | Key validation rejected the credential. | Replace or rotate the key; do not retry the same credential. |
401 | Authentication failed | Key validation could not complete. | Retry only after checking service health; do not reveal the key in logs. |
403 | Route-specific forbidden response | Authentication succeeded, but the user or key lacks access. | Use the correct organization context and request the required role or scope. |
See Manage organization API keys for key lifecycle tasks and Authentication and authorization model for the broader permission model.
Validation and payload errors
Most JSON endpoints validate the request after authentication. Treat 400 as a request defect: inspect the response error, correct field names and types, and submit a new request. Common causes include malformed JSON, missing required fields, unsupported enum values, and identifiers that do not resolve in the current access context.
Payload parsing can reject a request before business validation. When a route returns a payload-size error, reduce the body rather than retrying it unchanged. A 404 can intentionally cover both a missing resource and a resource the caller cannot access; do not use that distinction to probe identifiers.
Error bodies are not uniform across all route families. Clients should always branch on the HTTP status first, then read error, code, and field-level details when present. Do not require every response to contain a success property.
Rate limits
Rate-limited routes identify a caller by x-user-id, the first address in x-forwarded-for, and the request path. Limits are maintained per resulting key and window. Because the backing store is process-local, the implementation does not establish a durable or distributed quota guarantee.
A rejected request has this shape:
{
"success": false,
"error": "Too many requests. Please try again later.",
"code": "RATE_LIMITED",
"retryAfter": 12
}The response is 429 Too Many Requests and includes these headers:
| Header | Meaning |
|---|---|
Retry-After | Whole seconds to wait before retrying. |
X-RateLimit-Limit | Maximum requests allowed in the active window. |
X-RateLimit-Remaining | 0 on the rejected response. |
X-RateLimit-Reset | Window reset time as Unix seconds. |
Honor Retry-After, then retry with bounded exponential backoff and jitter. Do not retry 400, 401, or 403 responses without changing the request or credentials.