Errors
The one error shape of the PDF Loft API, and every stable error code with its status and meaning.
One error shape
Every error, from every route, has this shape. Branch on error, which is stable. The message is written for a person and may change.
{
"statusCode": 402,
"error": "tasks.exhausted",
"message": "The account has used its tasks for this period.",
"requestId": "5b6c0c88-6d06-4a62-9a0e-6c3c3e1b9b0e",
"details": { "limit": 2000, "used": 2000, "resetsAt": "2026-12-01T00:00:00.000Z" }
}requestIdis also sent in theX-Request-Idheader. Quote it to support. You may send your ownX-Request-Idof letters, digits, dots, underscores and hyphens, up to 128 characters, and it is used.detailsholds numbers you can act on, such as a limit and when it resets.fieldslists the inputs of avalidation_failederror.- A 5xx answer never carries internal text. Retry with backoff, and keep the request id.
Error codes
| Code | Status | Meaning |
|---|---|---|
validation_failed | 400 | The request body, query or a path value is not valid. The fields array names each invalid input. |
invalid_api_key | 401 | The key is missing, malformed or unknown, or the person who made it is no longer an owner or admin of the account. |
api_key_revoked | 401 | The key was revoked. Make a new key. |
api_key_expired | 401 | The key passed its expiry date. Make a new key. |
plan_required | 402 | The account plan does not include the API. The API is included in the Team plan and above. |
signatures.exhausted | 402 | The account has used its signature requests for this period. The details give the limit, the amount used, the amount a bulk send needed and when the period resets. |
tasks.exhausted | 402 | The account has used its tasks for this period. The details give the limit, the amount used and when it resets. |
credits.exhausted | 402 | The account has used its AI credits for this period. The details give the limit and when it resets. |
insufficient_scope | 403 | The key does not hold the scope this call needs. The details name the scope. |
forbidden | 403 | The person who owns the key may read this signature request but not change it. Only the sender, or an owner or admin for an account-wide request, can. |
read_only | 403 | The person who owns the key has read only access to the account. |
not_found | 404 | There is no such tool, run, file, document or endpoint in this account. Another account resources are never revealed. |
result.expired | 410 | The result was deleted two hours after the run. Run the tool again, or save results as documents. |
idempotency_in_progress | 409 | A request with the same Idempotency-Key is still running. Wait a moment and send it again. |
signature.not_draft | 409 | The signature request was already sent. |
signature.not_open | 409 | The signature request is complete, voided, or no longer waiting for signatures. |
signature.not_completed | 409 | The signed document and the certificate are made when every signer has signed. |
storage.full | 409 | Saving the document would take the library past the storage limit of the plan. |
storage.over_limit | 409 | The library is over its storage limit, so nothing new is saved until space is freed or the plan changes. |
webhook.limit_reached | 409 | The account already has the most webhook endpoints it may have. |
file.too_large | 413 | A file is larger than the plan or the tool allows. The details give maxBytes. |
payload_too_large | 413 | A JSON body is larger than 1 MB. |
unsupported_media_type | 415 | The body has a content type the route does not read. Send JSON, or a file only to POST /v1/files. |
file.type_refused | 415 | No tool reads this content type, this tool does not read it, or the bytes of the file are not the type it declares. The check reads the file itself, never only the Content-Type header. |
idempotency_key_reused | 422 | The Idempotency-Key was already used with a different request. |
idempotency_key_invalid | 400 | The Idempotency-Key is not 1 to 255 visible ASCII characters. |
run.too_many_files | 400 | More files than one run of the tool takes on the plan. The details give the limit. |
run.too_few_files | 400 | The tool needs more files. The details give the minimum. |
options.invalid | 400 | The options do not fit the tool. |
tool.runs_on_device | 400 | The tool has no server version, so it cannot be run through the API. Every tool in the current list has one; the code is kept for a tool added later that runs in the browser only. |
webhook.url_refused | 400 | The endpoint address is not a public https address. Private, loopback, link-local and metadata addresses are refused. |
rate_limited | 429 | The key passed its calls a minute. Wait for the Retry-After seconds. |
tool.unavailable | 503 | The tool cannot run right now. Try again later. |
service.unavailable | 503 | The API or storage is not available right now. Try again. |
internal_error | 500 | Something went wrong on the PDF Loft side. Quote the requestId to support. |