Response format
All error responses follow the same shape:errors is an array of field-level validation errors when applicable (e.g. request body validation failures). It is empty for most errors.
HTTP status codes
| Code | Name | When it occurs |
|---|---|---|
400 | Bad Request | Missing required field, invalid ObjectId, batch too large, invalid parameter value |
401 | Unauthorized | Missing or invalid API key / session cookie |
403 | Forbidden | API key doesn’t have access to the workspace; agent not in workspace |
404 | Not Found | Dataset, run, trace, or agent not found |
409 | Conflict | Run is already in a terminal state (completed or failed); analysis already running |
429 | Too Many Requests | Rate limit exceeded (see Rate Limits) |
500 | Internal Server Error | Unexpected server error |
Common errors
401 Unauthorized
- Your
x-api-keyheader is present and matches a valid workspace API key - The key hasn’t been revoked in Settings → API Keys
403 Forbidden
workspaceId belongs to the same workspace as your API key.
404 Not Found
409 Conflict — terminal state
POST /results when the run has already been finalized or failed. Check the run status with GET /runs/:id before submitting more results.
400 Bad Request
Rate limits
| Route group | Limit |
|---|---|
POST /ingest/traces | 300 requests / minute per API key |
POST /ingest/ci-runs/* | 60 requests / minute per API key |
POST /custom-agent-evaluations/* | 60 requests / minute per API key |
429 Too Many Requests. Wait for the next minute window and retry.
Retrying
Safe to retry on500 and 429. Not safe to retry POST /results without idempotency keys — always set idempotencyKey on every result to avoid duplicate scoring on retry.
