Errors
Every status code, what causes it, and how to fix it.
Error response format
All error responses follow this structure:
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable description of what went wrong",
"requestId": "req_a1b2c3d4"
}
}code: Machine-readable error code. Use this for programmatic error handling.message: Human-readable description. Safe to display to end users.requestId: Unique request identifier. Include this when contacting support.
This is the shape for every endpoint documented in this API reference. A separate, per-IP request limiter guards login, invites, and most dashboard/admin endpoints; its 429 responses are a bare {"error": "Rate limit exceeded: ..."} string, not this object. See Rate limits.
Error codes
| Status | Code | Meaning |
|---|---|---|
200 | None | Success |
401 | UNAUTHORIZED | Missing API key |
401 | INVALID_API_KEY | API key is malformed or does not match a live key |
401 | API_KEY_REVOKED | API key has been revoked |
402 | INSUFFICIENT_CREDITS | The organization's balance cannot cover the request |
402 | BILLING_SUSPENDED | Billing is on hold for the organization |
403 | NO_COLLECTION_ACCESS | No access to requested collection |
403 | SANDBOX_UNSUPPORTED_ENDPOINT | Sandbox key used on an endpoint with no sandbox behaviour |
404 | COLLECTION_NOT_FOUND | Collection not found |
409 | IDEMPOTENCY_KEY_IN_PROGRESS | A preview with this Idempotency-Key is still running |
410 | CACHED_RESULT_EXPIRED | Cached result or preview has expired (7-day window), or the preview was written by an older payload version |
422 | VALIDATION_ERROR | Invalid request body |
422 | INVALID_FILTER | A search filter cannot be applied: unknown field, unsupported operator combination, or invalid value |
422 | INVALID_QUERY | The query carries too little to search on, such as only symbols, only stop words, or one repeated character |
422 | IDEMPOTENCY_KEY_REUSED | This Idempotency-Key was already used with a different request body |
429 | QUOTA_EXCEEDED | Per-minute, daily, or monthly quota exceeded |
429 | API_KEY_BUDGET_EXCEEDED | The API key's spending cap is used up |
429 | PREVIEW_RATE_LIMIT_EXCEEDED | Preview rate limit exceeded |
429 | SEARCH_RATE_LIMITED | Too many rejected queries in a short time |
500 | INTERNAL_ERROR | Internal server error |
503 | SERVICE_UNAVAILABLE | A dependency the request needs (e.g. the quota service) is unreachable |
Handling errors in the SDKs
Every non-2xx response becomes a typed error carrying status, code, message and requestId from the envelope above, so the code column is what you branch on and requestId is what you send to support. 429 and 503 are retried automatically before they surface (see Rate limits).
| Status | Python | TypeScript | Go |
|---|---|---|---|
401 | AuthError | AuthError | *AuthError |
402 | InsufficientCredits | InsufficientCredits | *InsufficientCreditsError |
403 | AccessDenied | AccessDenied | *AccessDeniedError |
404 | NotFound | NotFound | *NotFoundError |
410 | Expired | Expired | *ExpiredError |
422 | ValidationError | ValidationError | *ValidationError |
429 | QuotaExceeded | QuotaExceeded | *QuotaExceededError |
503 | AssistedUnavailable | AssistedUnavailable | *AssistedUnavailableError |
| anything else | RedpineError | RedpineError | *APIError |
from redpine import AccessDenied, QuotaExceeded, RedpineError
try:
r = client.search("your search query", collection="my-collection")
except AccessDenied as e:
print("key cannot reach this collection:", e.code) # NO_COLLECTION_ACCESS
except QuotaExceeded as e:
print("back off for", e.retry_after, "seconds")
except RedpineError as e:
print(e.status, e.code, e.message, e.request_id)A missing key never reaches the network: the Python and TypeScript constructors raise AuthError and Go's New returns an error when no explicit key is given and neither REDPINE_API_KEY nor the legacy CONNECT_API_KEY is set.
Troubleshooting
- 401 UNAUTHORIZED: The Authorization header is missing entirely. Include
Authorization: Bearer sk_live_...(orsk_test_...for sandbox). - 401 INVALID_API_KEY: The header is present but the key doesn't match a live key. Check for typos or a stale/rotated key.
- 401 API_KEY_REVOKED: The key was revoked. Generate a new one. Retrying with a revoked key will keep failing.
- 402 INSUFFICIENT_CREDITS: The balance cannot cover the request. Nothing is charged; add credits or a payment method and retry the same request.
- 402 BILLING_SUSPENDED: Billing is on hold for the organization, or the balance check is briefly unavailable. Retry once; if it persists, contact support.
- 403 NO_COLLECTION_ACCESS: The API key doesn't have access to this collection. Use an org-wide key or add the collection to the key's scope.
- 403 SANDBOX_UNSUPPORTED_ENDPOINT: The key is a sandbox key (
sk_test_) and this endpoint has no sandbox behaviour. Use a live key, or one of the endpoints listed in Sandbox. This is deliberate: an endpoint that quietly behaved normally would leave you unable to tell a fixture from a real result. - 404 COLLECTION_NOT_FOUND: Verify the collection name exists. Names are case-sensitive.
- 410 CACHED_RESULT_EXPIRED: The
queryIdyou passed toGET /api/v1/search/results/{queryId}orPOST /api/v1/search/unlockis older than the 7-day window, or the preview it points to was written by an older payload version. Run the search or preview again to get a freshqueryId. - 422 VALIDATION_ERROR: Check required fields (query is required; exactly one of collection/collections). Ensure query is under 1000 characters (16,000 on
POST /api/v1/search/assisted) and limit is between 1-30. OnPOST /api/v1/search/unlock, this also covers aresultIdthat isn't part of the preview and any unrecognized field in the request body. Both preview and unlock reject unknown keys rather than ignoring them. - 422 INVALID_FILTER: The
messagesays what to change and names the field where there is one (also indetails.field). Common causes: a field name typo (the message lists the indexed fields),doc_id, ajournal_metric.*threshold outside the metric bounds or matching more than 35,000 ISSNs, two operator families in one condition, a field the collection has no index for, or an invalid date orarticle_type. Retrying the same filter fails the same way. See Filtering. - 422 INVALID_QUERY: The query has too little to search on: only whitespace or symbols, too few letters or digits, one character repeated (
aaaaaaa), the same word over and over, or only stop words (what is the). Short identifiers such asp53,BRCA1orCOVID-19are fine. Rephrase the query; retrying it unchanged fails the same way. - 409 IDEMPOTENCY_KEY_IN_PROGRESS and 422 IDEMPOTENCY_KEY_REUSED: See Retrying a preview safely. Retry the first after a moment; for the second, send a new key.
- 429 QUOTA_EXCEEDED: You've hit the per-minute, daily, or monthly quota. Back off and retry. See Rate limits for how long each window takes to reset.
- 429 API_KEY_BUDGET_EXCEEDED: The key has reached the spending cap set on it in the dashboard. The cap applies however the key is used, including through MCP sign-in and paid integration tools. Ask an organization admin to raise the cap, or use another key.
- 429 PREVIEW_RATE_LIMIT_EXCEEDED: This organization's preview rate limit was exceeded. Wait for the Retry-After period. See Rate limits for the current per-hour default.
- 429 SEARCH_RATE_LIMITED: More than 30 queries were rejected as
INVALID_QUERYwithin a minute. Wait for theRetry-Afterperiod and check what is generating the queries. - 500 INTERNAL_ERROR: An unexpected error occurred. Retry the request. If it persists, contact support with the requestId.
- 503 SERVICE_UNAVAILABLE: A backing service the request depends on (e.g. the quota check
POST /api/v1/search/unlockperforms) is temporarily unreachable. On unlock, this happens before the charge commits: nothing is charged and no result is unlocked, so it's safe to retry with backoff.
Usage is tracked per API key. View statistics on your Usage page in the dashboard.