Every error response from the Titan Public API is a JSON object with a stable, machine-readable shape. Human-readable text is helpful for logging; the structured fields are what your integration should branch on.
{
"error": {
"code": "invalid_argument",
"message": "page_size must be between 1 and 500.",
"field": "page_size",
"request_id": "req_01HYZ8V3X5A9K2QW6T3P0RJDNS",
"docs_url": "https://docs.titanapi.securityscorecard.io/docs/guides/errors#invalid_argument"
}
}| Field | Type | Present | Meaning |
|---|---|---|---|
code | string | always | Stable machine-readable identifier. Branch on this. |
message | string | always | Human-readable description. May change wording between releases. |
field | string | only on validation errors | Which request field caused the failure. |
request_id | string | always | Correlation ID. Include this when reporting bugs. |
docs_url | string | when applicable | Deep link to the specific error's documentation. |
The HTTP status code groups errors into the categories below. Match on error.code, not on status, when your integration needs fine-grained branching — a single status can carry multiple codes.
| Status | Category | Example codes |
|---|---|---|
400 | Malformed or invalid request | invalid_argument, missing_required_field |
401 | Authentication failed | unauthenticated, token_expired |
403 | Authenticated but not permitted | permission_denied, insufficient_scope |
404 | Resource does not exist or is not visible | not_found |
409 | Conflict with existing state | already_exists, precondition_failed |
410 | Endpoint has been retired | endpoint_gone |
422 | Payload validated but semantically rejected | unprocessable_entity |
429 | Rate limit exceeded | rate_limit_exceeded |
500 | Server error — safe to retry | internal |
503 | Service temporarily unavailable | unavailable |
4xxother than429— treat as permanent for this request. Do not retry without changing the request. Logrequest_idfor support.429— honour theRetry-Afterheader. See Usage Limits.5xx— retry with exponential backoff (base 1s, factor 2, jitter, cap 30s). If a retry succeeds, no further action. If retries exhaust, escalate with the earliestrequest_idyou observed.410(retired) — the endpoint is gone. Migrate to the successor documented in the endpoint'sLink: <url>; rel="successor-version"header.
At minimum, log:
- HTTP status code
error.codeerror.request_id- The endpoint and method you called (not the full request body — it may contain sensitive fields).
Do not log access tokens, CLIENT_SECRET, or full request/response payloads by default — they may contain sensitive fields.
When opening a support ticket, include:
request_id— required. Without it we cannot correlate your call to server logs.- HTTP status and
error.code. - Approximate timestamp (UTC).
- Minimal request example (method, path, headers other than
Authorization). - What you expected vs. what you observed.