Batching

Parse or extract up to 100 documents in one request.

Batch endpoints group independent parse or extraction jobs behind one parent job:

OperationEndpoint
ParsePOST /parse/batch
ExtractPOST /extract/batch

Both endpoints accept between 1 and 100 items and return 202 Accepted. Each item becomes a durable child job with its own status, result, error, and billing.

Map files to items

Each item needs a caller-defined client_item_id and exactly one source:

  • file_index points to a file in the ordered multipart files fields.
  • file_id references a reusable file uploaded with POST /files.

Every uploaded file must be referenced exactly once. file_index is zero-based.

curl -X POST 'https://api.openparser.dev/parse/batch' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H "Idempotency-Key: $(uuidgen 2>/dev/null || openssl rand -hex 16)" \
  -F 'request={"items":[{"client_item_id":"invoice-001","file_index":0,"ocr_model":"paddleocr-vl-1.6"},{"client_item_id":"invoice-002","file_index":1,"ocr_model":"paddleocr-vl-1.6"}],"output_format":"openparser@1"};type=application/json' \
  -F 'files=@./invoice-001.pdf' \
  -F 'files=@./invoice-002.pdf'
# parse-batch.json contains the request object (items + output_format)
openparser parse batch --request parse-batch.json ./invoice-001.pdf ./invoice-002.pdf
const accepted = await client.parse.batch({
  body: {
    request: {
      items: [
        { client_item_id: 'invoice-001', file_index: 0, ocr_model: 'paddleocr-vl-1.6' },
        { client_item_id: 'invoice-002', file_index: 1, ocr_model: 'paddleocr-vl-1.6' },
      ],
      output_format: 'openparser@1',
    },
    files: [file1, file2],
  },
});
from pathlib import Path

accepted = client.parse.batch(
    {
        "items": [
            {
                "client_item_id": "invoice-001",
                "file_index": 0,
                "ocr_model": "paddleocr-vl-1.6",
            },
            {
                "client_item_id": "invoice-002",
                "file_index": 1,
                "ocr_model": "paddleocr-vl-1.6",
            },
        ],
        "output_format": "openparser@1",
    },
    files=[Path("invoice-001.pdf"), Path("invoice-002.pdf")],
)

client_item_id is returned with the child summary, so you can match results to your own records without relying on array position.

Parse and extract use the same model

A parse item contains its source, ocr_model, and optional OCR options.

An extraction item contains the same source plus either:

  • pipeline_id, or
  • inline ocr_model, llm_model, schema, and extraction options

The pipeline or inline configuration belongs to each item. There is no batch-level extraction configuration in API v1. parse_job_id reuse is available only for single-document extraction and cannot be used in a batch.

Poll the parent job

The admission response contains the parent job ID, child_count, and a Location header. Poll that location with GET /jobs/{id}.

The parent response includes:

  • summary, with counts by child status
  • children.items, with each child's status and any terminal result or error
  • children.next_cursor when more child summaries are available

Pass cursor and limit to paginate children. Partial failures are preserved; successful children are not discarded because another child failed.

A mixed batch can finish with parent status succeeded when at least one child succeeded. Always inspect the child summaries before treating the entire batch as successful.

Scheduling priority

Batch children run at secondary priority behind single synchronous and asynchronous jobs. This keeps interactive requests responsive when the service is busy. Waiting batch jobs are protected from starvation, but a batch can take longer to start than the same documents submitted as individual jobs.

Use batching for bulk work where throughput matters more than immediate start time.

Limits and billing

  • A batch contains at most 100 children.
  • Each direct upload can be up to 50 MiB.
  • Total input across uploaded files and resolved file_id sources can be up to 100 MiB.
  • The 100-million rendered-pixel limit still applies to each page.

Billing is calculated per child. Parse children use normal per-page billing. Extraction children include both their OCR page charge and language-model token charge. A succeeded extraction child's result.usage and result.attempts contain its aggregate and per-attempt language-model costs when usage is available.

Retry safely

The batch request requires one Idempotency-Key. Reuse it only when retrying the identical batch, including the same item configuration and files. Reusing it with different input returns 409 Conflict.

On this page