Errors, limits and idempotency
Error shapes
| API | Shape |
|---|---|
| Portal API and Ingest API | {"detail": "message"}, or a list of validation problems for 422 |
| SBOM upload | {"detail": {"code": "too_large", "message": "..."}} with a stable code |
| AI Gateway | OpenAI style: {"error": {"message": "...", "type": "invalid_request_error"}} |
Status codes
| Status | Meaning | What to do |
|---|---|---|
200, 201, 202 | Success (202 for ingest: accepted for processing) | Check rejected in ingest responses |
400 | Malformed request | Fix the request |
401 | Credential missing, invalid, expired or revoked | Refresh the session, or replace the token |
403 | Your role or token lacks permission. The detail names it. | Use an account with the permission |
404 | Not found, or in another tenant | Check the ID and tenant |
409 | Conflict: the change would do nothing, or the state forbids it | Read the detail |
413 | Body larger than the endpoint limit | Send smaller batches |
415 | Unsupported content type | Use the documented type |
422 | Validation failed | Fix the fields listed in detail |
429 | Rate limit exceeded | Wait Retry-After seconds |
502 | Gateway: your model provider could not be reached | Retry |
503 | A dependency such as the rate limiter or storage is unavailable | Wait Retry-After seconds, then retry. It is safe to repeat. |
Rate limits
| Endpoint | Limit |
|---|---|
POST /api/ingest/events | 1,200 events a minute per sensor token; 500 events and 256 KB per request |
POST /api/ingest/security-events | 600 events a minute per ingest token; 500 events and 256 KB per request |
POST /api/ingest/otlp/v1/traces | 600 spans a minute per ingest token; 1 MB per request |
POST /api/ingest/sbom | 30 documents a minute per ingest token; 20 MB per request |
| Failed authentication | 30 a minute per token prefix, then 429 |
POST /api/shadow-agents/scan | 10 a minute per tenant |
| Heavy Portal calls (simulations, scenarios, assessments, observability) | Limited per tenant and user. Over the limit returns 429. |
| Gateway chat completions | No gateway-side limit. Your provider's own limits still apply. |
Limits fail closed on ingest
If the rate limiter itself is down, ingest endpoints answer 503 with Retry-After. They never fall back to unlimited traffic. Your sender should back off and retry.
Retrying safely
Every ingest call is idempotent:
| Call | Idempotency key |
|---|---|
| Sensor events | event_id per tenant |
| Security events | event_uid per source |
| OTLP spans | trace_id and span_id |
| SBOM | Subject plus the SHA-256 of the document |
Sending the same item again is reported as a duplicate and changes nothing, so retry after any timeout, 429 or 503. For the gateway, send Idempotency-Key so a retried model call is not counted twice in cost accounting.
Correlate and report
Every Portal API response carries X-Request-ID. Send your own value to correlate, and include it when you contact support.