API v1 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 409 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/documents/{document}/extraction-runs/{extractionRun}/pages/{physicalPage}/preview Download an extraction evidence page preview downloadDocumentExtractionEvidencePagePreview 200 403 404 429
GET /api/v1/documents/{document}/exports/{projection} Download a document profile export downloadDocumentProfileExport 200 403 404 409 429
GET /api/v1/documents/exports/{projection} Download a deterministic batch profile export downloadDocumentProfileExportBatch 200 403 404 409 422 429
POST /api/v1/documents/{document}/extractions/reviews Review a profile result reviewDocumentExtraction 201 403 404 409 422 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 and review writes String, max 255 characters Unique key for one logical write. Upload replay compares the caller-supplied file and fields, including mode, lane, and profile; later changes to profile settings or prices do not alter the stored replay. Review replay compares the complete decision payload.
If-Match Review writes only Profile-result ETag Optimistic concurrency guard returned by the extractions endpoint. A stale value returns 409 extraction_version_conflict.
X-Request-ID No String, max 128 characters Optional caller request ID. exdata echoes this value, or a generated request ID, in error responses.
GET /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.

ParameterLocationRequiredDescription
None-NoOnly the bearer token is required.
StatusResponseDescription
200JSON objectAuthentication succeeded.
401Error envelopeBearer token is missing, invalid, or revoked.
429Error envelopeRead rate limit exceeded.
Request
curl -sS "https://www.exdata.app/api/v1/ping" \
  -H "Authorization: Bearer $EXDATA_API_TOKEN"
200 response
{
  "status": true
}
GET /api/v1/documents

List documents

Returns paginated documents for the token's account. Use this endpoint for status dashboards, reconciliation, integration workflows, and scheduled backfills.

ParameterLocationRequiredTypeDescription
sortQueryNocreated_at or -created_atSort by creation time. Use -created_at for newest first.
per_pageQueryNoInteger, 1-100Number of documents per page. Defaults to 100.
extraction_profileQueryNoStringFilter by the profile selected at upload, for example de.energy.supply-invoice.
review_statusQueryNoProfile outcomeFilter by the current outcome of the effective specialized profile result, such as needs_review.
handoff_statusQueryNoHandoff statusFilter by the current downstream projection state.
StatusResponseDescription
200Paginated document listdata contains document objects. links and meta contain Laravel pagination data.
403Error envelopeThe token does not have documents:read.
422Validation errorA query parameter is not valid.
429Error envelopeRead rate limit exceeded.
Request
curl -sS "https://www.exdata.app/api/v1/documents?sort=-created_at&per_page=25" \
  -H "Authorization: Bearer $EXDATA_API_TOKEN"
