Errors and retries
Safe to retry
Section titled “Safe to retry”Retry GET, HEAD and OPTIONS after network failures, 408, 429 and temporary 5xx
responses. Respect Retry-After.
Writes
Section titled “Writes”Retry a write only with the same idempotency key and unchanged body. A new question or tier needs a new key.
The error envelope
Section titled “The error envelope”Every 4xx and 5xx response has the same JSON body:
{ "error": { "type": "rate_limited", "code": "rate_limit_exceeded", "message": "Rate limit of 60 reads requests per minute exceeded for this key. Retry in 37s.", "retry_after": 37, "retryable": true, "request_id": "req_01J9ZQ7V6H0000000000000000" }}code is stable and is what a client should branch on; message is for
people and can change. retryable says whether the same request may succeed
if sent again unchanged, after retry_after when there is one: true for 429,
500, 502, 503, 504 and 409 idempotency_in_flight, false for every other 4xx
and for 501. param names the offending field when there is one.
Quote request_id (also sent as the X-Request-Id header) when you contact
support. The full list of codes is the ErrorEnvelope schema in the
API reference.
Statuses
Section titled “Statuses”401 means authentication failed; its WWW-Authenticate header names the realm
and, per RFC 9728, the resource metadata at
https://api.hyperresearch.ai/.well-known/oauth-protected-resource. 403 means
scope, CSRF or policy is insufficient. 409 reports a state conflict. 429 means
a rate limit; wait Retry-After seconds.
The Answers routes can also answer 503, always with Retry-After. A 503 is
free, with one exception: if the billing store fails right after a call was
charged, the 503 says so, and retrying with the same Idempotency-Key returns
that call’s result without charging again.
answers_capacity: Answers is at capacity. When the day’s capacity is used up,Retry-Afterruns to 00:00 UTC anderror.resets_atsays when.temporarily_unavailable: the billing store did not answer. Retry after the delay, with the sameIdempotency-Keyif you sent one.engine_unavailable(search, on deployments that report search failures over HTTP): the search did not finish. Otherwise the same failure is a 200 withstatus: "error"and anerrorobject whoseretryableistrue.
Rate limits
Section titled “Rate limits”Limits are per API key, per minute:
| Bucket | Limit | What counts |
|---|---|---|
status |
600 | Polling one run: GET /v1/runs/{id} and its event stream |
reads |
60 | Everything not listed elsewhere |
writes |
20 | Creating API keys and webhooks |
creates |
10 | Starting billable work: runs, re-runs, verification, fetches, vault chat, exports, webhook tests |
ask |
60 | Answers calls: POST /v1/answers and POST /v1/answers/search |
Creates, writes and Answers calls also have a per-workspace ceiling (40, 60 and
120 a minute), so more keys do not buy more throughput. Reading a stored Answers
call (GET /v1/answers and GET /v1/answers/{id}) counts against reads.
Keyless routes are limited to 300 requests a minute per network.
Windows are fixed 60-second windows. A refusal from the per-workspace ceiling
also carries X-RateLimit-Scope: workspace, and its RateLimit-Policy names
ask-workspace (or creates-workspace, writes-workspace). Separately from
the per-minute limit, an account can have only a few Answers calls running at
once; one over that answers 429 concurrency_limit with Retry-After: 5 and
lists the calls still running in error.in_flight, so you can collect those
with GET /v1/answers/{id} instead of asking again.
Responses carry the limit that applied, in two forms:
RateLimit-Policy: "reads";q=60;w=60andRateLimit: "reads";r=57;t=41(IETF RateLimit fields): quotaqper windowwseconds,rrequests remaining,tseconds until the window resets;X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset(Unix seconds) andX-RateLimit-Bucket.
A 429 always carries Retry-After and the same number in error.retry_after.
Refused requests do not count against the limit, so a client that waits as told
recovers on schedule.
Versioning
Section titled “Versioning”How /v1 changes and how a deprecation is announced:
Versioning and deprecation.