Error response shape
Every error response body contains the following fields:integer
required
The HTTP status code of the response (e.g.
404, 422, 429). Mirrors the HTTP status on the response itself.string
required
A stable string identifier for the error category (e.g.
NotFoundIssue). See the taxonomy below. This value is frozen — it will not be renamed in /v1.string
A human-readable description of what went wrong. Useful for logging and debugging; do not rely on the exact wording in application logic.
object
Optional structured detail about the error — for example, which field failed validation or what the applicable rate limit is.
string
A unique identifier for this specific request, generated by Topo’s API gateway. Always include this value when contacting support — it’s the fastest way to locate your request in our logs.
string
Internal trace identifier. Present in non-production environments for debugging.
string
Internal span identifier. Present in non-production environments for debugging.
Error taxonomy
Thetype field uses a frozen set of values. Branch first on status_code, then use type as a stable refinement for more specific handling.
The
type identifiers listed below are frozen and will not be renamed in /v1. Adding a new error type is an additive change; renaming an existing one is breaking and would require /v2.ValidationIssue (400)
Returned when the request itself is malformed.data.param points at the first offending field, and data.errors lists every validation failure with its field, message, and type.
UnauthorizedIssue (401 / 403)
A401 means no valid key was provided; a 403 means the key is valid but does not have the required scope. Check the data.required field to see which scope is needed.
NotFoundIssue (404)
Returned when a resource ID does not exist or belongs to a different workspace. Topo deliberately returns 404 (rather than 403) for cross-workspace resources to avoid leaking the existence of records.RateLimitIssue (429)
Returned when your organization exceeds the allowed request rate. See the rate limits section below for how to handle this response.Rate limits
Topo enforces rate limits per organization across three time windows simultaneously: per second, per minute, and per day. All three windows are active on every request. Every API response includes headers that tell you your current rate limit state:
When a rate limit is exceeded, the API returns
429 with a RateLimitIssue error body:
Handling rate limits
1
Read the Retry-After header
On a
429 response, read the Retry-After header value (in seconds) and wait at least that long before retrying.2
Apply exponential backoff
If you continue to receive
429 responses, increase your wait time exponentially with jitter to avoid synchronized retries across parallel workers.3
Monitor remaining capacity proactively
Watch
X-RateLimit-Remaining-minute on successful responses. If it drops near zero, slow down your request rate before hitting the limit.Debugging tips
- Branch on
status_codefirst for broad categories (auth, not found, server error), then usetypeto distinguish sub-cases like401vs403. - Don’t match on
message— the human-readable message text is for display only and may change over time. Usetypefor logic. - Log
datafor validation errors — it contains field-level detail that helps you identify what to fix in your request. - 5xx errors are Topo-side — if you receive a
500 InternalServerIssue, the issue is not with your request. Retry with backoff and contact support if it persists, providing therequest_id.