Errors & rate limits
The canonical Qeet error envelope, HTTP status codes, and how rate limiting works.
Every Qeet API returns a single, predictable error shape and standard HTTP status codes, so you can handle failures the same way across products.
The error envelope
Errors are returned as JSON under a top-level error object
(internal/platform/httpx.WriteError):
{
"error": {
"code": "unauthorized",
"message": "authentication required",
"detail": "the ApiKey credential was missing or expired",
"request_id": "req_8f1c2a9e"
}
}
| Field | Type | Description |
|---|---|---|
code |
string | Stable, machine-readable error code — branch on this, not the message. |
message |
string | Short human-readable summary. |
detail |
string | Optional extra context (may be omitted). |
request_id |
string | Correlates with the X-Request-Id response header — quote it in support requests. |
Always switch on
error.code, never onmessage— messages may be reworded, codes are stable.
HTTP status codes
| Status | Typical code |
Meaning |
|---|---|---|
400 |
bad_request |
Malformed request — bad JSON, missing or invalid parameters. |
401 |
unauthorized |
Missing, malformed, or expired credential. |
403 |
forbidden |
Authenticated, but the credential lacks the required scope or permission. |
404 |
not_found |
The resource doesn’t exist (or isn’t visible to your tenant). |
409 |
conflict |
The request conflicts with current state (e.g. a duplicate). |
422 |
unprocessable_entity |
The request was well-formed but failed validation. |
429 |
too_many_requests |
You’ve hit a rate limit — back off and retry. |
5xx |
internal |
Something went wrong on our side; retry idempotent requests with backoff. |
Rate limits
To keep the platform fast and fair, endpoints are rate limited per credential
and tenant. When you exceed a limit the API responds with 429 Too Many Requests and the canonical error envelope.
- Back off. When a
Retry-Afterheader is present, wait at least that many seconds before retrying. - Use exponential backoff with jitter for retries on
429and5xxresponses — don’t retry tightly in a loop. - Retry only idempotent operations (
GET,PUT,DELETE) automatically; forPOST, make sure a retry won’t create a duplicate.
Debugging with request IDs
Every response carries an X-Request-Id, echoed as error.request_id on
failures. Log it on your side and include it when contacting support — it lets
us trace the exact request through the platform.