API documentation
Endpoint reference
Every document API endpoint with parameters, responses, fields, and copyable examples.
OpenAPI coverage
The operation list below is read from the published OpenAPI contract. Use it as a compact index when comparing generated clients, request methods, operation IDs, and documented response codes.
| Method | Path | Operation | Responses |
|---|---|---|---|
| GET | /api/v1/ping |
Check API authentication ping |
200
429
|
| GET | /api/v1/documents |
List documents listDocuments |
200
429
|
| POST | /api/v1/documents |
Upload a document uploadDocument |
201
422
409
429
402
|
| POST | /api/v1/x402/extractions |
Upload a document with x402 payment createAnonymousX402Extraction |
200
201
400
402
409
422
429
503
|
| GET | /api/v1/x402/extractions/{document} |
Retrieve an anonymous x402 extraction getAnonymousX402Extraction |
200
403
404
429
|
| GET | /api/v1/documents/{document} |
Retrieve a document getDocument |
200
403
404
429
|
| DELETE | /api/v1/documents/{document} |
Delete a document deleteDocument |
204
403
404
429
|
| GET | /api/v1/documents/{document}/thumbnail |
Download document thumbnail getDocumentThumbnail |
200
403
404
429
|
| GET | /api/v1/documents/{document}/previews |
List document previews listDocumentPreviews |
200
403
404
429
|
| GET | /api/v1/documents/{document}/extractions |
List document extractions listDocumentExtractions |
200
403
404
429
|
| GET | /api/v1/previews/{preview} |
Download a preview file getPreview |
200
403
404
429
|
Common headers
Each request is scoped to the account behind the API token. Upload retries should include an idempotency key so a network retry does not create another document.
| Header | Required | Value | Description |
|---|---|---|---|
Authorization |
Yes | Bearer <token> |
Account-scoped API token created in the exdata app. The token must have the ability required by the endpoint. |
Idempotency-Key |
Uploads only | String, max 255 characters | Unique key for one logical upload. Reusing the same key with the same file, fields, and processing mode returns the stored response. A different processing mode is a different payload and returns 409. |
X-Request-ID |
No | String, max 128 characters | Optional caller request ID. exdata echoes this value, or a generated request ID, in error responses. |
/api/v1/ping
Ping
Use this endpoint for a lightweight token check during integration setup, deploy checks, or uptime probes that should not upload files.
| Parameter | Location | Required | Description |
|---|---|---|---|
| None | - | No | Only the bearer token is required. |
| Status | Response | Description |
|---|---|---|
200 | JSON object | Authentication succeeded. |
401 | Error envelope | Bearer token is missing, invalid, or revoked. |
429 | Error envelope | Read rate limit exceeded. |
curl -sS "https://www.exdata.app/api/v1/ping" \
-H "Authorization: Bearer $EXDATA_API_TOKEN"
{
"status": true
}
/api/v1/documents
List documents
Returns paginated documents for the token's account. Use this endpoint for status dashboards, reconciliation, support tooling, and scheduled backfills.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
sort | Query | No | created_at or -created_at | Sort by creation time. Use -created_at for newest first. |
per_page | Query | No | Integer, 1-100 | Number of documents per page. Defaults to 100. |
| Status | Response | Description |
|---|---|---|
200 | Paginated document list | data contains document objects. links and meta contain Laravel pagination data. |
403 | Error envelope | The token does not have documents:read. |
422 | Validation error | A query parameter is not valid. |
429 | Error envelope | Read rate limit exceeded. |
curl -sS "https://www.exdata.app/api/v1/documents?sort=-created_at&per_page=25" \
-H "Authorization: Bearer $EXDATA_API_TOKEN"
{
"data": [
{
"id": 123,
"mode": "live",
"processing_mode": "extraction",
"status": "completed",
"processing_stage": "completed",
"processing_error": null,
"blocked_reason": null,
"scanner_status": "clean",
"scanner_provider": "local_noop",
"scanner_message": null,
"filename": "invoice-re-2026-1048.pdf",
"file_format": "pdf",
"file_size": 240123,
"locale": "en",
"custom_types": ["invoice"],
"requester": "accounts-payable",
"origin": "api",
"ai_processing": true,
"is_e_invoice": false,
"thumbnail": "https://www.exdata.app/api/v1/documents/123/thumbnail",
"previews": [
{
"id": 987,
"filename": "page-1.png",
"file_format": "png",
"file_size": 94812,
"preview": "https://www.exdata.app/api/v1/previews/987"
}
],
"latest_extraction_run": {
"id": 456,
"mode": "live",
"source": "api",
"status": "completed",
"blocked_reason": null,
"error_code": null,
"error_message": null,
"extraction_schema_version": "2026-07-28.1",
"extractor_version": "document:2026-07-28.1",
"ai_prompt_version": "document-ai:2026-07-28.1",
"normalization_version": "base:2026-07-28.1",
"quality": {
"status": "normal",
"degraded": false,
"reasons": [],
"ai": {
"status": "completed",
"model": "gpt-5.4-mini-2026-03-17",
"reasoning_effort": "low",
"service_tier": "default",
"max_output_tokens": 8192,
"input_mode": "attachment",
"text_purpose": null,
"detail": "high",
"preflight_unavailable": false,
"low_detail_document_text_cross_checked": null,
"document_text_truncated": false,
"email_text_truncated": false,
"deterministic_supplementation": false,
"no_usable_text": false,
"conflict_fields": [],
"rejected_fields": []
},
"pdf": {
"page_count": 1,
"page_count_known": true,
"native_text_available": true,
"native_text_truncated": false,
"ocr_attempted_pages": 0,
"ocr_successful_pages": 0,
"ocr_page_limit_reached": false,
"ocr_page_limit": 200,
"pages_beyond_ocr_limit": 0,
"failed_pages": [],
"skipped_pages": [],
"empty_pages": [],
"blank_pages": [],
"conflict_pages": [],
"unreliable_pages": [],
"limited_pages": []
},
"email": null,
"structured": null
},
"started_at": "2026-05-10T01:00:04.000000Z",
"completed_at": "2026-05-10T01:00:18.000000Z",
"created_at": "2026-05-10T01:00:03.000000Z"
},
"created_at": "2026-05-10T01:00:00.000000Z",
"updated_at": "2026-05-10T01:00:18.000000Z"
}
],
"links": {
"first": "https://www.exdata.app/api/v1/documents?page=1",
"last": "https://www.exdata.app/api/v1/documents?page=4",
"prev": null,
"next": "https://www.exdata.app/api/v1/documents?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 4,
"per_page": 25,
"to": 25,
"total": 82
}
}
/api/v1/documents
Upload document
Upload a file with multipart form data. The response is a document resource you can poll until processing is complete. The default extraction mode preserves the existing extraction workflow; thumbnail mode only creates a JPEG thumbnail.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
file | Form data | Yes | File, max 500 MB; XML max 5 MiB | Document file. Supported file types are listed under Files and versioning. |
text | Form data | No | String or null, max 256 KiB | Additional source text or business context, such as an accompanying email or customer note. It is treated as document evidence, not extraction instructions, and may contain up to 262,144 UTF-8 bytes. |
custom_types[] | Form data | No | Array of strings | Up to 50 optional type extensions, each up to 100 characters. Standard types are 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. |
requester | Form data | No | String or null | Integration name, user reference, workflow ID, or source system, up to 255 characters. |
locale | Form data | No | String or null | Supported locale such as en or de. |
processing_mode | Form data | No | extraction or thumbnail | Defaults to extraction. Thumbnail mode skips OCR, AI, structured extraction, persisted previews, extraction runs, and extraction credits. |
allow_ai_processing | Form data | No | Boolean | Multipart clients may send true, false, 1, or 0; letter case does not matter for the words. This optional extraction-mode flag disables AI only when false and does not disable OCR, previews, non-AI structured extraction, or the extraction credit. Thumbnail mode takes precedence over either value. |
Omitting processing_mode is the same processing choice as extraction. With extraction mode, allow_ai_processing controls AI only. With thumbnail mode, exdata reports ai_processing: false regardless of that field.
| Status | Response | Description |
|---|---|---|
201 | Document resource | The document was accepted. Extraction mode includes a pending extraction run when queued. Thumbnail mode queues without an extraction run or credit check. |
402 | Insufficient credits error | Extraction mode only. The document was created, then blocked because the account does not have enough credits. Thumbnail mode is not blocked by the extraction credit balance. |
403 | Error envelope | The token does not have documents:write, or the account is suspended. |
409 | Error envelope | The idempotency key is still processing or was reused with a different upload payload, including a different processing mode. |
422 | Validation error | The file or form field failed validation. |
429 | Error envelope | Upload rate limit exceeded, including sandbox daily upload limits for test-mode tokens. |
curl -sS -X POST "https://www.exdata.app/api/v1/documents" \
-H "Authorization: Bearer $EXDATA_API_TOKEN" \
-H "Idempotency-Key: invoice-2026-1048" \
-F "file=@./invoice-re-2026-1048.pdf" \
-F "locale=en" \
-F "custom_types[]=invoice" \
-F "requester=accounts-payable"
import fs from "node:fs";
const form = new FormData();
form.set("file", new Blob([fs.readFileSync("./invoice-re-2026-1048.pdf")]), "invoice-re-2026-1048.pdf");
form.set("locale", "en");
form.append("custom_types[]", "invoice");
form.set("requester", "accounts-payable");
const response = await fetch("https://www.exdata.app/api/v1/documents", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.EXDATA_API_TOKEN}`,
"Idempotency-Key": "invoice-2026-1048",
},
body: form,
});
console.log(await response.json());
import os
import requests
with open("./invoice-re-2026-1048.pdf", "rb") as file:
response = requests.post(
"https://www.exdata.app/api/v1/documents",
headers={
"Authorization": f"Bearer {os.environ['EXDATA_API_TOKEN']}",
"Idempotency-Key": "invoice-2026-1048",
},
files={"file": ("invoice-re-2026-1048.pdf", file, "application/pdf")},
data={
"locale": "en",
"custom_types[]": "invoice",
"requester": "accounts-payable",
},
timeout=60,
)
print(response.json())
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://www.exdata.app/api/v1']);
$response = $client->post('/documents', [
'headers' => [
'Authorization' => 'Bearer '.getenv('EXDATA_API_TOKEN'),
'Idempotency-Key' => 'invoice-2026-1048',
],
'multipart' => [
['name' => 'file', 'contents' => fopen('./invoice-re-2026-1048.pdf', 'r'), 'filename' => 'invoice-re-2026-1048.pdf'],
['name' => 'locale', 'contents' => 'en'],
['name' => 'custom_types[]', 'contents' => 'invoice'],
['name' => 'requester', 'contents' => 'accounts-payable'],
],
]);
print_r(json_decode((string) $response->getBody(), true));
curl -sS -X POST "https://www.exdata.app/api/v1/documents" \
-H "Authorization: Bearer $EXDATA_API_TOKEN" \
-H "Idempotency-Key: video-thumbnail-2026-1048" \
-F "file=@./inspection-video.mp4" \
-F "processing_mode=thumbnail"
{
"data": {
"id": 123,
"mode": "live",
"processing_mode": "extraction",
"status": "pending",
"processing_stage": "queued",
"processing_error": null,
"blocked_reason": null,
"filename": "invoice-re-2026-1048.pdf",
"file_format": "pdf",
"file_size": 240123,
"additional_text": null,
"additional_text_plain": null,
"custom_types": ["invoice"],
"requester": "accounts-payable",
"locale": "en",
"number_of_pages": null,
"origin": "api",
"ai_processing": true,
"is_e_invoice": false,
"thumbnail": null,
"previews": null,
"extractions": null,
"latest_extraction_run": {
"id": 456,
"mode": "live",
"source": "api",
"status": "pending",
"blocked_reason": null,
"error_code": null,
"error_message": null,
"extraction_schema_version": "2026-07-28.1",
"extractor_version": "document:2026-07-28.1",
"ai_prompt_version": "document-ai:2026-07-28.1",
"normalization_version": "base:2026-07-28.1",
"quality": null,
"started_at": null,
"completed_at": null,
"created_at": "2026-05-10T01:00:03.000000Z"
},
"created_at": "2026-05-10T01:00:00.000000Z",
"updated_at": "2026-05-10T01:00:03.000000Z"
}
}
{
"data": {
"id": 124,
"mode": "live",
"processing_mode": "thumbnail",
"status": "pending",
"processing_stage": "queued",
"processing_error": null,
"filename": "inspection-video.mp4",
"file_format": "mp4",
"origin": "api",
"ai_processing": false,
"thumbnail": null,
"previews": null,
"extractions": null,
"latest_extraction_run": null,
"created_at": "2026-05-10T01:00:00.000000Z",
"updated_at": "2026-05-10T01:00:00.000000Z"
}
}
/api/v1/documents/{document}
Retrieve document
Fetch the current document status, processing mode, file metadata, and completed results. A completed thumbnail-only document contains the thumbnail URL, reports ai_processing: false, and has no persisted previews, extraction fields, or extraction run.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
document | Path | Yes | Integer | Document ID returned by create or list. |
| Status | Response | Description |
|---|---|---|
200 | Document resource | Current document state. Completed documents can include previews and extraction fields. |
403 | Error envelope | The token cannot access this document or lacks documents:read. |
404 | Error envelope | No document exists for this account and ID. |
curl -sS "https://www.exdata.app/api/v1/documents/123" \
-H "Authorization: Bearer $EXDATA_API_TOKEN"
{
"data": {
"id": 123,
"mode": "live",
"processing_mode": "extraction",
"status": "completed",
"processing_stage": "completed",
"processing_error": null,
"blocked_reason": null,
"filename": "invoice-re-2026-1048.pdf",
"file_format": "pdf",
"file_size": 240123,
"number_of_pages": 1,
"origin": "api",
"ai_processing": true,
"is_e_invoice": false,
"thumbnail": "https://www.exdata.app/api/v1/documents/123/thumbnail",
"previews": [
{
"id": 987,
"filename": "page-1.png",
"file_format": "png",
"file_size": 94812,
"preview": "https://www.exdata.app/api/v1/previews/987"
}
],
"extractions": {
"document_number": {
"value": "RE-2026-1048",
"candidates": ["RE-2026-1048"]
},
"gross_amount": {
"value": "1079.50",
"candidates": ["Total due EUR 1,079.50"]
}
},
"latest_extraction_run": {
"id": 456,
"mode": "live",
"source": "api",
"status": "completed",
"blocked_reason": null,
"error_code": null,
"error_message": null,
"extraction_schema_version": "2026-07-28.1",
"extractor_version": "document:2026-07-28.1",
"ai_prompt_version": "document-ai:2026-07-28.1",
"normalization_version": "base:2026-07-28.1",
"quality": {
"status": "normal",
"degraded": false,
"reasons": [],
"ai": {
"status": "completed",
"model": "gpt-5.4-mini-2026-03-17",
"reasoning_effort": "low",
"service_tier": "default",
"max_output_tokens": 8192,
"input_mode": "attachment",
"text_purpose": null,
"detail": "high",
"preflight_unavailable": false,
"low_detail_document_text_cross_checked": null,
"document_text_truncated": false,
"email_text_truncated": false,
"deterministic_supplementation": false,
"no_usable_text": false,
"conflict_fields": [],
"rejected_fields": []
},
"pdf": {
"page_count": 1,
"page_count_known": true,
"native_text_available": true,
"native_text_truncated": false,
"ocr_attempted_pages": 0,
"ocr_successful_pages": 0,
"ocr_page_limit_reached": false,
"ocr_page_limit": 200,
"pages_beyond_ocr_limit": 0,
"failed_pages": [],
"skipped_pages": [],
"empty_pages": [],
"blank_pages": [],
"conflict_pages": [],
"unreliable_pages": [],
"limited_pages": []
},
"email": null,
"structured": null
},
"started_at": "2026-05-10T01:00:04.000000Z",
"completed_at": "2026-05-10T01:00:18.000000Z",
"created_at": "2026-05-10T01:00:03.000000Z"
},
"created_at": "2026-05-10T01:00:00.000000Z",
"updated_at": "2026-05-10T01:00:18.000000Z"
}
}
{
"data": {
"id": 124,
"mode": "live",
"processing_mode": "thumbnail",
"status": "completed",
"processing_stage": "completed",
"processing_error": null,
"filename": "inspection-video.mp4",
"file_format": "mp4",
"origin": "api",
"ai_processing": false,
"thumbnail": "https://www.exdata.app/api/v1/documents/124/thumbnail",
"previews": [],
"extractions": [],
"latest_extraction_run": null,
"created_at": "2026-05-10T01:00:00.000000Z",
"updated_at": "2026-05-10T01:00:08.000000Z"
}
}
/api/v1/documents/{document}
Delete document
Deletes the document resource for the account. Use this when your retention policy or customer request requires removal.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
document | Path | Yes | Integer | Document ID to delete. |
| Status | Response | Description |
|---|---|---|
204 No Content | No body | Document deleted. |
403 | Error envelope | The token cannot delete this document or lacks documents:write. |
404 | Error envelope | No document exists for this account and ID. |
curl -sS -X DELETE "https://www.exdata.app/api/v1/documents/123" \
-H "Authorization: Bearer $EXDATA_API_TOKEN" \
-i
/api/v1/documents/{document}/thumbnail
Thumbnail
Downloads the generated JPEG thumbnail for a document when one is available. For a video upload, including a thumbnail-only upload, the thumbnail is a representative frame extracted from the video and returned through this same endpoint.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
document | Path | Yes | Integer | Document ID. |
| Status | Response | Description |
|---|---|---|
200 | JPEG binary (image/jpeg) | Generated document thumbnail or, for a video, its representative frame. |
403 | Error envelope | The token cannot access this document or lacks documents:read. |
404 | Error envelope | No document or thumbnail exists for this account and ID. |
curl -L "https://www.exdata.app/api/v1/documents/123/thumbnail" \
-H "Authorization: Bearer $EXDATA_API_TOKEN" \
-o document-123-thumbnail.jpg
/api/v1/documents/{document}/previews
List previews
Returns preview metadata for generated page or file previews. Use the returned preview ID with the preview download endpoint. Thumbnail mode never creates persisted previews, so a completed thumbnail-only document returns {"data":[]}.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
document | Path | Yes | Integer | Document ID. |
| Status | Response | Description |
|---|---|---|
200 | Preview list | data contains preview objects for this document, or an empty array for thumbnail mode. |
403 | Error envelope | The token cannot access this document or lacks documents:read. |
404 | Error envelope | No document exists for this account and ID. |
curl -sS "https://www.exdata.app/api/v1/documents/123/previews" \
-H "Authorization: Bearer $EXDATA_API_TOKEN"
{
"data": [
{
"id": 987,
"filename": "page-1.png",
"file_format": "png",
"file_size": 94812,
"preview": "https://www.exdata.app/api/v1/previews/987"
},
{
"id": 988,
"filename": "page-2.png",
"file_format": "png",
"file_size": 88204,
"preview": "https://www.exdata.app/api/v1/previews/988"
}
]
}
For a completed thumbnail-only document, this endpoint returns {"data":[]}. Download the JPEG from /documents/{document}/thumbnail instead.
/api/v1/previews/{preview}
Download preview
Downloads the binary preview file. Preview IDs are returned by the document previews endpoint and are account-scoped.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
preview | Path | Yes | Integer | Preview ID returned by /documents/{document}/previews. |
| Status | Response | Description |
|---|---|---|
200 | Binary stream | Preview file. The content type depends on the generated preview. |
403 | Error envelope | The token cannot access this preview or lacks documents:read. |
404 | Error envelope | No preview exists for this account and ID. |
curl -L "https://www.exdata.app/api/v1/previews/987" \
-H "Authorization: Bearer $EXDATA_API_TOKEN" \
-o document-123-page-1.png
/api/v1/documents/{document}/extractions
Read extractions
Returns extracted fields keyed by field name. Call this for completed extraction-mode documents or after receiving a document.completed webhook. Thumbnail mode never runs structured extraction, so a completed thumbnail-only document returns {"data":[]}.
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
document | Path | Yes | Integer | Completed document ID. |
| Status | Response | Description |
|---|---|---|
200 | Extraction object or empty array | data is an object keyed by normalized field name, or an empty array for thumbnail mode. |
403 | Error envelope | The token cannot access this document or lacks documents:read. |
404 | Error envelope | No document exists for this account and ID. |
curl -sS "https://www.exdata.app/api/v1/documents/123/extractions" \
-H "Authorization: Bearer $EXDATA_API_TOKEN"
const response = await fetch("https://www.exdata.app/api/v1/documents/123/extractions", {
headers: { Authorization: `Bearer ${process.env.EXDATA_API_TOKEN}` },
});
const extractions = await response.json();
console.log(extractions.data);
import os
import requests
response = requests.get(
"https://www.exdata.app/api/v1/documents/123/extractions",
headers={"Authorization": f"Bearer {os.environ['EXDATA_API_TOKEN']}"},
timeout=30,
)
print(response.json()["data"])
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://www.exdata.app/api/v1']);
$response = $client->get('/documents/123/extractions', [
'headers' => ['Authorization' => 'Bearer '.getenv('EXDATA_API_TOKEN')],
]);
print_r(json_decode((string) $response->getBody(), true)['data']);
{
"data": {
"type": {
"value": "invoice",
"candidates": ["Invoice"]
},
"document_number": {
"value": "RE-2026-1048",
"candidates": ["RE-2026-1048"]
},
"issue_date": {
"value": "2026-05-10",
"candidates": ["10 May 2026"]
},
"payment_due_date": {
"value": "2026-06-09",
"candidates": ["Due 09/06/2026"]
},
"sender_name": {
"value": "Meyer Supply GmbH",
"candidates": ["Meyer Supply GmbH"]
},
"recipient_name": {
"value": "Northwind Operations Ltd.",
"candidates": ["Northwind Operations Ltd."]
},
"currency": {
"value": "EUR",
"candidates": ["EUR"]
},
"net_amount": {
"value": "1079.50",
"candidates": ["Net amount EUR 1,079.50"]
},
"gross_amount": {
"value": "1079.50",
"candidates": ["Amount due EUR 1,079.50"]
},
"tax_breakdowns": {
"value": [
{
"taxable_amount": "1079.50",
"tax_amount": "0.00",
"tax_rate": "0.00",
"taxability": "taxable",
"tax_collection_mechanism": "reverse_charge",
"tax_exemption_reason": "Intra-EU B2B reverse charge"
}
],
"candidates": ["Reverse charge applies under Article 196 VAT Directive"]
},
"payment_reference": {
"value": "RE-2026-1048",
"candidates": ["Payment reference RE-2026-1048"]
}
}
}
Response objects
The tables below define the fields used by endpoint responses. The extraction field reference lists every normalized extraction key separately.
Document object
| Field | Type | When present | Description |
|---|---|---|---|
id | Integer | Always | Document ID. |
mode | live or test | Always | Whether the document was created by a live or test-mode token. |
processing_mode | extraction or thumbnail | Always | Work selected at upload. extraction is the default; thumbnail generates only the JPEG thumbnail. |
status | pending, completed, error, or blocked | Always | Current document processing status. |
processing_stage | String or null | Always | Current stage such as queued, thumbnailing, extracting, or completed. |
processing_error | String or null | Always | Human-readable processing failure message when status is error. |
blocked_reason | String or null | Always | Machine-readable reason when status is blocked, for example insufficient_credits. |
scanner_status | clean, rejected, or null | Always | Upload scanner decision when available. |
scanner_provider | String or null | Always | Scanner provider or configured scanning backend. |
scanner_message | String or null | Always | Scanner explanation when available. |
scanned_at | Date-time or null | Always | When file scanning completed. |
processing_started_at | Date-time or null | Always | When processing work started. |
processed_at | Date-time or null | Always | When processing reached a terminal state. |
filename | String | Always | Original uploaded filename. |
file_format | String | Always | Detected or stored file extension, for example pdf. |
file_size | Integer | Always | File size in bytes. |
additional_text | String or null | Always | Optional upload context supplied through the text form field. |
additional_text_plain | String or null | Always | Plain-text version of additional_text. |
custom_types | Array of strings or null | Always | Type extensions supplied at upload time. |
requester | String or null | Always | Caller reference supplied at upload time. |
locale | String or null | Always | Locale hint supplied at upload time. |
number_of_pages | Integer or null | Always | Detected page count when available. |
extracted_text | String or null | Always | Extracted document text when OCR/text extraction is available. |
extracted_text_plain | String or null | Always | Plain-text version of extracted_text. |
origin | api, app, or null | Always | Where the document was created. |
ai_processing | Boolean | Always | Whether AI extraction is enabled. Always false for thumbnail mode. In extraction mode, false does not disable OCR, previews, non-AI structured extraction, or charging. |
is_e_invoice | Boolean | Always | Whether the document was recognized as an e-invoice. |
thumbnail | URL or null | Always | Download URL for the generated JPEG thumbnail. Video thumbnails use a representative decoded frame. |
previews | Array or null | Always | Preview objects for completed extraction-mode documents when previews are loaded. Thumbnail mode creates none. |
extractions | Object, empty array, or null | Always | Extraction fields for completed extraction-mode documents when extractions are loaded. Completed thumbnail-only documents return an empty array. |
latest_extraction_run | Extraction run or null | Always | Latest extraction attempt metadata. Always null for thumbnail mode. |
created_at | Date-time | Always | Document creation timestamp. |
updated_at | Date-time | Always | Last document update timestamp. |
Extraction run object
| Field | Type | Description |
|---|---|---|
id | Integer | Extraction run ID. |
mode | live or test | Billing/reporting mode for the run. |
source | api, app, or null | Where the run was started. |
status | pending, processing, completed, blocked, or error | Run status. |
blocked_reason | String or null | Machine-readable block reason. |
error_code | String or null | Machine-readable failure code. |
error_message | String or null | Failure message for operators or support tooling. |
extraction_schema_version | String or null | Extraction schema version used by this run. |
extractor_version | String or null | Extractor implementation version. |
ai_prompt_version | String or null | AI prompt version used by this run. |
normalization_version | String or null | Normalization version used after extraction. |
quality | Object or null | Processing-path quality signals and AI execution settings. This can be null when no AI, PDF, email-attachment, or structured-invoice quality metadata applies. When degraded=true, inspect reasons, AI fallback/truncation fields, rejected or conflicting fields, PDF OCR coverage, email attachment selection, and structured parser, arithmetic, and source-linkage provenance before automating critical values. |
started_at | Date-time or null | When extraction processing started. |
completed_at | Date-time or null | When extraction processing completed. |
created_at | Date-time or null | When the run record was created. |
The quality object is deliberately separate from the run status. A run can complete successfully while using a text fallback, partial deterministic supplementation, truncated evidence, incomplete OCR coverage, or a degraded email attachment path. High-detail PDF evidence is the primary path, including a PDF selected from an EML or MSG container. Low detail is used only as a context-limit fallback and is cross-checked for detected conflicts against independently extracted document text when that text is available. A cross-check is credited only when the fallback pass contains document text without supplemental email evidence; a combined document-and-email pass remains conservatively unverified because field-level provenance cannot be isolated. A missing value in one pass does not confirm the other pass. An attachment+text mode means separate evidence attempts contributed to the result; exdata does not send the same PDF content twice in one request. For email uploads, quality.email records bounded parsing, ignored decoration, unsupported or failed attachments, evidence truncation, and whether multiple document candidates were present. quality.structured records parser/profile support, structural and arithmetic validation, whether machine-readable values were accepted, and field-name-only linkage or conflicts against a paired PDF. Unsupported standalone e-invoice XML fails processing instead of completing with empty invoice fields. For hybrid PDFs and email containers, rejected structured data is not used silently; another readable source may complete the run with degraded quality and explicit conflict metadata. A single extraction result uses one selected financial attachment and does not merge separate invoices. Treat quality.status=degraded as a review signal for money, tax, payment, identity, and date fields. quality.status=normal means that no known processing degradation was recorded; it is not a confidence score or a guarantee that every extracted value is correct.
Preview object
| Field | Type | Description |
|---|---|---|
id | Integer | Preview ID used by the preview download endpoint. |
filename | String | Generated preview filename. |
file_format | String | Preview file extension, for example png. |
file_size | Integer | Preview file size in bytes. |
preview | URL | Download URL for the preview binary. |
Extraction field object
| Field | Type | Description |
|---|---|---|
value | String, array, object, or null | Normalized value for system mapping. Amounts are dot-decimal strings, dates use YYYY-MM-DD, currency uses ISO 4217, and tax_breakdowns uses an array of tax rows. |
candidates | Array or null | Raw or derived candidate values considered for the field. Use these in review UIs, support tools, and debugging. |
Error envelope
| Field | Type | Description |
|---|---|---|
message | String | Human-readable error message. |
code | String | Machine-readable error code such as validation_failed or insufficient_credits. |
request_id | String | Request identifier for support and log correlation. |
errors | Object | Validation field errors. Present on 422 responses. |
retry_after | Integer or null | Retry delay in seconds. Present on some rate-limit responses. |
available_credits | Integer | Available credits. Present on insufficient-credit upload responses. |
required_credits | Integer | Credits required for the upload. Present on insufficient-credit upload responses. |
document | Document object | Blocked document created before credit reservation failed. Present on insufficient-credit upload responses. |
account_daily_document_limit | Integer | Sandbox account daily upload limit. Present on test-mode limit responses. |
user_daily_document_limit | Integer | Sandbox user daily upload limit. Present on test-mode limit responses. |
token_daily_document_limit | Integer | Sandbox token daily upload limit. Present on test-mode limit responses. |