200 response
{
  "data": [
    {
      "id": 123,
      "mode": "live",
      "processing_mode": "extraction",
      "processing_lane": "standard",
      "status": "completed",
      "processing_stage": "completed",
      "processing_error": null,
      "blocked_reason": null,
      "scanner_status": "clean",
      "scanner_provider": "default",
      "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",
        "processing_lane": "standard",
        "source": "api",
        "status": "completed",
        "blocked_reason": null,
        "error_code": null,
        "error_message": 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",
        "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": [],
            "recovered_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
  }
}
POST /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. Omitting extraction_profile selects the generic extraction, which uses one live credit per started 10-page band. de.energy.supply-invoice currently uses 3 credits per band, so 1–10 pages use 3 credits and 11–20 use 6. The final billable total is the credit_cost recorded for the run multiplied by the number of started bands and is kept when a usable result or retrievable extracted fields remain. thumbnail mode only creates a JPEG thumbnail with zero credit usage. The optional batch lane is available to eligible accounts and uses lower-priority capacity for delay-tolerant workloads.

ParameterLocationRequiredTypeDescription
fileForm dataYesFile, max 500 MBSupported document file. Lower format-specific processing limits apply; see the supported-file capability matrix.
textForm dataNoString or null, max 256 KiBAdditional 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. Validation mode rejects this field because it evaluates only the uploaded PDF or XML.
custom_types[]Form dataNoArray of stringsUp 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. Validation mode does not use or persist these extensions.
requesterForm dataNoString or nullIntegration name, user reference, workflow ID, or source system, up to 255 characters. For de.energy.supply-invoice, it remains upload metadata and does not affect profile extraction.
localeForm dataNoString or nullSupported locale such as en or de.
processing_modeForm dataNoextraction, analysis, validation, or thumbnailDefaults to extraction. Analysis mode does not run AI or structured extraction and returns the thumbnail, previews, page count, extracted text, and e-invoice detection. Validation mode accepts PDF or XML and returns only the structured-invoice assessment without AI, general extraction, persisted previews, a thumbnail, or retained document text. Both use the generic page-band credit calculation. Thumbnail mode skips OCR, AI, structured extraction, persisted previews, extraction runs, and credit usage.
processing_laneForm dataNostandard or batchDefaults to standard. Batch is available to eligible accounts. It uses constrained lower-priority capacity, may take longer to start, and preserves the same result fields, statuses, polling behavior, and lifecycle webhooks. If batch is unavailable for the account, the upload returns 422 with code=validation_failed and a processing_lane validation error.
pagesForm dataNoString, max 255Analysis mode only, for PDF and single-page file types. Comma-separated first, last, all, or 1-based page numbers, for example first,last. Only the requested pages are processed, returned, and charged; the thumbnail still uses the first page. Other processing modes and Word, TIFF, email, or video uploads return 422.
allow_ai_processingForm dataNoBooleanMultipart 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 page-band credit calculation. Thumbnail, analysis, and validation mode take precedence over either value.
extraction_profileForm dataNogeneric or de.energy.supply-invoiceOmit for generic extraction. Validation mode accepts only the generic profile. Any active account can explicitly select de.energy.supply-invoice; it accepts PDF uploads and requires extraction mode with AI enabled. New uploads use profile version 2.0.1 and schema version 2.0.0, and the current rate is 3 credits per started 10-page band. The selected profile determines the version, processing settings, and applicable per-band rate recorded for the run. Upload, polling, result, review, and export operations use the document endpoints. Read the canonical payload from GET /api/v1/documents/{document}/extractions or download its canonical_json and invoice_lines_csv exports after acceptance.
Processing field interaction

Omitting processing_mode is the same processing choice as extraction. With extraction mode, allow_ai_processing controls AI only. With analysis, validation, and thumbnail mode, exdata reports ai_processing: false regardless of that field.

Choose analysis when you need the thumbnail, previews, page count, extracted text, and e-invoice detection but not extraction. Structured extraction does not run in analysis mode, so analysis documents complete with an empty extractions array. It uses the same stages, webhooks, and page-band credit calculation as extraction, and returns considerably faster because AI processing is not performed.

Choose validation when a PDF or XML file needs a structured-invoice assessment without general extraction. The asynchronous run performs detection, the applicable XML validation, and required PDF/XML linkage. For valid embedded invoice XML, bounded rendered OCR is required for visible linkage; a searchable or hidden native text layer does not establish a passing result. Multiple recognized invoice XML attachments produce an indeterminate multiple_embedded_invoice_xml_attachments result instead of selecting one. Invalid and unsupported input completes with an explicit assessment; a technical validator dependency failure remains retryable and, after a terminal failure, is available as validation_status: "unavailable". A completed assessment is published only after the final page-band total is covered, so a page-band funding block exposes no completed structured assessment. Read the result from latest_extraction_run.quality.structured. The run creates no extraction fields, persisted previews, thumbnail, or retained document text.

With analysis you can also choose which pages of a PDF to process using pages, for example first, last, first,last, all, or 1,3,5. Pages you do not request are not processed: they are not OCRed and contribute no text to the result, and the page band is charged on the pages you asked for. The thumbnail and the first-page preview are always generated. A smaller selection returns sooner and costs less. Page numbers beyond the document are ignored; a selection whose pages all lie beyond the document processes the first page. When the page count cannot be read, last resolves within the documented visual PDF processing limit. The field is rejected with 422 in other modes and for file types without selectable pages, such as Word, TIFF, email, and video; single-page file types collapse every selection to their one page.

Result-based credit usage

A live extraction keeps its final page-band total when a usable result or retrievable extracted fields remain. A terminal processing error that leaves neither, including a preprocessing failure, returns all applied credits and reports latest_extraction_run.credits_charged: 0. Test-mode and thumbnail-only uploads have zero net live credit usage. Reprocessing after an already charged result also reports zero; reprocessing after a fully returned failure receives a new page-band charge when it first leaves a usable result or retrievable extracted fields.

StatusResponseDescription
201Document resourceThe document was accepted. A live extraction normally applies the recorded credit_cost to its first band. Because analysis determines the page count later, polling or document.blocked can still report page_band_insufficient_credits; that outcome returns the initial credits. Thumbnail mode is accepted without an extraction run or credit check.
402Insufficient credits errorExtraction, analysis, or validation mode. The document was created, then blocked because available credits do not cover the first band at the applicable rate. No credit was charged. Thumbnail mode is not blocked by the credit balance.
403Error envelopeThe token does not have documents:write, or the account is suspended.
409Error envelopeThe idempotency key is still processing, was reused with a different upload payload, or identifies an interrupted attempt that created a document. The last case returns conflict_reason=document_created with a cleanup-only document.id; delete it before deciding whether to submit a new upload.
422Validation errorThe file or form field failed validation.
429Error envelopeUpload rate limit exceeded, including sandbox daily upload limits for test-mode tokens.
Upload request with cURL
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"
Thumbnail-only upload
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"
201 response: extraction
{
  "data": {
    "id": 123,
    "mode": "live",
    "processing_mode": "extraction",
    "processing_lane": "standard",
    "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",
      "processing_lane": "standard",
      "source": "api",
      "status": "pending",
      "blocked_reason": null,
      "error_code": null,
      "error_message": 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",
      "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"
  }
}
201 response: thumbnail
{
  "data": {
    "id": 124,
    "mode": "live",
    "processing_mode": "thumbnail",
    "processing_lane": "standard",
    "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"
  }
}
GET /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.

ParameterLocationRequiredTypeDescription
documentPathYesIntegerDocument ID returned by create or list.
StatusResponseDescription
200Document resourceCurrent document state. Completed documents can include previews and extraction fields.
403Error envelopeThe token cannot access this document or lacks documents:read.
404Error envelopeNo document exists for this account and ID.
Request
curl -sS "https://www.exdata.app/api/v1/documents/123" \
  -H "Authorization: Bearer $EXDATA_API_TOKEN"
200 response
{
  "data": {
    "id": 123,
    "mode": "live",
    "processing_mode": "extraction",
    "processing_lane": "standard",
    "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",
      "processing_lane": "standard",
      "source": "api",
      "status": "completed",
      "blocked_reason": null,
      "error_code": null,
      "error_message": 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",
      "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": [],
          "recovered_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"
  }
}
200 response: completed thumbnail mode
{
  "data": {
    "id": 124,
    "mode": "live",
    "processing_mode": "thumbnail",
    "processing_lane": "standard",
    "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"
  }
}
DELETE /api/v1/documents/{document}

Delete document

Makes the document resource and stored extracted values unavailable to the account. The service attempts to remove the ordinary source file, thumbnail, and previews, but the response is not an object-storage deletion receipt.

A separately retained quality-evidence sample may remain until its documented retention expiry. This exception is uncommon and does not change the document's account visibility after deletion.

ParameterLocationRequiredTypeDescription
documentPathYesIntegerDocument ID to delete.
StatusResponseDescription
204 No ContentNo bodyThe document and stored extracted values are no longer available. Ordinary source, thumbnail, and preview cleanup was attempted; this response does not attest to object-storage deletion. A separately retained quality-evidence sample follows its documented retention expiry.
403Error envelopeThe token cannot delete this document or lacks documents:write.
404Error envelopeNo document exists for this account and ID.
409Error envelopeThe current live extraction is still active. Retry after the document reaches a terminal status.
Request
curl -sS -X DELETE "https://www.exdata.app/api/v1/documents/123" \
  -H "Authorization: Bearer $EXDATA_API_TOKEN" \
  -i
GET /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.

ParameterLocationRequiredTypeDescription
documentPathYesIntegerDocument ID.
StatusResponseDescription
200JPEG binary (image/jpeg)Generated document thumbnail or, for a video, its representative frame.
403Error envelopeThe token cannot access this document or lacks documents:read.
404Error envelopeNo document or thumbnail exists for this account and ID.
Request
curl -L "https://www.exdata.app/api/v1/documents/123/thumbnail" \
  -H "Authorization: Bearer $EXDATA_API_TOKEN" \
  -o document-123-thumbnail.jpg
GET /api/v1/documents/{document}/previews

List previews

Returns preview metadata for generated page or file previews. Every supported e-invoice receives one human-readable HTML invoice visualization in CII, UBL, and ZUGFeRD 1.0 COMFORT syntax, so the same invoice layout is returned regardless of the source format. Locally validated Extension XRechnung 3.0 invoices additionally keep their source-ordered recursive invoice-line view. For exceptionally large line sets or repeatable review sections, the affected content is shown as a clearly labelled bounded prefix so browser rendering remains safe; the original XML remains unchanged. This HTML file is the canonical preview; the accompanying JPEG is only a representative thumbnail and visual fallback. Remaining safe XML uses a pretty-printed XML fallback. The visualization is labelled in the document locale; English and German are available. Use the returned preview ID with the preview download endpoint. Thumbnail mode never creates persisted previews, so a completed thumbnail-only document returns {"data":[]}.

ParameterLocationRequiredTypeDescription
documentPathYesIntegerDocument ID.
StatusResponseDescription
200Preview listdata contains preview objects for this document, or an empty array for thumbnail mode.
403Error envelopeThe token cannot access this document or lacks documents:read.
404Error envelopeNo document exists for this account and ID.
Request
curl -sS "https://www.exdata.app/api/v1/documents/123/previews" \
  -H "Authorization: Bearer $EXDATA_API_TOKEN"
200 response
{
  "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"
    }
  ]
}
Thumbnail-only result

For a completed thumbnail-only document, this endpoint returns {"data":[]}. Download the JPEG from /documents/{document}/thumbnail instead.

GET /api/v1/previews/{preview}

Download preview

Downloads the binary preview file. Preview IDs are returned by the document previews endpoint and are account-scoped.

ParameterLocationRequiredTypeDescription
previewPathYesIntegerPreview ID returned by /documents/{document}/previews.
StatusResponseDescription
200Binary streamPreview file. The content type depends on the generated preview.
403Error envelopeThe token cannot access this preview or lacks documents:read.
404Error envelopeNo preview exists for this account and ID.
Request
curl -L "https://www.exdata.app/api/v1/previews/987" \
  -H "Authorization: Bearer $EXDATA_API_TOKEN" \
  -o document-123-page-1.png
GET /api/v1/documents/{document}/extractions

Read extractions

Returns extracted fields keyed by field name. Read this endpoint after the document reaches a terminal completed, error, or blocked status, or after receiving a document.completed or document.failed webhook. A finalized specialized profile result is returned under sector_extraction; an error document can therefore expose a canonical failed result, while a blocked document has none. There is no separate profile-result endpoint. Its common envelope is profile-neutral, while payload, validation, review, evidence, and registered projections are supplied by the selected profile. German energy full-invoice profile versions 2.0.0 and 2.0.1 return machine_payload and effective_payload as {"packet": {...}, "invoices": [...]}. A single invoice still appears at invoices[0], independently issued invoices remain separate items, and a source-verified non-invoice has invoices=[] with an unsupported outcome. The result advertises canonical JSON and invoice-line CSV exports under sector_extraction.exports. Structured extraction does not run in thumbnail, analysis, or validation mode, so those documents return {"data":[]} after completion.

