Pull specific data from documents into structured JSON
Extract pulls specific fields from documents as structured JSON. You define a schema describing the data you need, and Reducto returns values matching that schema, handling OCR, layout detection, and LLM-based field location under the hood.Extract builds on Parse, which processes the document first, then uses AI to locate and return the specified fields accurately, even across complex layouts.
Both endpoints process documents, but they answer different questions.Parse answers: “What’s in this document?” It returns all content as structured chunks with positions and types. Use Parse for RAG pipelines, document viewers, or when you need to feed full content to an LLM.Extract answers: “What is the value of X?” It returns only the specific fields you request. Extract runs Parse internally, then uses AI to pull out values matching your schema.The key insight is that Extract can only return what Parse sees. If a value doesn’t appear in the Parse output (perhaps due to OCR issues or a table format problem), no amount of schema tweaking will extract it.
When debugging extraction issues, always verify the data exists in the Parse result first.
The result is an array containing objects matching your schema. When you enable citations, the response format changes to wrap each value with its source location.
Response Format Details
Full breakdown of result structure, citations, and usage fields.
Using jobid:// skips the parsing step entirely, which is useful when you want to try different extraction schemas on the same document without re-parsing, or when combining data from multiple documents into a single extraction.
JSON schema defining target fields and types. Field names and descriptions directly influence extraction quality because the LLM uses them to locate values. A field called invoice_total with description "The total amount due, typically at the bottom of the invoice" performs better than a generic total field.
system_prompt
Document-level context. Describe what kind of document this is or highlight edge cases. Field-specific instructions belong in schema descriptions, not here.
For documents with repeating data (line items, transactions). Segments the document, extracts from each segment, and merges results. Required when you need complete arrays from long documents.
deep_extract
false
Agentic extraction mode that iteratively refines its output to achieve near-perfect accuracy. Best for complex documents where accuracy is critical. See Deep Extract.
citations.enabled
false
Return page number, bounding box, and source text for each extracted value. Useful for verification and debugging.
citations.numerical_confidence
true
When citations are enabled, include a 0-1 confidence score instead of just “high”/“low”.
include_images
false
Include page images in the extraction context. Can help with visually complex documents but increases cost.
optimize_for_latency
false
Prioritize speed at 2x credit cost. Jobs get higher priority in the processing queue.
Citations cannot be used with chunking. If you enable settings.citations.enabled, the parsing step automatically disables chunking. This is because citations require knowing exactly where each piece of content came from, which chunking obscures.
Since Extract runs Parse internally, you can configure how parsing works. These options are ignored if your input is a jobid:// reference.Common options:
result = client.extract.run( input=upload.file_id, instructions={"schema": schema}, parsing={ "enhance": { "agentic": [{"scope": "table"}] # LLM correction for tables }, "formatting": { "table_output_format": "html" # Better for complex tables }, "settings": { "page_range": {"start": 1, "end": 10}, # Process specific pages "document_password": "secret" # For encrypted PDFs } })
const result = await client.extract.run({ input: upload.file_id, instructions: { schema }, parsing: { enhance: { agentic: [{ scope: 'table' }] // LLM correction for tables }, formatting: { table_output_format: 'html' // Better for complex tables }, settings: { page_range: { start: 1, end: 10 }, // Process specific pages document_password: 'secret' // For encrypted PDFs } }});
Extract supports two modes of operation: schema-based extraction (the default) and schemaless extraction.Schema-based extraction is what most users need. You define a JSON schema specifying exactly which fields to extract and their types. The model returns data matching your schema structure. This gives you predictable, typed output that integrates cleanly with your application code.
Schemaless extraction lets the model decide what to extract based on a natural language prompt. Instead of providing a schema, you describe what you want in plain English. The model analyzes the document and returns whatever it deems relevant. This is useful for exploration or when you don’t know the document structure in advance.
# Schemaless: the model decides what to extractresult = client.extract.run( input=upload.file_id, instructions={ "system_prompt": "Extract all the key financial information from this invoice" })
// Schemaless: the model decides what to extractconst result = await client.extract.run({ input: upload.file_id, instructions: { system_prompt: 'Extract all the key financial information from this invoice' }});
curl -X POST https://platform.reducto.ai/extract \ -H "Authorization: Bearer $REDUCTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "input": "reducto://your-file-id", "instructions": { "system_prompt": "Extract all the key financial information from this invoice" } }'
Use schema-based extraction for production workflows where you need consistent output structure. Use schemaless extraction when exploring new document types or building prototypes.
Schema Best Practices
Detailed guidance on schema design, naming conventions, and descriptions.
Standard extraction works well for short documents, but for documents with many repeating items (hundreds of transactions, long invoice line items), you need array extraction.The problem: LLMs have context limits. When a document is too long, items toward the end may be truncated or missed. Array extraction solves this by segmenting the document, extracting from each segment, and merging the results.
Citations link each extracted value back to its source location in the document. Enable them when you need to verify extractions or show users where values came from.
result = client.extract.run( input=upload.file_id, instructions={"schema": schema}, settings={ "citations": { "enabled": True } })# With citations enabled, result is a dict with wrapped valuesfield = result.result["total_amount"]print(f"Value: {field.value}")print(f"Found on page {field.citations[0].bbox.page}")print(f"Confidence: {field.citations[0].confidence}")
const result = await client.extract.run({ input: upload.file_id, instructions: { schema }, settings: { citations: { enabled: true } }});// With citations enabled, result is an object with wrapped valuesconst field = result.result.total_amount;console.log(`Value: ${field.value}`);console.log(`Found on page ${field.citations[0].bbox.page}`);console.log(`Confidence: ${field.citations[0].confidence}`);
You can also add guidance in your system prompt: “Process all pages in the document, not just the beginning.”
Missing values from schema
When expected fields come back empty:
Check the Parse output first. Extract can only find what Parse sees. Run client.parse.run(input=upload.file_id) and verify the value appears in the content.
If it’s in Parse output, refine your schema. Add better field descriptions that match how the value appears in the document.
If it’s not in Parse output, adjust your parsing configuration. Try enabling agentic mode for tables, or changing the table output format to HTML.
For long arrays, also try enabling array_extract.
Hallucinated or computed values
Extract returns only what’s on the document. If you request calculated fields (like “annual cost” when only monthly appears), the model may fabricate values.Solution: Extract raw values and compute in your code:
Enable citations to verify source locations for any suspicious values.
Schema is too large
Very large schemas may exceed LLM token limits and fail with a 422 error. Solutions:
Flatten deeply nested structures
Remove unnecessary fields
Split into multiple extraction calls
As a rule of thumb, keep schemas under 50 fields. If you need more, consider breaking the extraction into logical groups.
Citations and chunking error
If you see “Citations and chunking cannot be enabled at the same time”, you have conflicting options.When citations are enabled, chunking is automatically disabled in the parsing step. If you’re explicitly setting chunking options in parsing.retrieval.chunking, either remove them or disable citations.