detail is an array of field-level errors:
Status codes
| Code | Meaning | What to do |
|---|---|---|
200 OK | Success | — |
201 Created | Resource created | Capture the returned id |
204 No Content | Success, no body | — |
400 Bad Request | Malformed request | Fix the request body |
401 Unauthorized | Missing or invalid credentials | Check X-API-Key or Authorization header |
403 Forbidden | Authenticated but not allowed | Add the missing scope, or you’re hitting a workspace you don’t belong to |
404 Not Found | Resource doesn’t exist | Verify the id |
409 Conflict | Resource isn’t in the expected state | Check the error code — e.g., synthesis_pending |
422 Unprocessable Entity | Validation error | Fix the field-level issues in detail |
429 Too Many Requests | Rate limited | Honor Retry-After |
500 Internal Server Error | Bug on our side | Retry; if persistent, contact support with the request id |
503 Service Unavailable | Temporary outage | Retry with backoff |
Common error codes
code | Meaning |
|---|---|
invalid_api_key | Key is missing, malformed, or revoked |
insufficient_scope | Key is missing a required scope |
workspace_forbidden | Key belongs to a different workspace |
synthesis_pending | Campaign hasn’t completed synthesis yet |
graph_not_ready | Entity-extraction pipeline hasn’t finished |
campaign_locked | Lifecycle action invalid for current status (e.g., starting an already-completed campaign) |
rate_limited | Per-workspace rate limit exceeded |
Idempotency
Safe-by-design endpoints (anyGET, DELETE) are naturally idempotent. For POST endpoints, pass an Idempotency-Key header with a unique value (e.g., a UUID) to make retries safe:
Rate limits
Rate limits apply per workspace, not per key. Limits are returned in headers on every response:| Header | Meaning |
|---|---|
X-RateLimit-Limit | Limit for the current window |
X-RateLimit-Remaining | Calls remaining in this window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Retry-After | Seconds to wait (only on 429) |