ParameterLocationRequiredTypeDescription
documentPathYesIntegerTerminal document ID. A finalized specialized result can be selected for delivery from a completed or error document.
includeQueryNoevidenceIncludes profile evidence plus sorted evidence_pages[] descriptors for cited pages from the exact extraction run. Omit for the compact response.
StatusResponseDescription
200Extraction object or empty arraydata is an object keyed by normalized field name, or an empty array for thumbnail, analysis, or validation mode. sector_extraction is present when a finalized specialized profile result is selected for delivery, including a canonical failed result when no usable earlier result exists; its ETag is returned in the response header.
403Error envelopeThe token cannot access this document or lacks documents:read.
404Error envelopeNo document exists for this account and ID.
Read extractions with cURL
curl -sS "https://www.exdata.app/api/v1/documents/123/extractions" \
  -H "Authorization: Bearer $EXDATA_API_TOKEN"
200 response
{
  "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"]
    }
  }
}
GET /api/v1/documents/{document}/extraction-runs/{extractionRun}/pages/{physicalPage}/preview

Download extraction evidence page preview

Downloads one protected page artifact cited by a specialized profile result. Use the preview_url returned in sector_extraction.evidence_pages[] instead of constructing a URL from the latest document state. The document, immutable extraction run, and physical page must match exactly; this endpoint never falls back to a page from another run.

ParameterLocationRequiredDescription
documentPathYesAccount-scoped document ID.
extractionRunPathYesExact extraction run ID from the profile result.
physicalPagePathYesOne-based cited physical page.
StatusResponseDescription
200Inline binary artifactReturns the safe stored content type with Cache-Control: private, no-store.
403Error envelopeThe token cannot access the account document or lacks documents:read.
404Error envelopeThe document, exact run/page relation, or safe persisted artifact is unavailable. Missing and expired artifacts fail closed.
429Error envelopeRead rate limit exceeded.
Download cited page
curl -L "https://www.exdata.app/api/v1/documents/123/extraction-runs/456/pages/1/preview" \
  -H "Authorization: Bearer $EXDATA_API_TOKEN" \
  -o evidence-page-1.jpg
GET /api/v1/documents/{document}/exports/{projection}

Download document profile export

Downloads a projection only when the selected profile registers one. Read the stable URL, projection contract version, and current availability from sector_extraction.exports. German energy full-invoice profile versions 2.0.0 and 2.0.1 register canonical_json at canonical.json for the complete packet and every invoice, and invoice_lines_csv at invoice-lines.csv for all invoice charge lines with leading invoice identity and page-range columns. Both become available only after the effective result and handoff are accepted.

StatusResponseDescription
200Projection-defined attachmentReturned after the extraction is finalized and the selected projection's readiness requirements pass. Includes result ETag, X-Projection-Version, and private no-store caching.
403Error envelopeThe token cannot access the document or lacks documents:read.
404Error envelopeThe document, effective profile result, or requested registered projection is unavailable.
409Error envelopeprofile_export_not_ready with current outcome and handoff details.
429Error envelopeRead rate limit exceeded.
GET /api/v1/documents/exports/{projection}

Download deterministic batch profile export

Combines 1–100 distinct documents into one batch-capable projection when the selected profile registers one. Repeat document_ids[] for each ID. The request is account-scoped and all-or-nothing: every document must exist in the caller's account, every extraction run must be completed and finalized, every effective result and handoff must be accepted, and every result must expose the same batch projection implementation and version. German energy full-invoice profile versions 2.0.0 and 2.0.1 support batch invoice-lines.csv; rows are ordered by document ID, then preserve invoice source order and each invoice's charge-line order.

StatusResponseDescription
200Projection-defined attachmentRows are rendered in ascending document-ID order regardless of request order. Includes a composite ETag, shared X-Projection-Version, and private no-store caching.
403Error envelopeThe token lacks documents:read.
404Error envelopeAt least one ID is unknown or outside the account. No partial output or ownership detail is returned.
409Error envelopeprofile_export_not_ready for missing, unfinished, or unaccepted results, or profile_export_incompatible when no one shared batch projection can render the complete set.
422Validation errorThe request does not contain 1–100 distinct positive integer document_ids[] values.
429Error envelopeRead rate limit exceeded.
Download deterministic batch
curl -L "https://www.exdata.app/api/v1/documents/exports/invoice-lines.csv?document_ids[]=456&document_ids[]=123" \
  -H "Authorization: Bearer $EXDATA_API_TOKEN" \
  -o invoice-lines.csv
POST /api/v1/documents/{document}/extractions/reviews

Review a profile result

Records one append-only review decision and revalidates the effective profile result returned under sector_extraction. For German energy full-invoice profile versions 2.0.0 and 2.0.1, confirmation and correction require the target invoice_ref; complete-packet rejection must omit it. API tokens require extractions:review. Send both Idempotency-Key and the latest extraction ETag as If-Match. A review-only token receives audit metadata after the write; add documents:read to receive field values and the full profile payload.

Every action may include review_duration_seconds, an integer from 1 through 86,400 containing measured active human-review time spent reaching that individual decision. This caller-supplied value is workflow telemetry, not the age of the queue item or wall-clock time between extraction and review. Omit it or send null when active time was not measured; exdata then marks duration coverage incomplete and never assumes the missing time was zero.

ActionRequired JSON fieldsDescription
confirminvoice_ref, entity_ref, fieldConfirms the current non-empty value in one German energy invoice.
correctinvoice_ref, entity_ref, field, corrected_value, evidence_referenceCorrects one reviewable field in the selected German energy invoice. Most corrections are non-empty strings; billing_period uses {"start","end"}, while service_address and billing_address use address objects.
rejectreasonRejects the complete result. A rejected result is terminal; German energy rejection must omit invoice_ref.

