anyformat exposes a REST API that lets you programmatically create workflows, process documents, and retrieve results. This page is the orientation guide — for a step-by-step walkthrough, see the quickstart.
For terminology (Workflow, Field, Run, etc.) start at Concepts. For complete worked examples (invoices, resumes, contracts, …) see Recipes.
Base URL
https://api.anyformat.ai/
All v2 endpoints use the /v2/ prefix — for example, https://api.anyformat.ai/v2/workflows/. When a new major version ships, /v2/ will continue to serve traffic for a bounded deprecation window — see Versioning & deprecation below to wire your integration for alerting.
All endpoint paths require a trailing slash. Requests without one receive a 307 Temporary Redirect, which preserves the request method and body.
Authentication
All endpoints (except /docs/ and /schema/) require an API key, passed as a Bearer token:
curl -H "Authorization: Bearer YOUR_API_KEY" https://api.anyformat.ai/v2/workflows/
See Authentication for how to obtain and manage API keys.
Rate limits
The API uses two-tier rate limiting. File submission endpoints have a stricter limit; all other endpoints share a higher general limit.
| Tier | Endpoints | Limit |
|---|
| Submission | POST /v2/workflows/{id}/run/, POST /v2/workflows/{id}/upload/, POST /v2/workflows/{id}/files/ | 60 requests/min |
| General | All other authenticated endpoints | 600 requests/min |
Each tier has an independent counter — extraction endpoints don’t consume your general quota, and vice versa.
If you exceed a limit, the API responds with 429 Too Many Requests. Wait for the number of seconds in the Retry-After header before retrying.
All successful responses include rate-limit headers for the tier that applies:
| Header | Description |
|---|
x-ratelimit-limit | Maximum requests allowed per window |
x-ratelimit-remaining | Requests remaining in current window |
x-ratelimit-reset | Seconds until the rate limit resets |
The Retry-After header appears only in 429 responses, not in every response.
Endpoints at a glance
The API is organized around three resource groups.
Workflows
| Method | Endpoint | Description |
|---|
| POST | /v2/workflows/ | Create a workflow |
| GET | /v2/workflows/ | List workflows |
| GET | /v2/workflows/{id}/ | Get a workflow |
| DELETE | /v2/workflows/{id}/ | Delete a workflow |
| POST | /v2/workflows/{id}/run/ | Run a workflow on a file |
| POST | /v2/workflows/{id}/upload/ | Upload a file (no processing) |
| GET | /v2/workflows/{id}/runs/ | List workflow runs |
Files
| Method | Endpoint | Description |
|---|
| POST | /v2/workflows/{workflow_id}/files/ | Upload a file |
| GET | /v2/workflows/{workflow_id}/files/ | List files |
| DELETE | /v2/files/{id}/ | Delete a file |
| GET | /v2/workflows/{workflow_id}/files/{id}/results/ | Get results |
Webhooks
| Method | Endpoint | Description |
|---|
| POST | /v2/webhooks/ | Create a webhook |
| GET | /v2/webhooks/ | List webhooks |
| DELETE | /v2/webhooks/{id}/ | Delete a webhook |
See Webhooks overview for setup, signing, and delivery semantics.
Successful responses are JSON. The detailed envelope (including as_lists=true for tabular shapes) is documented in Response formats.
Error responses follow a consistent structured shape:
{
"error": "Brief, human-readable error description",
"detail": "Detailed explanation of what went wrong",
"error_code": "MACHINE_READABLE_ERROR_CODE",
"retryable": false,
"request_id": "a1b2c3d4e5f67890abcdef1234567890"
}
See Errors for the complete error code reference and retry patterns.
Versioning & deprecation
The API is versioned in the URL path. The current stable major is /v2/. When a new major (e.g. /v3/) is introduced, the previous one continues to serve traffic through an announced deprecation window before it is shut down.
/v2/ is deprecated and sunsets on October 3, 2026. See the v2 → v3 migration guide for the endpoint-by-endpoint mapping.
Every response carries a version identifier, plus deprecation signals whenever the version you called is on the retirement path.
| Header | When emitted | Value |
|---|
X-API-Version | Every /v2/ response | Current major version (e.g. 2.0.0) |
Deprecation | Only while a version is deprecated | HTTP-date the deprecation was announced (RFC 8594) |
Sunset | Only while a version is deprecated | HTTP-date after which the version stops serving traffic |
Link | Only when a per-route successor exists | <https://api.anyformat.ai/vN/...>; rel="successor-version" — the equivalent endpoint on the newer version |
Example — a call to a deprecated endpoint:
HTTP/1.1 200 OK
X-API-Version: 2.0.0
Deprecation: Fri, 03 Jul 2026 00:00:00 GMT
Sunset: Sat, 03 Oct 2026 00:00:00 GMT
Link: </v3/workflows/abc/>; rel="successor-version"
Content-Type: application/json
The Deprecation and Sunset headers are absent while a version is not deprecated — so their presence alone is a reliable signal that migration work is due.
Don’t get surprised — alert on Sunset
Deprecation windows are typically three months between the Deprecation announcement and the Sunset cutoff. Rather than tracking release notes by hand, we strongly recommend wiring your integration to detect these headers automatically. A minimal setup:
- In your HTTP client middleware, check every response for a
Sunset header. If present, emit a warning to your logs or monitoring system that includes the endpoint path and the sunset date.
- In your metrics / observability stack, add a counter or gauge indexed by
X-API-Version, Deprecation, and Sunset. A dashboard panel or alert firing on “any response has Sunset” gives on-call visibility without human polling.
- Escalate as the sunset approaches: for example, log-level warning at first sight, page on-call one month before
Sunset, hard-fail your CI a week before if you still have live traffic on the deprecated version.
Example — a five-line Python wrapper around requests that surfaces the signal:
import logging
import requests
def call(method: str, url: str, **kw) -> requests.Response:
response = requests.request(method, url, **kw)
if sunset := response.headers.get("Sunset"):
logging.warning(
"anyformat API deprecation: %s %s sunsets %s (successor: %s)",
method, url, sunset, response.headers.get("Link", "n/a"),
)
return response
Equivalent hooks exist in httpx (event hooks), axios (interceptors), fetch (a wrapping function), and every other mainstream HTTP client.
If you can only pick one thing: alert on the Sunset header. Everything else — endpoint, announcement date, successor URL — is derivable from the same response.
SDKs
Official client libraries with a fluent builder over the typed-graph API:
OpenAPI schema
The full OpenAPI specification is available at: