410 Gone.
Base URL
307 Temporary Redirect, which preserves the request method and body.
Authentication
All endpoints require an API key, passed as a Bearer token:Resource model
All identifiers are hyphenated UUIDs, such as
069dcc2c-e14c-7606-8000-2ee4fb17b4e1. Path parameters are always snake_case: workflow_id, document_packet_id, run_id.
The typical flow:
- Create a workflow (or build it visually in the dashboard).
- Upload and run a document in one call. The response carries a
run_id. - Get the run until
statusisprocessed; the results envelope is inline on the same response.
Pagination
Every list endpoint is keyset-paginated and returns the same page shape:?limit=sets the page size. The default is20and the maximum is100. A larger value returns400; the API does not clamp it.?cursor=takes the opaquenext_cursortoken from the previous page.- Iterate by following
next_cursoruntil it isnull. - Sort order is fixed at newest-first (
-created_at, -id).
400 rather than ignoring it, so a typo like ?pagesize= fails loudly.
Idempotency
The POSTs that create packets or trigger runs accept an optionalIdempotency-Key header. The value is any unique string you choose, such as a UUID.
POST /v3/workflows/{workflow_id}/upload/POST /v3/workflows/{workflow_id}/upload/run/POST /v3/document-packets/{document_packet_id}/run/POST /v3/workflows/{workflow_id}/evals/
422 IDEMPOTENCY_KEY_REUSED. A key binds to the first request it saw; send a fresh key for a genuinely new request.
Rate limits
Submission endpoints have a stricter limit, and so does downloading a split, which renders a document on every request. Everything else shares a higher general limit. Each tier counts separately.
Exceeding a limit returns
429 Too Many Requests; wait for the number of seconds in the Retry-After header. Every response carries x-ratelimit-limit, x-ratelimit-remaining, and x-ratelimit-reset for the tier that applies.
Response headers
Every/v3/ response is stamped with the API version:
Deprecation or Sunset headers. A version on the retirement path would add them, per RFC 8594, so alerting on Sunset catches a future retirement early.
Compression
SendAccept-Encoding: gzip and JSON responses over 1 KB come back gzip-compressed, with Content-Encoding: gzip. A run’s results compress about 4x, so a large run downloads faster. Without the header, you get the same response uncompressed.
The SDKs, the CLI, Python requests and httpx, and JavaScript fetch send the header and decompress for you. Some clients need it set by hand:
Errors
Error responses use the same structured envelope as v2:retryable: true means the same request may succeed on retry, with backoff. retryable: false means you must change the request first. See Errors for the complete code reference. Two codes are worth knowing up front:
402 PAYMENT_REQUIRED: the organization is out of extraction credit, so the API rejected the run trigger.400 TOPOLOGY_INVALID: a workflow create or update body failed graph validation.detail.violationslists each broken rule with the offending node ids.
v3 never returns
412 Precondition Failed. Where v2 used 412 to signal “results not ready yet”, v3 returns 200 with the run’s status field. See Get run.Endpoints at a glance
Workflows
Upload
Document packets
Runs
OpenAPI schema
The full OpenAPI specification is available at:- JSON: https://api.anyformat.ai/schema/?format=json
- Swagger UI: https://api.anyformat.ai/docs/