evidence_reference uses component_ref, physical_page, optional printed_page/label, text, a profile-defined source, optional match, and optional bbox. It is optional for confirm, which otherwise retains the current citation, and required for correct. The selected profile validates the source against the run and, for German energy, verifies that the component and page belong to the selected invoice; the profile currently accepts native_text, embedded_ocr, tesseract_ocr, and combined. Evidence must support the complete reviewed value. Identifier evidence needs a type-compatible label inside the evidence text; supplier and customer names need the correct party role; service and billing addresses need the correct address role. Every populated structured address component must occur in its corrected raw value and the evidence, and an explicit country code must be visible as the country name or uppercase code. Technical identifiers are normalized and format-checked for both actions. MaLo and legacy metering-point values can only be reviewed on a supply point, MeLo on a metering location, meter numbers on meter assignments, and operator_code on the operator that owns it.

Reviewer transcription is a privileged attestation

exdata verifies that the cited component, physical page, and selected text source belong to the selected invoice in the recorded page manifest. It stores manually supplied evidence text with reviewer_transcribed=true, but does not compare that transcription with OCR or native extracted text. This permits correction of OCR errors, so grant extractions:review only to trusted reviewers who visually check the cited page. A review does not clear an ambiguous supply-point association; affected relationship identifiers remain in review in the canonical payload until a new extraction resolves it.

StatusResponseDescription
201Decision and updated profile resultReturns the new ETag. Review-only tokens receive metadata; tokens with documents:read receive the full result. An identical retry also returns Idempotent-Replayed: true.
403Error envelopeThe token lacks extractions:review, is outside the account, or the user role cannot review.
404Error envelopeNo document or specialized profile result exists for this account and ID.
409Error envelopeextraction_version_conflict for a stale ETag, or idempotency_conflict when the key was reused with another payload.
422Validation errorThe action, target field, corrected value, evidence reference, or headers are invalid; rejected results and accepted handoffs are terminal and also reject later decisions.
429Error envelopeWrite rate limit exceeded.

When a decision makes both effective_outcome and handoff_status accepted, the accepted handoff is terminal. A later confirmation, correction, or rejection returns a validation error and cannot mutate the accepted result snapshot.

Correct a field
curl -sS -X POST "https://www.exdata.app/api/v1/documents/123/extractions/reviews" \
  -H "Authorization: Bearer $EXDATA_REVIEW_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: correct-customer-number-123" \
  -H 'If-Match: "extraction-result-789-v0"' \
  --data '{
    "action": "correct",
    "invoice_ref": "invoice_5f2db86e322d058b2bfd",
    "entity_ref": "relationship_1",
    "field": "customer_number",
    "corrected_value": "KUNDE-10",
    "reason": "Confirmed against the printed account block.",
    "review_duration_seconds": 95,
    "evidence_reference": {
      "component_ref": "component_8a1f74f0f1d8c2ab",
      "physical_page": 1,
      "printed_page": "1",
      "label": "Kundennummer",
      "text": "Kundennummer KUNDE-10",
      "source": "native_text",
      "match": "manual"
    }
  }'
201 response excerpt
{
  "data": {
    "decision": {
      "id": 901,
      "action": "correct",
      "invoice_ref": "invoice_5f2db86e322d058b2bfd",
      "entity_ref": "relationship_1",
      "field": "customer_number",
      "review_duration_seconds": 95,
      "previous_value": "KUNDE-1O",
      "corrected_value": "KUNDE-10",
      "expected_lock_version": 0,
      "resulting_lock_version": 1
    },
    "sector_extraction": {
      "id": 789,
      "machine_outcome": "needs_review",
      "effective_outcome": "accepted",
      "handoff_status": "accepted",
      "lock_version": 1,
      "etag": "\"extraction-result-789-v1\""
    }
  }
}

Response objects

The tables below define the fields used by endpoint responses. The extraction field reference lists every normalized extraction key separately.

For XML documents, is_e_invoice=true means a supported structured e-invoice was accepted after validation; recognizing invoice-like XML alone does not set the flag. Standard XRechnung 3.0 and the exact Extension profile in supported UBL and CII syntax use their matching pinned KoSIT scenarios on the original XML and report xml_profile_conformance. The exact CVD profile in CII syntax uses its pinned KoSIT scenario but reports structural_and_business; UBL CVD is not claimed as supported. The exact ZUGFeRD 1.0 COMFORT profile with TypeCode 380 or 84 is validated against its checksum-pinned XSD, Schematron constraints, and arithmetic rules and reports structural_and_business. The published tax TypeCodes VAT, ZF_INSURANCE_TAX (insurance tax), and AAJ (second-hand-parts tax) are supported. Accepted document-level values map into the v1 fields. Recursive line hierarchy, embedded attachment metadata, and third-party payment rows from the UBL Extension path feed the generated HTML visualization but are not returned as v1 extraction fields; exceptionally large line sets or repeatable review sections are shown as clearly labelled source-order prefixes. Multiple ambiguous payee accounts remain validation-only and leave the singular iban and bic fields null. ZUGFeRD 1.0 BASIC and EXTENDED, other document or tax codes, invalid invoices, and unknown or unsupported profiles fail closed with unsupported_structured_invoice in extraction mode.

Document object

