API v1 documentation
Documents
Upload, process, inspect, and download document thumbnails, previews, and extraction results.
Upload a document
POST /api/v1/documents accepts multipart form data and returns a document resource you can poll until processing is complete. Omit processing_mode for extraction, send analysis for the same lifecycle without AI and structured extraction, send validation to assess a PDF or XML e-invoice without general extraction, or send thumbnail when you only need a JPEG thumbnail. Omit processing_lane for standard priority; the delayed batch lane is available to eligible accounts. Review supported files and capabilities before sending a new format.
curl -sS -X POST "https://www.exdata.app/api/v1/documents" \
-H "Authorization: Bearer $EXDATA_API_TOKEN" \
-H "Idempotency-Key: invoice-upload-001" \
-F "file=@./invoice.pdf" \
-F "locale=en" \
-F "custom_types[]=invoice"
Upload fields
Send the file and any context your workflow already knows. Keep hints short and factual; they help classification without replacing extraction from the document itself.
| Field | Required | Type | Description |
|---|---|---|---|
file |
Yes | File | Supported document file, up to 500 MB. Lower format-specific processing limits apply. |
text |
No | String | Additional source text or business context to treat as document evidence, not extraction instructions, up to 256 KiB (262,144 UTF-8 bytes). Validation mode rejects this field because it evaluates only the uploaded PDF or XML. |
custom_types[] |
No | Array | Up to 50 optional type extensions, each up to 100 characters. exdata already supports standard types: invoice, credit-note, reminder, salary-statement, bank-statement, contract, balance-sheet, tax-assessment-note, timesheet, letter, and other. Add custom values only when your integration needs extra document categories. Validation mode does not use or persist these extensions. |
requester |
No | String | Your integration name, user reference, workflow ID, or request source, up to 255 characters. For de.energy.supply-invoice, exdata keeps this as upload metadata and it does not affect profile extraction. |
locale |
No | String | Supported locale such as en or de. |
processing_mode |
No | extraction, analysis, validation, or thumbnail |
Defaults to extraction. Live extraction uses the applicable profile rate per started 10-page band and keeps the calculated total when a usable result or retrievable extracted fields remain. analysis follows the same lifecycle without AI or structured extraction. validation accepts PDF or XML and returns only the structured-invoice assessment. Both use the generic page-band rate. Use thumbnail to generate only a JPEG thumbnail with zero credit usage. |
processing_lane |
No | standard or batch |
Defaults to standard. Batch is available to eligible accounts. It has lower priority and may take longer to start without changing processing results, status polling, or lifecycle webhooks. If batch is unavailable for the account, the upload returns 422 with code=validation_failed and a processing_lane validation error. |
pages |
No | String, max 255 | Analysis mode only, for PDF and single-page file types. Comma-separated first, last, all, or 1-based page numbers. Only the requested pages are processed, returned, and charged; the thumbnail still uses the first page. Other modes and Word, TIFF, email, or video uploads return 422. |
allow_ai_processing |
No | Boolean | Optional extraction flag. Multipart clients may send true, false, 1, or 0; letter case does not matter for the words. In extraction mode, false disables AI only; OCR, previews, non-AI structured extraction, thumbnail generation, and page-band credit rules still apply. Thumbnail, analysis, and validation mode take precedence over either value. |
extraction_profile |
No | String | Explicit extraction profile selection. Omit this field or send generic for the standard field map. Validation mode accepts only the generic profile. Send de.energy.supply-invoice to any active account for German electricity and natural-gas supply invoices; the profile accepts PDFs and requires extraction mode with AI enabled. New uploads use profile version 2.0.1 and schema version 2.0.0. The selected profile determines the version, processing settings, and applicable per-band rate recorded for the run. |
XML source files are limited to 5 MiB. Visual PDF processing is limited to 200 pages; each rendered page must stay within 18,000,000 pixels and 32 MiB, with 512 MiB of rendered data and 8 MiB of retained OCR text per document. EML and MSG containers are limited to 64 MiB, with up to 8 attachments, 20 MiB each, 32 MiB combined, and 100 pages per attached PDF. Decoded video frames must not exceed 33,177,600 pixels (8K UHD). See the capability matrix for extraction and preview behavior.
Processing modes
The mode determines which results are produced after upload. All modes use the same asynchronous document statuses, polling endpoint, and lifecycle webhooks.
| Mode | Work performed | Extraction credit | Completed results |
|---|---|---|---|
extraction |
Existing OCR, preview, structured extraction, thumbnail, and optional AI workflow. | The profile's recorded credit_cost per started 10-page band, kept when a usable result or retrievable extracted fields remain. Generic extraction has a rate of one; test-mode uploads have zero live credit usage. |
Thumbnail, previews, extraction fields, and extraction-run metadata when available. |
analysis |
Existing OCR, preview, and thumbnail workflow. AI and structured extraction do not run. Supports the pages selection. |
One live credit per started 10-page band, kept when a usable result or retrievable extracted fields remain. Sector profiles that require AI cannot be selected in analysis mode. | Thumbnail, previews, page count, extracted text, e-invoice detection, and extraction-run metadata. extractions completes as an empty array. |
validation |
PDF or XML e-invoice detection, XML validation, and required PDF/XML linkage only. No AI, general metadata extraction, persisted previews, thumbnail, or retained document text. For valid embedded invoice XML, bounded rendered OCR is required for visible PDF/XML linkage; a searchable or hidden native text layer does not establish a passing result. A completed assessment is published only after the final page-band total is covered. | One live credit per started 10-page band. Invalid or unsupported input still produces a completed assessment; a terminal technical failure returns credits when no usable result remains. | latest_extraction_run.quality.structured contains the assessment. extractions completes as an empty array. |
thumbnail |
JPEG thumbnail only. Videos use a representative decoded frame. No OCR, AI, structured extraction, or persisted preview generation runs. | Zero. A zero-credit account can use this mode. | Thumbnail URL, empty preview and extraction endpoint results, and latest_extraction_run: null. |
processing_mode=thumbnail, processing_mode=analysis, and processing_mode=validation always win over allow_ai_processing and return ai_processing: false. If processing_mode is omitted or set to extraction, allow_ai_processing keeps its existing AI-only meaning.
Credit usage
Live extraction-lifecycle runs apply the applicable profile rate per started 10-page band. A specialized profile can use a different credit_cost, expressed as credits per started 10-page band. Because the final page count can become available only after processing begins, latest_extraction_run.credits_charged can update as processing progresses. Generic extraction, analysis, and validation have a one-credit rate. Read latest_extraction_run.credits_charged for the current total attributed to the run.
| Point in the lifecycle | Credit behavior | API signal |
|---|---|---|
| Upload accepted | The run starts with the profile's per-band credit_cost for the first 1-10 pages before processing begins. |
201; a generic pending live run normally reports credit_cost: 1 and credits_charged: 1. |
| Page count analyzed | The usage total updates to credit_cost × started 10-page bands. For a rate of 3, 1-10 pages use 3 credits, 11-20 use 6, and 21-30 use 9. |
number_of_pages and credits_charged update while processing remains asynchronous. |
| Successful completion | The final usage total is recorded. | status: "completed" and the final total in credits_charged. |
| Terminal error with retrievable extracted fields | The usage total remains recorded because delivered fields remain available through the extractions endpoint. | status: "error" and the retained total in credits_charged. |
| Terminal or preprocessing error with neither a usable result nor retrievable extracted fields | The initial credit amount is returned, so net usage is zero. | status: "error" and credits_charged: 0. |
| Additional page band unavailable | Processing stops before extraction and the initial credit amount is returned, so net usage is zero. | status: "blocked", blocked_reason: "page_band_insufficient_credits", and credits_charged: 0. This can happen after a 201. |
| Test, thumbnail, or reprocessing after a completed result | Zero net live credit usage. Thumbnail mode has no extraction run. | Test and reprocessing after a completed result report credits_charged: 0; thumbnail mode reports latest_extraction_run: null. Reprocessing after a failure whose credits were returned starts with the applicable rate and is charged only if it first leaves a usable result or retrievable extracted fields. |
Processing lanes
The lane controls processing priority, not extraction semantics. Choose a lane independently from processing_mode; extraction, analysis, validation, and thumbnail work support standard and batch processing. Batch is available to eligible accounts and is typically used for archive backfills. If batch is unavailable for the account, the upload returns 422 with code=validation_failed and a processing_lane validation error.
| Lane | Processing behavior | Use when | Result contract |
|---|---|---|---|
standard |
Normal processing priority. | Turnaround time matters or a user is waiting for the result. | Normal document statuses, polling responses, and lifecycle webhooks. |
batch |
The lane provides lower-priority processing with potentially longer waits. | Archive backfills, scheduled imports, and other delay-tolerant workloads. | The same statuses, fields, results, and lifecycle webhooks as standard. |
Extraction profiles
A profile adds a versioned document schema, validation policy, review rules, evidence contract, and optional export projections while preserving the regular document and extraction endpoints. Every active account can explicitly select a registered profile by sending its key in extraction_profile. The selected profile records the profile, schema, processing settings, and applicable per-band rate for each extraction run. These values are returned as run metadata rather than upload fields.
Omitting extraction_profile always selects generic. New German energy uploads use profile version 2.0.1 with schema version 2.0.0. Profile setting changes apply to new uploads; reprocessing an existing document preserves the version, processing settings, and credit rate recorded for that document.
| Value | Behavior |
|---|---|
Omitted or generic | Returns the generic extraction field map and uses the standard one-credit-per-band rate. |
de.energy.supply-invoice | Current specialized profile, available to every active account through explicit selection. It returns packet metadata and one source-ordered item per independently issued invoice. Each invoice contains identity, supply-point and operator data, tariffs, consumption, meter registers and readings, gas conversion, charge lines, taxes, settlement balances, due dates, and payment details. A single invoice still uses invoices[0]; a source-verified non-invoice uses invoices=[]. Accepted full-invoice profile versions 2.0.0 and 2.0.1 also expose canonical JSON and invoice-line CSV exports. It requires a PDF processed in extraction mode with AI enabled. Its current rate is 3 credits per started band: 1–10 pages use 3 credits and 11–20 use 6. |
Profile results are returned by GET /api/v1/documents/{document}/extractions under the sector_extraction key; there is no separate profile-result endpoint. The response envelope is shared across profiles, while machine_payload, effective_payload, validation details, review behavior, and projections come from the selected profile. See German energy invoices for the currently available profile's canonical data model and review workflow.
Document object
Document responses include the selected processing mode, lane, extraction profile, status, processing details, and file metadata. Extraction, analysis, and validation documents can include extraction-run metadata; thumbnail-only documents always return latest_extraction_run: null. When a specialized profile result exists, the sector_extraction_summary key provides its compact review and handoff state, a link to the extractions endpoint, and available export descriptors.
{
"data": {
"id": 123,
"mode": "live",
"processing_mode": "extraction",
"processing_lane": "batch",
"pages": null,
"status": "pending",
"processing_stage": "queued",
"processing_error": null,
"blocked_reason": null,
"filename": "invoice.pdf",
"file_format": "pdf",
"file_size": 240123,
"locale": "en",
"custom_types": ["invoice"],
"ai_processing": true,
"extraction_profile": "generic",
"latest_extraction_run": {
"id": 456,
"mode": "live",
"processing_lane": "batch",
"source": "api",
"status": "pending",
"blocked_reason": null,
"credits_charged": 1,
"extraction_schema_version": "2026-08-28.1",
"extractor_version": "document:2026-08-28.1",
"ai_prompt_version": "document-ai:2026-07-28.1",
"normalization_version": "base:2026-08-28.1",
"extraction_profile": "generic",
"profile_version": "1.0.0",
"ai_model": "gpt-5.4-mini-2026-03-17",
"ai_reasoning_effort": "low",
"strategies_used": null,
"provenance_summary": null,
"billing_mode": "credits",
"credit_cost": 1,
"quality": null
},
"created_at": "2026-05-10T01:00:00.000000Z"
}
}
Endpoint reference
The document endpoints cover upload, status polling, generated previews, deletion, and reading extraction fields after processing completes. See the endpoint reference for parameters, response behavior, and copyable examples for every endpoint.
| Method | Path | Purpose |
|---|---|---|
| GET | /api/v1/documents |
List account documents with pagination and optional profile review and handoff filters. |
| POST | /api/v1/documents |
Upload a document. |
| GET | /api/v1/documents/{document} |
Fetch current document status and metadata. |
| DELETE | /api/v1/documents/{document} |
Delete a document. |
| GET | /api/v1/documents/{document}/thumbnail |
Download a generated thumbnail. |
| GET | /api/v1/documents/{document}/previews |
List generated preview files. |
| GET | /api/v1/previews/{preview} |
Download a preview file. |
| GET | /api/v1/documents/{document}/extractions |
Read generic fields and, when selected, the complete specialized profile result with optional evidence-page descriptors. |
| GET | /api/v1/documents/{document}/extraction-runs/{extractionRun}/pages/{physicalPage}/preview |
Download a protected cited page artifact bound to the exact extraction run. |
| GET | /api/v1/documents/{document}/exports/{projection} |
Download a profile-registered single-document projection when it is available for the selected profile result. |
| GET | /api/v1/documents/exports/{projection}?document_ids[]=123 |
Download a batch projection for 1–100 documents from the same account. Ineligible batches return an error instead of partial data. |
| POST | /api/v1/documents/{document}/extractions/reviews |
Record an idempotent review decision with conflict detection. |