# Split A scanned bundle is often many documents in one file — invoices stapled to correspondence, filings behind cover letters. Split finds the boundaries and gives you each record's page range, so you can extract or classify one document at a time. **Before you start.** You need an API key from the [quickstart](/quickstart) and a document that has already been [parsed](/parsing) — an unparsed file returns `409 file_must_be_parsed`. Split needs the `extract.run` permission and viewer access to the file. Failures carry a stable `code`; the full list is on the [error codes](/errors) page. Both split endpoints are **queued**: they return `202` with an operation id to poll. That is the opposite of [classify](/classify), which answers inside the request. The polling contract lives on [document workflows](/workflows). ## Suggest rules Two steps. Suggest rules, then run the split with rules you accepted or wrote yourself. ```bash curl -s -X POST "$DOCAI_API/v1/split/rules/suggest" \ -H "x-api-key: $DOCAI_API_KEY" -H "content-type: application/json" \ -d '{"file_id":"'"$FILE_ID"'"}' ``` The call returns `202` with an operation id. Poll [`GET /v1/operations/{operationId}`](/api/operations#get-queued-operation-status-progress-and-output) until `status` is `completed` — the finished operation carries `{ rules, modelId }` under `output`, not in this response. Each rule has a `name` and a `description`; edit them freely before running. ## Run the split ```bash OP=$(curl -s -X POST "$DOCAI_API/v1/split/runs" \ -H "x-api-key: $DOCAI_API_KEY" -H "content-type: application/json" \ -d '{"file_id":"'"$FILE_ID"'","rules":[{"name":"Invoice","description":"One invoice per record"}]}' \ | jq -r .operation_id) curl -s "$DOCAI_API/v1/operations/$OP" -H "x-api-key: $DOCAI_API_KEY" ``` `split_run` completes with a split session: `sessionId`, `sourceDocId`, `sourceDocName`, `sourcePageCount`, `records`, `rules`, `quality`, `warnings`, `createdAt`, `updatedAt`, plus `operation_id` and `modelId`. Each record carries `id`, `title`, `documentType`, `startPage`, `endPage`, `segmentIds`, `metadata`, `confidence`, `boundaryReason` and `warnings`. `quality` reports `coverage`, `recordCount`, `pageCount`, `gapPages`, `overlapPages`, `duplicateRecordIds`, `invalidRecords` and a `status` of `pass`, `review` or `fail`. Treat `review` as needing a human. If every model window fails, the operation ends `failed` with an `error` beginning `split_model_unavailable` and carrying the first window's actual reason. That is an infrastructure failure, not a one-record document. ## 200 versus 202 A split POST is idempotent on the request identity: your `idempotency_key`, or one derived from the file, the rules and the model when you omit it. - No matching operation, or a `failed`/`cancelled` one — a fresh attempt is charged and queued. `202`. - A `queued` or `in_progress` one — you re-attach to it. `202`, no new charge. - A `completed` one — **`200` with the finished output inline**. There is nothing to poll. So handle `200` and `202` differently on the same call. A client that always polls will work, but a client that assumes 202 will read `operation_id` off a body that is a full split session. Send a fresh `idempotency_key` when you want real new work on unchanged inputs. The derived fallback is stable per file, rules and model, so it cannot distinguish two deliberate runs of the same request. ## Downloading a record ```bash curl -s -X POST "$DOCAI_API/v1/split/download" \ -H "x-api-key: $DOCAI_API_KEY" -H "content-type: application/json" \ -d '{"file_id":"'"$FILE_ID"'","startPage":1,"endPage":4,"title":"Invoice-001"}' \ -o Invoice-001.pdf ``` Returns that page range of the source PDF. Source must be a PDF. No model runs, so it costs no [credits](/quickstart), and it needs viewer file access only. ## Cost and model controls Rules suggest and a split run each debit exactly one credit per charged attempt, debited before work starts and refunded if the queued operation ends `failed` or `cancelled`. The shared request fields — `model_id`, `reasoning_level`, `idempotency_key` — and the full credit semantics are on [document workflows](/workflows). ## Where to next - [Document workflows](/workflows) — the operation model: polling, cancelling, credits and model controls shared by every workflow. - [Classify](/classify) — label the records a split found. - [API reference](/api/document-split) — every request body and response field.