FieldTypeWhen presentDescription
idIntegerAlwaysDocument ID.
modelive or testAlwaysWhether the document was created by a live or test-mode token.
processing_modeextraction, analysis, validation, or thumbnailAlwaysWork selected at upload. extraction is the default; analysis runs the lifecycle without AI extraction; validation returns only the structured-invoice assessment; thumbnail generates only the JPEG thumbnail.
processing_lanestandard or batchAlwaysProcessing priority selected at upload. Batch is available to eligible accounts and is returned when selected for the upload. It can take longer to start but does not change the result contract. If batch is unavailable for the account, the upload returns 422 with code=validation_failed and a processing_lane validation error.
pagesString or nullAlwaysNormalized page selection stored for this upload, exactly as requested, such as first,last or all. null when the upload did not send a selection; selections only exist in analysis mode.
statuspending, completed, error, or blockedAlwaysCurrent document processing status.
processing_stageString or nullAlwaysCurrent stage such as queued, thumbnailing, extracting, or completed. waiting_for_capacity means the document is accepted while your account is already at its concurrent standard-lane limit; it starts automatically as your earlier documents finish. Thumbnail mode can report this too because thumbnail rendering uses standard processing capacity.
processing_errorString or nullAlwaysHuman-readable processing failure message when status is error.
blocked_reasonString or nullAlwaysMachine-readable reason when status is blocked, for example insufficient_credits.
scanner_statusclean, rejected, or nullAlwaysUpload scanner decision when available.
scanner_providerString or nullAlwaysLabel identifying the scanner result source when available.
scanner_messageString or nullAlwaysScanner explanation when available.
scanned_atDate-time or nullAlwaysWhen file scanning completed.
processing_started_atDate-time or nullAlwaysWhen processing work started.
processed_atDate-time or nullAlwaysWhen processing reached a terminal state.
filenameStringAlwaysOriginal uploaded filename.
file_formatStringAlwaysDetected or stored file extension, for example pdf.
file_sizeIntegerAlwaysFile size in bytes.
additional_textString or nullAlwaysOptional upload context supplied through the text form field.
additional_text_plainString or nullAlwaysPlain-text version of additional_text.
custom_typesArray of strings or nullAlwaysType extensions supplied at upload time.
requesterString or nullAlwaysCaller reference supplied at upload time.
localeString or nullAlwaysLocale hint supplied at upload time.
number_of_pagesInteger or nullAlwaysDetected page count when available.
extracted_textString or nullAlwaysDocument text exactly as extraction produced it. Page boundaries are form feed characters, and bracketed diagnostic and structure markers such as [PAGE OCR WARNING: OCR RETURNED NO TEXT] record how the text was produced.
extracted_text_plainString or nullAlwaysThe same text normalized for reading and indexing: whitespace collapsed, diagnostic and email structure markers removed, page boundaries kept as form feed characters. Prefer this field for full-text search, and split on the form feed for per-page text.
originapi, app, mcp, x402, or nullAlwaysWhere the document was created.
ai_processingBooleanAlwaysWhether AI extraction is enabled. Always false for thumbnail, analysis, and validation mode. In extraction mode, false does not disable OCR, previews, non-AI structured extraction, or charging.
extraction_profilegeneric or de.energy.supply-invoiceAlwaysEffective extraction profile recorded at upload.
is_e_invoiceBooleanAlwaysWhether a supported structured e-invoice was accepted after validation. Recognition alone does not set this flag.
thumbnailURL or nullAlwaysDownload URL for the generated JPEG thumbnail. Video thumbnails use a representative decoded frame.
previewsArray or nullAlwaysPreview objects for completed extraction-mode documents when previews are loaded. Thumbnail mode creates none.
extractionsObject, empty array, or nullAlwaysExtraction fields for completed extraction-mode documents when extractions are loaded. Completed thumbnail-only, analysis, and validation documents return an empty array.
latest_extraction_runExtraction run or nullAlwaysLatest extraction attempt metadata. Always null for thumbnail mode.
sector_extraction_summaryObject or nullAlwaysCompact current specialized profile result with review and handoff states, ETag, the extractions URL, and export descriptors. Null until a profile result exists.
created_atDate-timeAlwaysDocument creation timestamp.
updated_atDate-timeAlwaysLast document update timestamp.

Extraction run object

