Batching
Parse or extract up to 100 documents in one request.
Batch endpoints group independent parse or extraction jobs behind one parent job:
| Operation | Endpoint |
|---|---|
| Parse | POST /parse/batch |
| Extract | POST /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_indexpoints to a file in the ordered multipartfilesfields.file_idreferences a reusable file uploaded withPOST /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.pdfconst 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 statuschildren.items, with each child's status and any terminal result or errorchildren.next_cursorwhen 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_idsources 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.