Extraction
Return document fields as schema-validated JSON.
Extraction is an additional step on top of parsing:
- OpenParser parses the source into an
openparser@1document. - The selected language model extracts fields from that parsed document.
- OpenParser validates the output against your JSON Schema.
When you send file or file_id, the extraction endpoint runs both parsing and extraction. When you send the parse_job_id of a succeeded parse job, it reuses that job's ParsedDocument and starts at step 2.
curl -X POST 'https://api.openparser.dev/extract' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H "Idempotency-Key: $(uuidgen 2>/dev/null || openssl rand -hex 16)" \
-F 'request={"ocr_model":"paddleocr-vl-1.6","llm_model":"openai/gpt-5.6-terra","schema":{"type":"object","properties":{"invoice_number":{"type":"string"},"total":{"type":"number"}},"required":["invoice_number","total"],"additionalProperties":false}};type=application/json' \
-F 'file=@./invoice.pdf'openparser extract sync ./invoice.pdf \
--ocr-model paddleocr-vl-1.6 \
--llm-model openai/gpt-5.6-terra \
--schema-json '{"type":"object","properties":{"invoice_number":{"type":"string"},"total":{"type":"number"}},"required":["invoice_number","total"],"additionalProperties":false}'const result = await client.extract.sync(
{
ocr_model: 'paddleocr-vl-1.6',
llm_model: 'openai/gpt-5.6-terra',
schema: {
type: 'object',
properties: {
invoice_number: { type: 'string' },
total: { type: 'number' },
},
required: ['invoice_number', 'total'],
additionalProperties: false,
},
},
file,
);from pathlib import Path
result = client.extract.sync(
{
"ocr_model": "paddleocr-vl-1.6",
"llm_model": "openai/gpt-5.6-terra",
"schema": {
"type": "object",
"properties": {
"invoice_number": {"type": "string"},
"total": {"type": "number"},
},
"required": ["invoice_number", "total"],
"additionalProperties": False,
},
},
file=Path("invoice.pdf"),
)The output field in a successful response matches the schema you sent.
Extracted values keep the document's original wording, spelling, casing, and punctuation. OpenParser does not rewrite dates, addresses, names, or phrasing into a canonical form unless the field's JSON Schema type or description asks for that format. An integer or number field is an explicit format: the source text 4 year(s) becomes 4. Apply your own formatting, calculations, or review as downstream lineage steps.
Choose a source
A single extraction accepts exactly one source:
filefor a direct uploadfile_idfor a file uploaded withPOST /filesparse_job_idfor the result of a succeeded parse job
Reusing a parse job avoids running OCR again and does not add another page charge. Language-model usage is still billed. Batch extraction accepts uploaded files and file_id, but not parse_job_id.
Sync vs async
| Endpoint | Behavior |
|---|---|
POST /extract | Wait for the terminal result. Returns 202 with a job if the wait window expires first. |
POST /extract/async | Return 202 as soon as the durable job is accepted. |
POST /extract/batch | Accept 1–100 child jobs and return a batch job. |
All three use the same extraction workflow. File-backed requests parse first; the single-document endpoints can skip that step with parse_job_id. The endpoint choice only changes how work is admitted and returned.
Use the synchronous endpoint when holding the connection open is convenient. Use the async endpoint when your application prefers to poll GET /jobs/{id}.
Choose a model
Call GET /models/llm for the current catalog. The default response contains suggested models; use mode=search and q to search the full list.
Any compatible model can perform ordinary extraction. Field grounding requires a certified model.
Control validation
- Set
repair_attemptsfrom0to2to allow another model attempt when the first result does not satisfy the schema. - Set
groundingtofieldto request source locations for extracted values. The selected model must support grounding.
OpenParser does not silently switch models or exceed the configured repair limit.
Reuse the configuration
Create a pipeline when several requests share the same OCR model, language model, schema, and options. Then send pipeline_id instead of the inline configuration.
Do not combine pipeline_id with inline model, schema, or extraction options.
Billing
Extraction is billed by input and output tokens at the customer rates for the selected language model. Current rates are published by GET /models/llm.
Each provider-accepted attempt is billable, including configured repair attempts. File-backed extraction also incurs the normal OCR page charge. Reusing a succeeded parse with parse_job_id does not add another page charge.
When usage is available, the terminal extraction result includes:
usage.input_tokensandusage.output_tokensfor totals across all attemptsusage.cost_usdfor the total customer language-model chargeattempts[].input_tokens,attempts[].output_tokens, andattempts[].cost_usdfor per-attempt detail
type ExtractionUsage = {
input_tokens?: number;
output_tokens?: number;
cost_usd?: number;
};
type ExtractionAttemptUsage = ExtractionUsage & {
index: number;
kind: 'primary' | 'repair';
llm_model: string;
status: 'succeeded' | 'failed' | 'indeterminate';
};These fields are returned by a successful synchronous POST /extract response and inside result when GET /jobs/{id} returns a succeeded extraction job.
The cost is the customer charge, not the provider's raw list price, and does not include the separate OCR page charge.
Results
A successful extraction includes:
output, validated against your schemaparsed_document- the model that ran
attemptsand aggregate tokenusage- field
grounding, when requested and available lineage, a portablelineage@1derivation DAG, whengroundingisfield
POST /extract/async always returns a job. The synchronous endpoint also returns a job when processing exceeds its wait window. Poll GET /jobs/{id} for the final result.
Grounded lineage
Set grounding to field to receive verified citations and a complete
derivation DAG. The lineage contains:
- artifact entities for the source and parsed documents, collection entities for cited regions, and a field entity for every output leaf
- OCR and extraction activities with the exact models that ran
- one derivation for a verbatim field, or an extraction plus transform derivation when the returned value rewrites the source text
- source text, page geometry, canonical element ids, and table-cell ids
- the closest recognition confidence supplied by the OCR provider
OpenParser retains word or symbol confidence when the OCR provider supplies it. Otherwise it uses confidence from the cited table cell, text span, element, or page. Each assertion keeps its scope, granularity, source scale, and calibration status. A summary across a cited source region describes OCR recognition in that evidence—not the probability that the extracted value is correct. OpenParser does not invent extraction confidence when the language model does not report a calibrated field probability.
Evidence locators point into the parsed_document returned beside the lineage.
Your application can render the source directly and append new value entities,
activities, and derivations for normalization, calculations, inference, and
human review. See lineage@1 for the protocol and
@openparser/lineage helpers.
Lineage always carries region-level aggregates; per-word text and confidence
stay in parsed_document, where region selectors address them without copying
them into the graph. If lineage would push the terminal result over its size
limit, extraction still succeeds with grounding and omits lineage.
Each grounded field may include reason and transform_claim. reason
explains why the quoted passage is the source for the value — what in the
document identifies it — and does not explain formatting. transform_claim
is the model's bounded, untrusted report of how the quote became the returned
value and is omitted when the
value is the quote as written. It never authorizes a validator. For format-only
JSON Schema dates, source_format may only prioritize a member of the trusted
built-in source catalog; it cannot add formats or authorize a score of 1.
target_format and other claim parameters cannot change trusted policy.
{
"mode": "field",
"fields": [
{
"path": "lease_start_date",
"quote": "20 day of May 2025",
"reason": "The commencement clause states the lease begins on the 20 day of May 2025.",
"transform_claim": {
"operation": "date_time_format",
"parameters": { "source_format": "d 'day of' MMMM yyyy", "target_format": "yyyy-MM-dd" },
"reason": "The schema asks for an ISO 8601 date, so the written date was reformatted to 2025-05-20.",
"confidence": "high"
}
}
]
}In lineage, a justification is an attribute of the entity its step produced
(openparser:justification). A rewritten field's read reason lives on the
intermediate verbatim-text entity; its transform reason lives on the field
entity. See extraction and transforms.
Human review API
Every succeeded extraction job has a versioned review resource:
GET /jobs/{id}/reviewreturns immutable machine output, corrected output, status, and audit eventsPATCH /jobs/{id}/reviewapplies confirmations and retractions addressed by JSON Pointer withexpected_version. A confirmation is the single reviewer act: this field should sayvalue, signed by the caller. When that value differs from extraction, the confirmation is also the correction. A retraction takes back the caller's own current tip on that path, while nothing else depends on itPOST /jobs/{id}/review/completeapproves or rejects the reviewPOST /jobs/{id}/review/reopenreturns a completed review topending; only the reviewer who signed the run off may reopen it
Confirmations never overwrite result.output. Concurrent stale writes return 409, and each confirmation records its actor, timestamp, previous value when the field moved, and confirmed value. Quorum rules are yours to define; the platform records signed confirmations rather than enforcing a policy. This lets OpenParser Studio provide a lightweight review UI while clients build their own workflow-specific interfaces from the same API.
For grounded extractions, the review resource also returns the machine
lineage@1 graph extended with append-only review.confirm activities, reviewer
agents, corrected value entities when a confirmation changes a field, who stands
behind the current values, and the final approval or rejection decision. The
original machine entities remain unchanged. See
OpenParser human review.