FieldTypeDescription
idIntegerExtraction run ID.
modelive or testBilling/reporting mode for the run.
processing_lanestandard or batchProcessing priority used by this extraction attempt.
sourceapi, app, mcp, x402, or nullWhere the run was started.
statuspending, processing, completed, blocked, or errorRun status.
blocked_reasonString or nullMachine-readable block reason.
error_codeString or nullMachine-readable failure code. In extraction mode, unsupported_structured_invoice means XML was deterministically rejected because it exceeded safety limits, was unsafe or malformed, violated structured-invoice validation rules, or used an unsupported profile. Inspect quality.structured.validation_status, assessment, and validation_errors. Technical validator unavailability remains retryable and is never classified as an invalid invoice.
error_messageString or nullFailure message for diagnosing the run.
credits_chargedInteger or nullCurrent net billable total. A live run applies one profile-rate band, calculates usage as credit_cost × started 10-page bands, and keeps the total when a usable result or retrievable extracted fields remain. Terminal errors that leave neither, and page-band blocks caused by unavailable credits, report zero after credits are returned. Test and other non-credit runs report zero. Null means no credit usage was recorded.
extraction_schema_versionString or nullExtraction schema version used by this run.
extractor_versionString or nullExtractor version recorded for this run.
ai_prompt_versionString or nullProcessing instruction version recorded for this run.
normalization_versionString or nullNormalization version used after extraction.
extraction_profile, profile_versionStringProfile key and contract version used for this run.
ai_modelString or nullProcessing model recorded for this run.
ai_reasoning_effortString or nullReasoning setting recorded for this run.
strategies_usedArray or nullProfile-specific extraction strategies recorded for reproducibility.
provenance_summaryObject or nullWinning-value method summary for non-null extraction fields. It reports classification, methods_used, and per-method field_counts. It is null when no automatic winning-field provenance snapshot was persisted, including legacy, in-progress, analysis, validation, and reviewed-profile runs; this is separate from strategies_used.
billing_modeStringBilling treatment recorded for the run. This is informational run metadata, not an upload parameter.
credit_costIntegerCredits per started 10-page band recorded for this run. For example, a rate of 3 and two bands yields credits_charged: 6 when the run retains a usable result or retrievable extracted fields.
credit_cost_sourceStringIndicates how the recorded per-band rate was determined. This is returned run metadata, not an upload parameter; use it when your integration needs to interpret the rate rather than infer it from the profile name.
qualityObject or nullProcessing-path quality signals and AI execution settings. This can be null when no AI, PDF, email-attachment, or structured-invoice quality metadata applies. For structured invoices, use quality.structured.assessment as the objective validation and linkage result; do not derive an e-invoice traffic light from the general quality.status. When degraded=true, inspect reasons and the applicable component details before automating critical values.
started_atDate-time or nullWhen extraction processing started.
completed_atDate-time or nullWhen extraction processing completed.
created_atDate-time or nullWhen 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 visual evidence from PDFs and supported JPEG, PNG, and WebP source images is the primary AI attachment 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 or OCR 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 attachment and text evidence attempts contributed to the result; exdata does not send the same attachment content twice in one request. A text fallback may also repair partially valid attachment evidence. A complete, untruncated, document-only pass over clean high-detail PDF processing can remain normal only when every repaired field is deterministically corroborated by document text and no unrelated text field contributes. This strict normal recovery is currently limited to a country-format- and checksum-valid IBAN that differs by exactly one character from a checksum-only rejection and appears as the sole distinct valid IBAN in the document text; quality.ai.recovered_fields reports it. Other rejected fields remain in quality.ai.rejected_fields and keep the result degraded. 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 syntax/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 unresolved processing degradation remains after bounded recovery; it is not a confidence score or a guarantee that every extracted value is correct.

New structured-quality snapshots have contract_version: 1. detection_status distinguishes recognized, a completed not_detected result, and inconclusive. validation_status distinguishes accepted validation, warnings, completed invalidity, unsupported profiles, technical unavailability, and input that could not be evaluated safely. validation_scope says whether the claim is XML profile conformance, deterministic structural and business validation, or none. Standard and Extension XRechnung report XML profile conformance in supported UBL and CII syntax; CVD CII and ZUGFeRD 1.0 COMFORT report structural and business validation without claiming complete XML profile conformance. assessment combines validation with required PDF/XML linkage into pass, pass_with_warnings, fail, indeterminate, or not_applicable. Persisted validator metadata identifies the engine, engine version, configuration, standard, and scenario used for that run. Findings contain bounded rule identifiers and severity counts only, never message text or document contents. A valid XML result can still have assessment: "fail" when its visible PDF conflicts. This contract makes no statement about legal validity or complete PDF/A/container conformance, and older snapshots that omit these fields remain unknown rather than not_detected.

Profile-result summary object

This profile-neutral summary is returned under sector_extraction_summary. The German energy profile is the currently available specialized example.

FieldTypeDescription
id, extraction_run_idIntegerProfile result and source run identifiers.
profileStringCanonical profile key.
profile_versionStringProfile contract version.
schema_versionStringCanonical payload schema version.
machine_outcomeStringImmutable extraction/validation outcome.
effective_outcomeStringCurrent outcome after review.
handoff_statusStringCurrent downstream handoff state.
review_reasonsArrayBlocking canonical review reason codes.
handoff_review_reasonsArrayAdditional downstream handoff blockers.
warningsArrayNon-blocking source or extraction warnings.
lock_version, etagInteger and stringOptimistic concurrency state used for review decisions.
extractions_urlURLDocument-extractions endpoint containing the complete profile result.
exportsObjectProfile-registered export descriptors. German energy full-invoice profile versions 2.0.0 and 2.0.1 expose canonical_json and invoice_lines_csv, each with a stable url, contract version, and available flag.

Profile result object

The complete profile-neutral envelope is returned under sector_extraction. profile and schema_version define the nested payload contract.

