Appearance
Errors and limits
HTTP errors
Errors answer JSON with an error field (the 401 body uses message).
| Status | Body | When |
|---|---|---|
| 400 | {"error": "…"} | Missing or invalid parameter, bad cursor, body not JSON |
| 401 | {"message": "Unauthorized"} | No Authorization header; unknown, malformed, revoked or expired key; invalid session |
| 403 | {"error": "missing scope <scope>"} | The key lacks the scope of the endpoint |
| 403 | {"error": "API keys cannot manage API keys"} | A key called /keys… |
| 403 | {"error": "this key is limited to other profiles"} | Starting a run for a profile outside the key's limit |
| 404 | {"error": "not found"} | Unknown route |
| 404 | {"error": "run not found"} and similar | Unknown id, or outside the key's profile limit |
| 404 | {"found": false, "did_you_mean": [...], "hint": "…"} | Unknown service, package or advisory in a portfolio answer: retry with a suggestion |
| 405 | JSON-RPC error | GET on the MCP endpoint |
| 409 | {"error": "…"} | Not a Decide step; a person already decided; a key tried to clear a value |
| 410 | logs body with "error": "logs expired" | The log is older than its 30-day retention |
| 429 | {"error": "rate limit: 60 reads per minute", "retryAfter": 12} | A rate limit was hit (see below) |
| 500 | {"error": "…"} | Unexpected error |
| 502 | {"error": "…"} | A scan job could not start, or logs could not be read |
| 503 | {"error": "…"} | The feature is not available right now |
MCP errors are described in MCP → Errors.
Rate limits
Limits apply per API key in fixed windows. Signed-in people are not limited.
| Kind | What counts | Limit |
|---|---|---|
| read | every read (REST GET or a read MCP tool) | 60 per minute |
| write | recording a decision or a step status | 20 per minute |
| create | starting a run | 5 per day (UTC day) |
Requests denied for scope (403) do not count. On 429, wait retryAfter seconds (also in the Retry-After header) and retry.
Size limits
| What | Limit |
|---|---|
| Portfolio answers | at most 8000 bytes; longer lists are shortened and "truncated": true is added |
| Text fields you send (rationale, note) | at most 1000 characters |
| Key names | 1 to 80 characters |
| Download URLs | valid for 5 minutes for keys (1 hour for signed-in people) |
| Key activity | kept for 90 days |
| Scan logs | kept for 30 days |