> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anyformat.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Introduction

> API v3 overview — base URL, resource model, keyset pagination, idempotency, response headers, and the error envelope.

anyformat API **v3** is the current stable major. It exposes the same extraction engine as v2 through a smaller, flatter surface built around three resources: [workflows](/concepts/workflows), [document packets](/concepts/document-packets), and [runs](/concepts/runs-and-results).

Coming from v2? The [migration guide](/api-reference-v3/migrating-from-v2) maps every v2 path to its v3 successor. v2 keeps serving traffic through its announced deprecation window, unchanged.

***

## Base URL

```
https://api.anyformat.ai/v3/
```

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 require an API key, passed as a Bearer token:

```bash theme={null}
curl -H "Authorization: Bearer YOUR_API_KEY" https://api.anyformat.ai/v3/workflows/
```

See [Authentication](/api-reference/authentication) for how to obtain and manage API keys — keys work identically across v2 and v3.

***

## Resource model

| Resource            | What it is                                                                                          | Identifier           |
| ------------------- | --------------------------------------------------------------------------------------------------- | -------------------- |
| **Workflow**        | The extraction template — a typed graph of parse / classify / splitter / extract / validate nodes.  | `workflow_id`        |
| **Document packet** | The unit a workflow runs on — one or more files treated as a single document. Created by uploading. | `document_packet_id` |
| **Run**             | One execution attempt of a workflow against a packet. One packet can have many runs.                | `run_id`             |

All identifiers are hyphenated UUIDs (e.g. `069dcc2c-e14c-7606-8000-2ee4fb17b4e1`). Path parameters are always snake\_case: `workflow_id`, `document_packet_id`, `run_id`.

The typical flow:

1. [Create a workflow](/api-reference-v3/workflows/create) (or build it visually in the [dashboard](https://app.anyformat.ai)).
2. [Upload and run](/api-reference-v3/workflows/upload-and-run) a document in one call — it returns a `run_id`.
3. [Get the run](/api-reference-v3/runs/get) until `status` is `processed`; the results envelope is inline on the same response.

***

## Pagination

Every list endpoint is **keyset-paginated** and returns the same page shape:

```json theme={null}
{
  "items": [ ... ],
  "next_cursor": "eyJjcmVhdGVkX2F0Ijoi..."
}
```

* `?limit=` — page size, default `20`, maximum `100`. Values above 100 are rejected with `400`, not clamped.
* `?cursor=` — the opaque `next_cursor` token from the previous page.
* Iterate by following `next_cursor` until it is `null`.
* Sort order is fixed at newest-first (`-created_at, -id`).

There are **no totals, counts, or page numbers** — a count over a growing collection is stale the moment it is computed, so v3 doesn't pretend otherwise. List endpoints also reject unknown query parameters with `400` instead of silently ignoring them, so a typo like `?pagesize=` fails loudly.

***

## Idempotency

The three POSTs that create packets or trigger runs accept an optional `Idempotency-Key` header (Stripe convention — any unique string you choose, e.g. a UUID):

* [`POST /v3/workflows/{workflow_id}/upload/`](/api-reference-v3/workflows/upload)
* [`POST /v3/workflows/{workflow_id}/upload/run/`](/api-reference-v3/workflows/upload-and-run)
* [`POST /v3/document-packets/{document_packet_id}/run/`](/api-reference-v3/document-packets/run)

Retrying a request with the same key **replays the original response** — no duplicate packet is created, no second extraction is triggered or billed. Use it to make network-timeout retries safe.

```bash theme={null}
curl -X POST 'https://api.anyformat.ai/v3/document-packets/069dcc2c-e14c-7606-8000-2ee4fb17b4e1/run/' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Idempotency-Key: 5f2b6c3e-8a1d-4f7e-9c0b-1a2b3c4d5e6f'
```

***

## Rate limits

Same two-tier model as v2 — submission endpoints have a stricter limit, everything else shares a higher general limit:

| Tier           | v3 endpoints                                                                                                   | Limit            |
| -------------- | -------------------------------------------------------------------------------------------------------------- | ---------------- |
| **Submission** | `POST .../upload/`, `POST .../upload/run/`, `POST .../upload/from-url/`, `POST /v3/document-packets/{id}/run/` | 60 requests/min  |
| **General**    | All other authenticated endpoints                                                                              | 600 requests/min |

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:

```http theme={null}
X-API-Version: 3.0.0
```

v3 responses carry **no** `Deprecation` or `Sunset` headers — those appear only on versions that are on the retirement path (as `/v2/` responses do today). See [Versioning & deprecation](/api-reference/introduction#versioning--deprecation) for the full header reference and how to alert on sunset signals.

***

## Errors

Error responses use the same structured envelope as v2:

```json theme={null}
{
  "error": "Brief, human-readable error description",
  "detail": "Detailed explanation of what went wrong",
  "error_code": "MACHINE_READABLE_ERROR_CODE",
  "retryable": false,
  "request_id": "a1b2c3d4e5f67890abcdef1234567890"
}
```

`retryable: true` means the same request may succeed on retry (with backoff); `retryable: false` means you must change the request first. See [Errors](/api-reference/errors) for the complete code reference. Two codes worth knowing up front:

* `402 PAYMENT_REQUIRED` — a run trigger was rejected because the organization is out of extraction credit.
* `400 TOPOLOGY_INVALID` — a workflow create/update body failed graph validation; `detail.violations` lists each broken rule with the offending node ids.

<Note>
  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](/api-reference-v3/runs/get).
</Note>

***

## Endpoints at a glance

### Workflows

| Method | Endpoint                       | Description                                                                 |
| ------ | ------------------------------ | --------------------------------------------------------------------------- |
| POST   | `/v3/workflows/`               | [Create a workflow](/api-reference-v3/workflows/create)                     |
| GET    | `/v3/workflows/`               | [List workflows](/api-reference-v3/workflows/list)                          |
| GET    | `/v3/workflows/{workflow_id}/` | [Get a workflow](/api-reference-v3/workflows/get) — full typed graph inline |
| PATCH  | `/v3/workflows/{workflow_id}/` | [Update a workflow](/api-reference-v3/workflows/update)                     |
| DELETE | `/v3/workflows/{workflow_id}/` | [Delete a workflow](/api-reference-v3/workflows/delete)                     |

### Upload

| Method | Endpoint                                       | Description                                                                    |
| ------ | ---------------------------------------------- | ------------------------------------------------------------------------------ |
| POST   | `/v3/workflows/{workflow_id}/upload/`          | [Upload a document packet](/api-reference-v3/workflows/upload) (no processing) |
| POST   | `/v3/workflows/{workflow_id}/upload/run/`      | [Upload and run](/api-reference-v3/workflows/upload-and-run) in one call       |
| POST   | `/v3/workflows/{workflow_id}/upload/from-url/` | [Create a packet from URLs](/api-reference-v3/workflows/upload-from-url)       |

### Document packets

| Method | Endpoint                                         | Description                                                                      |
| ------ | ------------------------------------------------ | -------------------------------------------------------------------------------- |
| GET    | `/v3/workflows/{workflow_id}/document-packets/`  | [List a workflow's packets](/api-reference-v3/document-packets/list)             |
| GET    | `/v3/document-packets/{document_packet_id}/`     | [Get a packet](/api-reference-v3/document-packets/get) — files + `latest_run_id` |
| POST   | `/v3/document-packets/{document_packet_id}/run/` | [Run a packet](/api-reference-v3/document-packets/run) — returns a new `run_id`  |
| DELETE | `/v3/document-packets/{document_packet_id}/`     | [Delete a packet](/api-reference-v3/document-packets/delete)                     |

### Runs

| Method | Endpoint                            | Description                                                       |
| ------ | ----------------------------------- | ----------------------------------------------------------------- |
| GET    | `/v3/workflows/{workflow_id}/runs/` | [List a workflow's runs](/api-reference-v3/runs/list)             |
| GET    | `/v3/runs/{run_id}/`                | [Get a run](/api-reference-v3/runs/get) — status + results inline |

***

## OpenAPI schema

The full OpenAPI specification (v2 + v3) is available at:

* **JSON**: [https://api.anyformat.ai/schema/?format=json](https://api.anyformat.ai/schema/?format=json)
* **Swagger UI**: [https://api.anyformat.ai/docs/](https://api.anyformat.ai/docs/)
