> ## 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.

# Download a split

> Get one splitter sub-document's pages as a PDF

*Rate limit tier: **general**, 600 requests/min. See [Rate limits](/api-reference-v3/introduction#rate-limits). No credits are billed.*

A workflow with a splitter node carves one uploaded packet into sub-documents — the `splits[]` a run's results carry. This endpoint returns one of them as a PDF.

The document is built from the packet's source files when you ask for it and is never stored, so there is no artifact to expire and no second URL to follow: the bytes come back on this request.

## Finding the id

Read it off a processed run's results ([Get a run](/api-reference-v3/runs/get)).

An `id` is present when, and only when, it addresses exactly one sub-document:

| The splitter rule | Where the id is                                                              |
| ----------------- | ---------------------------------------------------------------------------- |
| No partition key  | `splits[].id` — the category is one sub-document, and `partitions` is empty. |
| A partition key   | `splits[].id` is `null` and each `splits[].partitions[].id` carries its own. |

A partitioned category is several sub-documents and no single one of them, so it has no id of its own. Download each partition instead.

## Caching

The response carries an `ETag` and `Cache-Control: private`. The tag is opaque — store the one you were given and send it back verbatim in `If-None-Match`, rather than building it from the split id. A split's pages never change (a new run of the same workflow mints new split ids), so a still-current split answers `304 Not Modified` without transferring the document again.

## Errors

| Status | `error_code`             | Meaning                                                                                                                                                                                                       |
| ------ | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `404`  | `NOT_FOUND`              | Unknown split id, or one belonging to another organization.                                                                                                                                                   |
| `409`  | `SPLIT_HAS_NO_PAGES`     | The category matched no page in this run. Every splitter rule gets a row, including the ones that matched nothing.                                                                                            |
| `409`  | `SPLIT_SOURCE_NOT_PDF`   | The split's source document could not be read as a PDF. A packet uploaded in another format is sliced out of the PDF the platform rendered for it, so this means that rendered copy is missing or unreadable. |
| `422`  | `INTERNAL_INCONSISTENCY` | The stored geometry names a page the source document does not have. Do not retry.                                                                                                                             |

<RequestExample>
  ```bash curl theme={null}
  curl -X GET 'https://api.anyformat.ai/v3/splits/3f2504e0-4f89-41d3-9a0c-0305e82c3301/pdf/' \
    -H 'Authorization: Bearer YOUR_API_KEY' \
    --output invoice.pdf
  ```

  ```python Python (SDK) theme={null}
  from anyformat.sdk import Client

  client = Client(api_key="YOUR_API_KEY")
  run = client.get_run("069dcc2c-e14c-7606-8000-2ee4fb17b4f9")

  for split in run.result.splits:
      for handle in ([split] if split.id else split.partitions):
          with open(f"{handle.name}.pdf", "wb") as out:
              out.write(client.download_split_pdf(handle.id))
  ```

  ```typescript TypeScript (SDK) theme={null}
  import { Anyformat } from "@anyformat/sdk";

  const af = new Anyformat({ apiKey: "YOUR_API_KEY" });
  const run = await af.getRun("069dcc2c-e14c-7606-8000-2ee4fb17b4f9");

  for (const split of run.results?.splits ?? []) {
    for (const handle of split.id ? [split] : split.partitions) {
      const pdf = await af.downloadSplitPdf(handle.id!);
      // `pdf` is a Blob — write it, upload it, or hand it to a viewer.
    }
  }
  ```
</RequestExample>


## OpenAPI

````yaml GET /v3/splits/{split_id}/pdf/
openapi: 3.1.0
info:
  title: anyformat API
  description: >
    Document extraction and workflow automation API.


    AnyFormat lets you define extraction workflows that pull structured data
    from any document — PDFs, images, scanned files, or plain text. Upload a
    file, run it through a workflow, and get back structured fields with
    confidence scores and source evidence.


    ## Quick start


    See the [Quick start
    guide](https://docs.anyformat.ai/api-reference/introduction) for a
    walkthrough.


    ## Authentication


    All endpoints (except `/health/`) require a Bearer token in the
    `Authorization` header:


    ```

    Authorization: Bearer <your-api-key>

    ```


    Get your API key from
    [app.anyformat.ai/api-key](https://app.anyformat.ai/api-key).


    ## Versioning


    Endpoints are versioned by path prefix (`/v2/`, `/v3/`). Every response
    under

    a versioned prefix includes `X-API-Version`.
  version: 2.0.0
servers:
  - url: https://api.anyformat.ai
    description: API server
security: []
tags:
  - name: workflows
    description: >-
      Workflows define extraction templates — what fields to extract from
      documents. Create workflows, upload files, run extractions, and fetch
      results.
  - name: files
    description: >-
      File collections group uploaded documents and track their extraction
      progress. Upload files, check status, and retrieve extraction results.
  - name: suggestions
    description: >-
      AI-powered schema and workflow suggestion endpoints for the AnyFormat
      webapp. Authenticated with a Cognito JWT rather than an API key.
  - name: document-packets
    description: >-
      Document packets group uploaded documents for a workflow (v3). Address a
      packet directly to (re-)run its workflow.
  - name: runs
    description: >-
      Extraction runs — the v3 first-class result entity. Each run is a single
      execution of a workflow against a document packet; fetch its status and
      results flat by run id.
  - name: splits
    description: >-
      Splits — the sub-documents a splitter node carves out of a packet.
      Download any one of them as a PDF, built from the source documents on
      request and never stored.
  - name: parse
    description: >-
      Parse a single document with the platform's fast lite parse — a one-call
      shortcut over the workflow upload + run primitives, backed by your
      organization's system parse workflow.
  - name: health
    description: Health check endpoints to verify API availability.
paths:
  /v3/splits/{split_id}/pdf/:
    get:
      tags:
        - splits
      summary: Download a split as a PDF
      description: >-
        Download one split's pages as a PDF.


        The document is built from the run's source files when you ask for it
        and

        is never stored, so the response reflects the split's current geometry.
        Take

        the id from `splits[].id` on a run's results, or from

        `splits[].partitions[].id` when the splitter partitions the category.


        The response carries an opaque `ETag` — send it back verbatim in

        `If-None-Match` and a still-current split answers `304` without

        transferring the document again. Do not build the tag yourself.
      operationId: v3_download_split_pdf
      parameters:
        - name: split_id
          in: path
          required: true
          schema:
            type: string
            title: Split Id
        - name: if-none-match
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            title: If-None-Match
      responses:
        '200':
          description: The split's pages as a PDF.
          content:
            application/pdf: {}
          headers:
            X-RateLimit-Limit:
              description: Requests allowed per window (60s).
              schema:
                type: integer
            X-RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            X-RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
        '304':
          description: Not modified — the `ETag` you sent is still current.
        '400':
          description: >-
            Validation failed — the request body or query parameters are
            invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                VALIDATION_ERROR:
                  value:
                    error: The request failed validation.
                    detail: The request failed validation.
                    error_code: VALIDATION_ERROR
                    retryable: false
                    request_id: req_abc123
        '401':
          description: Authentication failed — missing, invalid, or expired API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                AUTH_FAILED:
                  value:
                    error: Authentication failed.
                    detail: Authentication failed.
                    error_code: AUTH_FAILED
                    retryable: false
                    request_id: req_abc123
        '403':
          description: >-
            Access denied — the API key lacks access to this resource or the
            scope this call needs (`ACCESS_DENIED`,
            `INSUFFICIENT_API_KEY_SCOPE`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                ACCESS_DENIED:
                  value:
                    error: You do not have access to this resource.
                    detail: You do not have access to this resource.
                    error_code: ACCESS_DENIED
                    retryable: false
                    request_id: req_abc123
        '404':
          description: '`NOT_FOUND` — The resource does not exist.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                NOT_FOUND:
                  value:
                    error: The resource does not exist.
                    detail: The resource does not exist.
                    error_code: NOT_FOUND
                    retryable: false
                    request_id: req_abc123
        '409':
          description: |-
            `SPLIT_HAS_NO_PAGES` — The split holds no pages.
            `SPLIT_SOURCE_NOT_PDF` — The split's source document is not a PDF.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                SPLIT_HAS_NO_PAGES:
                  value:
                    error: The split holds no pages.
                    detail: The split holds no pages.
                    error_code: SPLIT_HAS_NO_PAGES
                    retryable: false
                    request_id: req_abc123
                SPLIT_SOURCE_NOT_PDF:
                  value:
                    error: The split's source document is not a PDF.
                    detail: The split's source document is not a PDF.
                    error_code: SPLIT_SOURCE_NOT_PDF
                    retryable: false
                    request_id: req_abc123
        '422':
          description: >-
            `INTERNAL_INCONSISTENCY` — The server found an internal
            inconsistency.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                INTERNAL_INCONSISTENCY:
                  value:
                    error: The server found an internal inconsistency.
                    detail: The server found an internal inconsistency.
                    error_code: INTERNAL_INCONSISTENCY
                    retryable: false
                    request_id: req_abc123
        '429':
          description: >-
            Rate limited — retry after the `Retry-After` header. Default
            windows: 60 requests/minute for extraction submission, 600
            requests/minute for general endpoints.
          headers:
            Retry-After:
              description: Seconds until the next request is allowed.
              schema:
                type: integer
            X-RateLimit-Limit:
              description: Requests allowed per window (60s).
              schema:
                type: integer
            X-RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            X-RateLimit-Reset:
              description: Seconds until the current window resets.
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                RATE_LIMITED:
                  value:
                    error: Rate limit exceeded — retry after backoff.
                    detail: Rate limit exceeded — retry after backoff.
                    error_code: RATE_LIMITED
                    retryable: true
                    request_id: req_abc123
        '500':
          description: >-
            An internal error stopped the request — `retryable=true`. Retry with
            backoff.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                INTERNAL_ERROR:
                  value:
                    error: An internal error stopped the request.
                    detail: An internal error stopped the request.
                    error_code: INTERNAL_ERROR
                    retryable: true
                    request_id: req_abc123
      security:
        - ApiKeyAuth: []
components:
  schemas:
    ErrorEnvelope:
      type: object
      title: ErrorEnvelope
      description: >-
        Uniform error response. `retryable=true` means the same request may
        succeed on retry (with backoff); `retryable=false` means the caller must
        change the request before retrying.
      required:
        - error
        - error_code
        - retryable
        - request_id
      properties:
        error:
          type: string
          description: Short human-readable summary.
        detail:
          description: >-
            Machine-readable detail, any JSON value. A string for most errors, a
            list of field errors for validation failures, and an object for a
            structured error such as `FILENAME_CONFLICT` (`detail.conflicts`).
        error_code:
          type: string
          description: Stable identifier for programmatic handling.
          examples:
            - VALIDATION_ERROR
            - AUTH_FAILED
            - NOT_FOUND
            - PRECONDITION_FAILED
            - RATE_LIMITED
            - INTERNAL_ERROR
            - GATEWAY_TIMEOUT
        retryable:
          type: boolean
          description: True when the caller should retry (with backoff for 429/412/5xx).
        request_id:
          type: string
          description: Correlates this response with server logs.
  securitySchemes:
    ApiKeyAuth:
      type: http
      description: >-
        API key issued from app.anyformat.ai/api-key. Send as `Authorization:
        Bearer <key>`.
      scheme: bearer

````