Skip to content
RagextractAPIStart freeSign-up and sign-in are temporarily unavailable — please check back shortly.

Errors

Failures arrive in one of two shapes depending on how far into the request they happened. Check the status code before you parse the body.

Two shapes

Rejections before the handler runs — a missing or invalid key, a workspace this key cannot reach, an insufficient permission level, a rate limit — come back as plain text. The body is the message and nothing else.

Response
HTTP/1.1 401 Unauthorized
content-type: text/plain;charset=UTF-8

Unauthorized. Missing API key.

Rejections from inside the handler — a resource that does not exist, a malformed body, a balance that cannot cover the work — come back as JSON, in the envelope's failure form.

Response
HTTP/1.1 404 Not Found
content-type: application/json

{
  "success": false,
  "error": "Dataset not found"
}

There is no unifying error object and no machine-readable error code. Branch on the status; use the message for a log line, not for control flow — the wording is not contract and can be improved without notice.

Request
res=$(curl -s -w '\n%{http_code}' \
  https://api.ragextract.com/v2/workspaces/wks_7Kq2mB4nR8vXpL3d/files \
  -H "x-api-key: $RAGEXTRACT_API_KEY")

body=${res%$'\n'*}
code=${res##*$'\n'}

# The body is JSON on success and on a handler error, and plain text on an
# auth, permission or rate-limit error. Test the status first.
[ "$code" -ge 400 ] && echo "failed ($code): $body" && exit 1

Status codes

StatusMeans
400The request body or query failed validation, or an endpoint's own precondition did not hold — an upload naming neither a file nor a URL, an unknown or expired upload session, an image_url pointing somewhere it may not.
401No key, an unknown key, an expired key, or a share token that does not verify. Every bad-credential path returns the same sentence on purpose, so the response cannot be used to tell a wrong key from an expired one.
403The workspace or table is reachable, but this key's level is below what the endpoint needs — a read-only grant on a write route.
402Not enough credits, or the organisation's monthly spend cap would be passed. From a run it is JSON carrying the numbers (see below); from search it is plain text, because the refusal happens in middleware.
404Either the resource does not exist, or it exists and this key cannot reach it at all. The two are deliberately not distinguished — see below.
429Over the rate limit. Back off and retry; there is no header saying how long to wait.
503A dependency we refuse to serve around — today, the search meter failing to write. Retry: the block claim is idempotent, so a retried search is not charged twice.
500Something on our side. Safe to retry an idempotent read; for a write, check the resource's state before repeating it.

Why an unreachable workspace is 404

A key that cannot reach a workspace gets 404, not 403, and the same holds for a table. That is not sloppiness. Answering 403 would confirm the id exists, and since ids appear in URLs, a narrowly scoped key could walk the organisation's id space one request at a time and learn what it has.

The rule to build against: 404 means "not yours or not there", and there is no way to tell which from the outside. 403 means "yours, but not at this level" — the fix is a wider scope or a higher sharing level, not a different id.

Running out of credits

Starting a table run when the balance cannot cover it fails with 402 before any work happens, and the JSON body carries the numbers you need to explain it:

  • cost — what the run would have spent, in credits.
  • balance — what is available.
  • cap — present only when the refusal was the organisation's monthly spend cap rather than the balance. A cap is a self-imposed ceiling, so buying credits does not lift it; raising or clearing it is done in the app.

Price a run first with the free run preview and this never has to be an error path. Note that ingest behaves differently: it refuses only a balance that cannot cover a single page, because the page count is not known until the document has been read.

Silently ignored parameters

Unknown keys in a request body are stripped, not rejected. A misspelled parameter returns 200 with the option dropped, and nothing tells you. If an option appears to do nothing, check its spelling against the endpoint's parameter table before looking anywhere else.