DocsErrors & limits

Open the app →

Errors & limits

Every error uses one envelope: a stable type for programmatic handling, a specific code, and a human-readable message.

Envelope
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_file_type",
    "message": "Supported types: PDF, JPEG, PNG, HTML."
  }
}

Status codes

Statustype / codeWhen
200Successful GETs; POST with wait=true that finished in time.
202POST accepted; extraction continues in the background.
400invalid_request_error · missing_file, invalid_base64, invalid_body, invalid_parameterMalformed body or parameters.
401authentication_error · missing_api_key, invalid_api_keyNo key, unknown key, or revoked key.
403authentication_error · insufficient_scopeA read-only key called a write endpoint.
404not_found · invoice_not_found, route_not_foundUnknown id (or an id on another account) or path.
405invalid_request_error · method_not_allowedWrong verb on a known path.
413invalid_request_error · file_too_largeOver 15 MB.
415invalid_request_error · unsupported_file_typeNot PDF/JPEG/PNG/HTML.
409api_error · idempotency_in_flightA request with the same Idempotency-Key is still processing.
422invalid_request_error · file_url_unreachablefile_url could not be fetched.
429rate_limit_error · rate_limited, or quota_exceeded · monthly_quota_reachedPer-key rate limit (respect Retry-After) or the account's monthly plan quota.
500api_error · internalOur fault. Safe to retry with backoff.

Rate limits

60 requests per minute per API key. Every authenticated response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (unix seconds) so clients can back off before hitting 429; 429 responses also include Retry-After. Rate limits protect the platform; they are separate from your plan's monthly extraction quota, which counts extractions across all channels (app, email, API). Check remaining quota anytime with GET /v1/me.

Idempotency & retries

Make POST /v1/invoices safe to retry by sending an Idempotency-Key header (any unique string up to 255 characters; a UUID works well). Retrying with the same key within 24 hours replays the original response (marked with an Idempotency-Replayed: true header) instead of ingesting the document again. If the original request is still processing, the retry gets 409 idempotency_in_flight; wait a moment and try again. Without the header, a retried create ingests twice (duplicate detection flags exact vendor + invoice number + amount matches, but sending a key is the safer path). GETs retry freely.

import { randomUUID } from "node:crypto";

await client.invoices.extract({
  fileUrl: "https://example.com/invoices/june.pdf",
  idempotencyKey: randomUUID(),
});