AskVault API error codes
Error response shape
Every non-2xx response from /v1/* is JSON. Bodies are typically under 1 KB. Average error-handling cost is well under 5 ms on the client side:
{ "detail": "workspace_id is required", "code": "missing_field", "request_id": "req_5b45ff_xxx"}| Field | Description |
|---|---|
detail | Human-readable error message. Log this for debugging. Never show raw to end users. |
code | Stable machine-readable error code. Use this for branching logic. |
request_id | Unique ID for this failed request. Include when reporting to support. |
4xx: client errors (don't retry)
These mean your request needs fixing. Retrying without changing the request will return the same error.
400 Bad Request
Malformed request body or missing required field. Common variants:
code | Cause | Fix |
|---|---|---|
missing_field | A required field is absent | Add the field |
invalid_workspace_id | workspace_id is malformed | Use the format wt_xxxxxx_xxx from Settings > General |
message_too_long | message exceeds 4,000 characters | Trim or summarize before sending |
invalid_json | Body isn't valid JSON | Check Content-Type: application/json and the body |
401 Unauthorized
Missing or invalid API key. The header must be exactly Authorization: Bearer ak_xxx.
code | Cause | Fix |
|---|---|---|
missing_auth | No Authorization header | Add Authorization: Bearer ak_xxx |
malformed_auth | Header doesn't match Bearer ak_xxx | Check spelling, no quotes around the key |
invalid_key | Key was revoked or never existed | Generate a new key in the dashboard |
expired_key | Key expired (Enterprise contracts with TTL) | Rotate the key |
403 Forbidden
The API key is valid but lacks permission for the requested resource.
code | Cause | Fix |
|---|---|---|
workspace_access_denied | Key belongs to a different workspace owner | Use a key from the same account |
feature_not_in_plan | Endpoint requires a higher plan | Upgrade |
verification_required | Identity verification required for this query | Pass verification_token |
404 Not Found
The resource doesn't exist.
code | Cause | Fix |
|---|---|---|
workspace_not_found | workspace_id doesn't exist or was deleted | Confirm the ID in Settings > General |
conversation_not_found | conversation_id is invalid | Omit it to start a fresh conversation |
document_not_found | A document in document_ids doesn't exist | Check Knowledge Hub |
409 Conflict
The request conflicts with the current state.
code | Cause | Fix |
|---|---|---|
plan_downgrade_blocked | Subscription downgrade isn't allowed mid-cycle | Cancel current subscription, then re-subscribe |
duplicate_request_id | Idempotency key already used | Use a fresh request ID |
422 Unprocessable Entity
The request parsed but a field violates a constraint.
code | Cause | Fix |
|---|---|---|
invalid_top_k | top_k is outside 1 to 10 | Use a value in range |
invalid_temperature | temperature is outside 0.0 to 1.0 | Use a value in range |
invalid_strictness | strictness is neither "strict" nor "helpful" | Use one of the valid values |
invalid_audience | audience array contains tags not configured for the workspace | Check Knowledge Hub audience tags |
429 Too Many Requests
Rate limit exceeded. The response includes Retry-After in seconds.
code | Cause | Fix |
|---|---|---|
rate_limit_minute | Per-minute cap hit | Wait Retry-After seconds, retry |
rate_limit_day | Per-day cap hit | Wait until midnight UTC, or upgrade |
quota_exhausted | Monthly query allowance fully used | Upgrade plan or wait for cycle reset |
See rate limits for cap values per plan.
5xx: server errors (retry with backoff)
These mean our infrastructure had a transient problem. Retry with exponential backoff.
500 Internal Server Error
Unexpected server error. Should be rare.
code | Cause | Fix |
|---|---|---|
internal_error | An exception slipped through | Retry. If it persists, contact support@askvault.co with request_id |
model_provider_error | Upstream LLM provider returned an error | Retry; AskVault's automatic failover usually kicks in within seconds |
502 Bad Gateway / 503 Service Unavailable
Temporary infrastructure issue.
code | Cause | Fix |
|---|---|---|
upstream_timeout | Backend service timed out | Retry with backoff |
deploying | We're rolling out a new version | Retry after 30 seconds |
provider_down | All upstream LLM providers are unavailable | Retry; this is rare and usually resolves in minutes |
504 Gateway Timeout
Your request took too long. Usually only happens on the synchronous /v1/query endpoint with very long retrieval. Switch to /v1/query/stream for time-sensitive UX.
Retry strategy
A simple, correct retry loop:
import time, requestsfrom random import uniform
def call_askvault(payload, max_attempts=5): for attempt in range(max_attempts): r = requests.post( "https://api.askvault.co/v1/query", headers={"Authorization": f"Bearer {API_KEY}"}, json=payload, timeout=30, ) if r.status_code == 200: return r.json() # 4xx: don't retry except 429 if 400 <= r.status_code < 500 and r.status_code != 429: raise Exception(f"Client error {r.status_code}: {r.json()['detail']}") # 429: respect Retry-After if r.status_code == 429: time.sleep(int(r.headers.get("Retry-After", 1))) continue # 5xx: exponential backoff with jitter sleep_s = (2 ** attempt) + uniform(0, 1) time.sleep(sleep_s) raise Exception("Max attempts exceeded")Rules of thumb:
- 4xx other than 429: don't retry. The request is wrong; retrying gives the same error.
- 429: sleep for
Retry-Afterseconds, then retry. - 5xx: exponential backoff with jitter. Max 5 attempts.
Debugging tips
Three habits that make debugging much faster:
- Log
request_idfrom every response, including errors. When you contact support, paste therequest_idso we can find the exact failure in our logs. - Distinguish 4xx and 5xx in your monitoring. 4xx counts are client bugs; 5xx counts are our problem. Mixing them in the same alert obscures both.
- Track the
codefield, not just the status code. Codes are more granular and stable across status code changes.
Common pitfalls
Treating every 4xx the same. A 401 means "fix auth", a 422 means "fix the request body", a 429 means "wait then retry". Different recovery paths.
Retrying 4xx in a loop. Burns your retry budget and slows everything down. Stop on 4xx (except 429).
Ignoring Retry-After. Retrying immediately after a 429 just gets another 429 and digs you deeper. Sleep for the suggested duration.
Not surfacing failed conversations to humans. A 5xx error shouldn't leave the customer stuck. Either retry transparently or hand off to a human via the escalate_to_human skill on your widget channel.
FAQ
How do I know if my retry was successful?
Same request_id makes the response idempotent if you pass Idempotency-Key: same-value on the retry. Without it, the server treats each retry as a new query (and consumes quota each time).
Are 5xx errors charged against my quota?
No. Failed requests don't count against your monthly query allowance.
What if I'm seeing only 5xx, never 2xx?
Check our status page. If we're up, the issue is your network or DNS. If we're down, watch the status page for the all-clear.
How do I reach support for a stuck error?
Email support@askvault.co with the request_id and the exact error response body. We can find the exact query in our logs and respond within one business day on every paid plan.
Related guides
- Getting started with the AskVault API
- API authentication
- Rate limits per plan
- POST /v1/query reference