FieldTypeDescription
id, document_id, extraction_run_idIntegerResult and source record identifiers.
profile, profile_version, schema_versionStringVersioned canonical contract.
machine_outcomeStringaccepted, needs_review, unsupported, or failed.
effective_outcomeStringMachine outcome updated by audited review; can also be rejected.
handoff_statusStringDownstream handoff acceptance state.
review_reasons, handoff_review_reasonsArrayCanonical and downstream blocking reason codes.
warningsArrayNon-blocking warnings.
lock_version, etagInteger and stringOptimistic concurrency state used by review requests.
acceptance_sourcemachine, human_review, or nullHow the effective result became accepted.
reviewed_atDate-time or nullTime of the latest recorded review decision.
machine_payloadProfile-defined object or nullImmutable normalized payload produced by the extraction run. It is null on a canonical failed result when no finalized usable profile payload exists, including after a provisional result is replaced during failed finalization. German energy full-invoice profile versions 2.0.0 and 2.0.1 otherwise return {packet,invoices}; each invoice's data contains party, relationship, supply-point, tariff, operator, meter, consumption, charge, tax, settlement, and payment entities. Embedded properties named evidence are omitted unless requested explicitly.
effective_payloadProfile-defined object or nullCurrent payload after append-only corrections and confirmations. For German energy it retains the same {packet,invoices} shape, and a field decision changes only the invoice named by invoice_ref. It is null when the canonical failed result has no finalized usable machine payload.
validation_summaryProfile-defined objectVersioned diagnostic validation snapshot. After review, use top-level outcomes/reasons and, for German energy, each effective_payload.invoices[] outcome plus invoices[].data.field_quality as the authoritative current state; machine-time counts can remain unchanged.
source_componentsArrayProfile-defined component and page groups used for provenance.
evidenceArrayFlattened page evidence; included only with include=evidence.
evidence_pagesArraySorted cited physical pages with available and a protected run-bound preview_url; included only with include=evidence. Unavailable artifacts use a null URL and never fall back to another run.
review_decisionsArrayImmutable decision history in application order.
exportsObjectProfile-registered downstream projections with profile-defined readiness. German energy full-invoice profile versions 2.0.0 and 2.0.1 return descriptors for canonical JSON and invoice-line CSV.
created_at, updated_atDate-time or nullResult creation and last-update timestamps.

Profile evidence object

FieldTypeDescription
entity_ref, field, field_statusStringProfile-defined entity and field supported by the evidence.
component_refStringSource component containing the evidence.
physical_pageIntegerOne-based physical PDF page.
printed_pageString or nullOptional page label printed by the supplier.
label, textString or null / StringOptional visible field label and required supporting span.
sourceStringNative text, embedded OCR, Tesseract OCR, or combined provenance.
matchStringExact, normalized, or manual match.
bboxObject or nullOptional page coordinates.

Profile review decision object

FieldTypeDescription
idIntegerReview decision ID.
actionconfirm, correct, or rejectImmutable decision action.
entity_ref, fieldString or nullStable field target for confirm/correct.
reasonString or nullReviewer explanation, required for rejection.
previous_value, corrected_valueAny JSON valueAudited values before and after a correction.
evidence_referenceEvidence or nullEvidence retained with the decision. Correction evidence has match=manual and reviewer_transcribed=true.
review_duration_secondsInteger or nullCaller-supplied workflow telemetry containing measured active human-review time for this decision. Null means unmeasured coverage, not zero; it is not wall-clock elapsed time.
reviewer_user_id, account_api_token_idInteger or nullApp user or account token that recorded the decision.
previous_effective_outcome, resulting_effective_outcomeStringOutcome transition caused by this decision.
previous_handoff_status, resulting_handoff_statusStringProjection transition caused by this decision.
expected_lock_version, resulting_lock_versionIntegerConcurrency state before and after the decision.
idempotency_key_prefixStringNon-secret prefix retained for retry diagnostics.
created_atDate-time or nullWhen the decision was recorded.

Preview object

FieldTypeDescription
idIntegerPreview ID used by the preview download endpoint.
filenameStringGenerated preview filename.
file_formatStringPreview file extension, for example png.
file_sizeIntegerPreview file size in bytes.
previewURLDownload URL for the preview binary.

Extraction field object

FieldTypeDescription
valueString, array, object, or nullNormalized 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.
candidatesArray or nullRaw or derived candidate values considered for the field. Use these in review UIs and troubleshooting workflows; they do not identify the origin of the selected value.
provenanceObject or nullPersisted origin of the selected value, with method, source, derived_from, and transforms. Null for legacy rows, null values, or all effective extraction fields projected from a profile result after any human-review decision, including fields not individually reviewed, because that projection no longer represents untouched automatic output. Candidate provenance is not included.

Error envelope

FieldTypeDescription
messageStringHuman-readable error message.
codeStringMachine-readable error code such as validation_failed or insufficient_credits.
request_idStringRequest identifier for diagnosing a request and correlating related events.
errorsObjectValidation field errors. Present on 422 responses.
retry_afterInteger or nullRetry delay in seconds. Present on some rate-limit responses.
available_creditsIntegerAvailable prepaid credits for self-service accounts or remaining committed units for commercial accounts. Present on insufficient-credit upload responses.
required_creditsIntegerBillable units required for the upload. Present on insufficient-credit upload responses.
documentDocument objectBlocked document created before the credit check failed. Present on insufficient-credit upload responses.
account_daily_document_limitIntegerSandbox account daily upload limit. Present on test-mode limit responses.
user_daily_document_limitIntegerSandbox user daily upload limit. Present on test-mode limit responses.
token_daily_document_limitIntegerSandbox token daily upload limit. Present on test-mode limit responses.
expected_lock_versionIntegerLock version submitted with a stale review decision. Present on extraction_version_conflict.
current_lock_versionIntegerCurrent profile-result version after a concurrency conflict.
conflict_reasonStringpayload_mismatch when a review idempotency key was reused with another decision.
document_idsArrayBatch documents that have no finalized profile result or are not accepted for handoff. Present on some profile_export_not_ready responses.