Integration
Markdown exportExternal API V1 Documentation
Convert invoices into validated e-invoices from your own systems: upload a PDF, DOCX, or TXT document — or structured ERP data — and download XRechnung, ZUGFeRD, EN 16931, UBL, or CII output once validation has passed. This page is the complete integration contract: access model, endpoints, error catalog, and limits.
Five REST endpoints turn PDF, DOCX, or TXT invoices — or structured ERP data — into validated XRechnung, ZUGFeRD, EN 16931, UBL, and CII e-invoices. Active Enterprise subscribers create keys directly; 100 shared Email/API conversions are included each month, then each conversion uses €0.50 in prepaid credits.
Overview
The API accepts multipart uploads, returns JSON responses, and uses standard HTTP status codes with Bearer authentication. Every conversion runs asynchronously: submit the document, poll the task, then download the result. A file is delivered only after validation has passed — there is no unvalidated output.
Send a PDF, DOCX, or TXT invoice document or structured invoice data to a conversion endpoint. Invoice-Converter starts one async task for extraction, validation, and artifact generation. The result endpoint returns a file only when the requested artifact is validated, checked, and ready; while processing it returns 202 TASK_NOT_READY, and blocking validation issues return 422 VALIDATION_FAILED.
Status: Enterprise access
Base path: /api/v1. Last synchronized 2026-08-07.
Key capabilities
- Upload endpoints for PDF invoices and structured invoice data
- AI-powered invoice data extraction
- Automated EN 16931 and KoSIT validation
- XRechnung, ZUGFeRD, EN16931, UBL, and CII output formats
- Async processing with polling; small invoices often take around 30 seconds, larger invoices up to 1-2 minutes
- Idempotent writes for safe retries
Start Enterprise API access
Every active Enterprise subscriber can create production API keys directly in the profile.
- Create an account and start Enterprise for €50/month or €420/year from the pricing page.
- Use the 100 shared Email/API conversions included each month; additional conversions use prepaid credits at €0.50 each.
- Create a live API key from the API access section in your profile.
- Run the first request with server-side credentials, then monitor usage and rotate keys from your profile.
Start Enterprise
Quickstart
Three API calls complete a conversion. The convert endpoint is served at /api/v1 and requires authentication.
POST /api/v1/invoices:convert
LiveConvert invoice document to structured e-invoice
POST /api/v1/invoices:convert-structured
LiveConvert structured data
GET /api/v1/tasks/{task_id}
LivePoll task status
Quickstart with curl
Replace $API_KEY with your live key and $TASK_ID with the task_id from the first response. The same three calls work for every output format.
curl -X POST "https://www.invoice-converter.com/api/v1/invoices:convert" \
-H "Authorization: Bearer $API_KEY" \
-H "Idempotency-Key: inv-2026-0001" \
-F "file=@invoice.pdf" \
-F "format=XRECHNUNG"curl "https://www.invoice-converter.com/api/v1/tasks/$TASK_ID" \
-H "Authorization: Bearer $API_KEY"curl -o invoice.xml \
"https://www.invoice-converter.com/api/v1/tasks/$TASK_ID/result?download=xml" \
-H "Authorization: Bearer $API_KEY"Base URL and API keys
- Production base URL:
https://www.invoice-converter.com/api/v1. - Live keys use the production host and the
icp_...prefix. - Run onboarding and validation requests with your live key before sending production volume.
- Treat keys as server-side secrets. Do not embed them in browser or mobile clients.
First successful request
Use this sequence as the minimum happy path after creating an API key.
- Upload:
POST /api/v1/invoices:convertwithAuthorization,Idempotency-Key,file=@invoice.pdf(or.docx/.txt), andformat=XRECHNUNG. - Poll with backoff: wait about
20 secondsafter the202, then callGET /api/v1/tasks/{task_id}on 20s, 30s, 45s, 60s, and 60s intervals until status iscompletedorfailed. Stay inside the10/minand120/hourstatus quota, and give up after about 16 minutes. - Download:
GET /api/v1/tasks/{task_id}/result?download=xmland storeX-Correlation-IDfor support tracing. - For ZUGFeRD PDF output, request
format=ZUGFERDon convert anddownload=pdfon result; hybrid PDF output requires a PDF source upload. - For structured input, call
POST /api/v1/invoices:convert-structuredwithpdf_file=@invoice.pdf,data_file=@invoice-data.json, and the targetformat. - Optionally send
client_referenceorexternal_invoice_idandsource_systemfor ERP reconciliation. - For split ERP exports of one invoice, repeat
data_file; for multiple invoices, start one task per invoice with its own idempotency key. - Store
result_artifactsfrom the status response to see whether XML/PDF artifacts are validated, cached, or still unavailable because of dependencies.
Common payload examples
XRECHNUNG: sendformat=XRECHNUNG.ZUGFERD: sendformat=ZUGFERD; usedownload=pdfon result for the hybrid PDF/A-3 output.Structured input: sendpdf_fileplus one or moredata_fileparts; accepted data formats are CSV, JSON, XML, XLSX, and TXT, with any supported target format. The data_file parts must contain all mandatory data; the PDF does not fill missing fields.Multiple invoices: submit separate convert requests and track each returnedtask_id; repeateddata_fileparts are only for split exports of the same invoice.UBL: sendformat=UBL; accepted profiles areXRECHNUNG,PEPPOL, andEN16931, defaulting toEN16931.CII: sendformat=CII; accepted profiles areXRECHNUNG,EN16931,ZUGFERD_EN16931, andZUGFERD_XRECHNUNG, defaulting toEN16931.formatxprofileis a closed table:XRECHNUNGaccepts[XRECHNUNG](defaultXRECHNUNG),EN16931accepts[EN16931](defaultEN16931),UBLaccepts[XRECHNUNG, PEPPOL, EN16931](defaultEN16931),CIIaccepts[XRECHNUNG, EN16931, ZUGFERD_EN16931, ZUGFERD_XRECHNUNG](defaultEN16931), andZUGFERDaccepts[ZUGFERD_EN16931, ZUGFERD_XRECHNUNG](defaultZUGFERD_EN16931). Profiles are matched case-insensitively;ZUGFERD,FACTURX,FACTUR-X, andFACTUR_XaliasZUGFERD_EN16931, andZUGFERD-XRECHNUNGaliasesZUGFERD_XRECHNUNG.
Required request headers
- Authorization: Bearer <api_key>
Auth rules
Every active Enterprise subscriber can create API keys from the profile and use them as Bearer tokens. The shared Email/API allowance includes 100 conversions per month; additional conversions use prepaid credits at €0.50 each.
- Keys are tenant-scoped live credentials for active Enterprise subscriptions. The current production prefix is
icp_.... - Create, rotate, and revoke API keys from your profile while Enterprise is active. Copy new keys immediately because plaintext keys are shown only once.
- Missing or invalid key returns
401. - Calls to
/api/v1receive anX-Correlation-IDautomatically when omitted. - Write calls require
Idempotency-Key; keep this value stable across retries. - Use server-to-server integration from your backend. Browser-origin access is restricted in production.
Idempotency contract
- Send an
Idempotency-Keyon every write call. - Idempotency keys must match
[A-Za-z0-9._:-]+and be at most 200 chars. - If you provide your own key, the same key + identical payload returns the cached response.
- Same key + different payload returns
409 IDEMPOTENCY_CONFLICT, which is not retryable; use a new key for a new payload. - A second request with the same key while the first is still processing returns
409 IDEMPOTENCY_IN_PROGRESS; retry the same key after a short delay. A stuck in-progress claim is reclaimed after15 minutes. - Once the original task is past its 24-hour retention, a replay returns
409 IDEMPOTENCY_REPLAY_EXPIRED; start a new conversion with a new key. - Idempotency records live for
24 hours, matching task retention.
Endpoint Reference
All endpoints are available under /api/v1. Timeouts surface as 504 and other temporary connectivity failures as 502; correlation IDs help support trace requests end-to-end.
POST /api/v1/invoices:convert
LiveUpload a PDF, DOCX, or TXT invoice document and start asynchronous conversion. Returns a task_id for polling. ZUGFeRD/Factur-X hybrid PDF downloads require a PDF source upload; DOCX/TXT sources should request XML results. Request: multipart/form-data; file (binary, required) — PDF, DOCX, or TXT invoice source document; legacy DOC/RTF, images, and other files are rejected; format (string, required) — target output format; see format matrix below; profile (string, optional, recommended for deterministic integrations) — explicit compliance profile, matched case-insensitively. Each format has a closed accepted set and one default: XRECHNUNG → [XRECHNUNG] (default XRECHNUNG); EN16931 → [EN16931] (default EN16931); UBL → [XRECHNUNG, PEPPOL, EN16931] (default EN16931); CII → [XRECHNUNG, EN16931, ZUGFERD_EN16931, ZUGFERD_XRECHNUNG] (default EN16931); ZUGFERD → [ZUGFERD_EN16931, ZUGFERD_XRECHNUNG] (default ZUGFERD_EN16931). ZUGFERD, FACTURX, FACTUR-X, and FACTUR_X alias ZUGFERD_EN16931; ZUGFERD-XRECHNUNG aliases ZUGFERD_XRECHNUNG. A value outside the accepted set returns 422 OUTPUT_PROFILE_CONFLICT; an unrecognized profile name returns 422 INVALID_PROFILE with details.allowed_profiles; jurisdiction (string, optional) — explicit ISO 3166-1 alpha-2 jurisdiction context used for validation/advisory checks; does not override profile; transaction_scope (string, optional) — explicit transaction scope context, such as B2G; applied to the queued task; delivery_channel (string, optional) — one of PEPPOL, DIRECT_XML, PORTAL, EMAIL_PDF, UNKNOWN; applied to the queued task; client_reference or external_invoice_id (string, optional) — tenant-side invoice/job reference returned on accepted uploads and task status responses; source_system (string, optional) — upstream ERP or billing system label returned on accepted uploads and task status responses; use_seller_master_data (boolean, optional) — when omitted, the tenant profile default applies; false ignores saved seller defaults for this request, true provides/uses seller defaults; seller_master_data (JSON object string, optional) — request-scoped seller defaults used only when use_seller_master_data=true; supported keys include business_name, address, tax, electronic address, contact, and payment fields (payment_means_code 30/42/58, payment_iban, payment_bic, payment_account_name, payment_terms_note); every supplied profile value replaces the corresponding extracted value, absent profile fields remain unchanged, and differences create non-blocking review warnings. Response: 202 Accepted.
POST /api/v1/invoices:convert-structured
LiveUpload a carrier PDF plus CSV, JSON, XML, XLSX, or TXT invoice data and start asynchronous structured-data conversion. The data_file parts are the only semantic source; the PDF does not fill missing invoice fields. For ZUGFeRD/Factur-X it is used as the carrier PDF, and for XML-oriented outputs it is retained as the submitted PDF artifact. Use one conversion request per invoice; repeat data_file only for split ERP exports that describe the same invoice. Request: multipart/form-data; pdf_file (binary, required) — carrier PDF used for ZUGFeRD/Factur-X embedding and retained for XML-oriented outputs; data_file (binary, required, repeatable) — CSV, JSON, XML, XLSX, or TXT invoice data used as the only semantic source; .xls, PDFs, and image files are rejected as data_file; repeat for split header/line exports of the same invoice; aliases data_files and data_files[] are accepted; structured data total size — max 2 MB across all data_file parts; format (string, required) — target output format; supports XRECHNUNG, ZUGFERD, EN16931, UBL, and CII; profile (string, optional, recommended for deterministic integrations) — explicit compliance profile, matched case-insensitively. Each format has a closed accepted set and one default: XRECHNUNG → [XRECHNUNG] (default XRECHNUNG); EN16931 → [EN16931] (default EN16931); UBL → [XRECHNUNG, PEPPOL, EN16931] (default EN16931); CII → [XRECHNUNG, EN16931, ZUGFERD_EN16931, ZUGFERD_XRECHNUNG] (default EN16931); ZUGFERD → [ZUGFERD_EN16931, ZUGFERD_XRECHNUNG] (default ZUGFERD_EN16931). A value outside the accepted set returns 422 OUTPUT_PROFILE_CONFLICT; an unrecognized profile name returns 422 INVALID_PROFILE with details.allowed_profiles; jurisdiction (string, optional) — explicit ISO 3166-1 alpha-2 jurisdiction context used for validation/advisory checks; does not override profile; transaction_scope (string, optional) — explicit transaction scope context, such as B2G; applied to the queued task; delivery_channel (string, optional) — one of PEPPOL, DIRECT_XML, PORTAL, EMAIL_PDF, UNKNOWN; applied to the queued task; client_reference or external_invoice_id (string, optional) — tenant-side invoice/job reference returned on accepted uploads and task status responses; source_system (string, optional) — upstream ERP or billing system label returned on accepted uploads and task status responses; use_seller_master_data (boolean, optional) — when omitted, the tenant profile default applies; false ignores saved seller defaults for this request, true provides/uses seller defaults; seller_master_data (JSON object string, optional) — request-scoped seller defaults used only when use_seller_master_data=true; supported keys include business_name, address, tax, electronic address, contact, and payment fields (payment_means_code 30/42/58, payment_iban, payment_bic, payment_account_name, payment_terms_note); every supplied profile value replaces the corresponding extracted value, absent profile fields remain unchanged, and differences create non-blocking review warnings. Response: 202 Accepted.
GET /api/v1/tasks/{task_id}
LivePoll the current status of a conversion task. Returns pending (accepted and queued, not started yet), processing, completed, or failed. Rate limit 10/min and 120/hour, which is the binding constraint for polling: wait about 20 seconds after the accepted 202 before the first call, then back off (20s, 30s, 45s, 60s, and 60s from there on) and stop on completed or failed. Completed tasks include result_artifacts diagnostics so clients can see which XML/PDF artifacts are available, cached, and validation-proven. Completed task payloads may include additive _processing_warnings and _validation_warnings entries with SOURCE_CONTEXT_* rule IDs when source evidence was unavailable, suspect, or truncated; treat them as review signals, not failures. When failed, the response includes an error field with the failure reason. Request: none (GET); task_id (path, required) — UUID returned by the convert endpoint; include_validation_report_html (query, optional) — true or false (default false); when true, the status response inlines the sanitized validation report HTML for the current strict artifact when available. Response: 200 OK.
GET /api/v1/tasks/{task_id}/result
LiveDownload the generated file (XML or PDF). Result syntax matches the original task format: XRECHNUNG/EN16931/UBL return UBL XML, CII/ZUGFERD return CII XML, and ZUGFERD + download=pdf returns a hybrid PDF/A-3. For other formats, download=pdf can return a rendered PDF; on a completed task download=xml is the expected-available artifact, not a guaranteed one. Repeated downloads may be served from cached generated artifacts when validation proof is still current. While processing, this endpoint returns a 202 carrying the standard error envelope ({"code":"TASK_NOT_READY","message":"Strict conversion is still processing. No validated artifact is available yet.","correlation_id":"<uuid>"}); blocking validation issues return 422 VALIDATION_FAILED, retryable dependency gaps return 503, terminal conversion failures return 500 TASK_FAILED with the reason in details.code, and artifact invariant failures return 500 INTERNAL_ARTIFACT_INVARIANT_FAILED, all with no file body. Successful downloads carry X-Correlation-ID, Content-Disposition, Cache-Control: no-store, X-Artifact-Sha256, X-Validation-Proof-Id, X-Artifact-Proof-Id, X-Artifact-State, X-Validation-State, X-Proof-Status, and X-Validator-Bundle-Id; X-Task-Id is not set on this endpoint. Rate limit 10/min and about 134/hour. Request: none (GET); task_id (path, required) — UUID returned by the convert endpoint; download (query, required) — xml or pdf. Response: 200 OK.
GET /api/v1/tasks/{task_id}/validation-report
LiveDownload the validation report tied to the current validated result artifact. The report is available only after strict conversion has produced a cached artifact with current validation proof, and returns 404 when no report is bound to the delivered artifact. A 202 carries the standard TASK_NOT_READY error envelope, not a file body. Successful responses carry X-Correlation-ID, Content-Disposition, Cache-Control: no-store, X-Artifact-Sha256, X-Validation-Proof-Id, X-Artifact-Proof-Id, X-Artifact-State, X-Validation-State, X-Proof-Status, X-Validator-Bundle-Id, plus X-Task-Id, X-Validation-Report-Proof-Id, X-Validation-Report-Content-Type, X-Validation-Report-Format, X-Validation-Report-Source, and X-Report-Source-Artifact-Format. Those artifact-level diagnostics describe the validated result artifact the report covers, not the returned report bytes: X-Artifact-Sha256 is the SHA-256 of that source artifact and must not be used to checksum the downloaded report, while X-Validation-Report-Proof-Id identifies the proof that supplied the report payload. Rate limit 10/min and 120/hour. Request: none (GET); task_id (path, required) — UUID returned by the convert endpoint; download (query, optional) — html or xml. Response: 200 OK.
Output format matrix
| Format | Syntax | Version / Profile | Content-Type | Extension |
|---|---|---|---|---|
| XRECHNUNG | UBL 2.1 XML | XRechnung 3.0.2 | application/xml | .xml |
| ZUGFERD | CII XML (download=xml) / hybrid PDF/A-3 (download=pdf) | ZUGFeRD 2.3.2 / Factur-X 1.07.2 | application/xml or application/pdf | .xml / .pdf |
| EN16931 | UBL 2.1 XML | EN 16931 | application/xml | .xml |
| UBL | UBL 2.1 XML | OASIS UBL 2.1 | application/xml | .xml |
| CII | UN/CEFACT CII XML | D16B | application/xml | .xml |
Error Contract
| Code | HTTP | Retryable | Notes |
|---|---|---|---|
| AUTHENTICATION_REQUIRED | 401 | No | Missing/empty bearer token |
| INVALID_API_KEY | 401 | No | API key not found/revoked/expired |
| API_NOT_ENABLED_FOR_TENANT | 403 | No | Key is valid but External API access is not enabled for the account; contact support instead of retrying |
| INSUFFICIENT_API_CREDITS | 402 | No | Included monthly allowance plus prepaid API credits could not cover the request. Two details shapes: prepaid (remaining, minimum_purchase 100) and included allowance (included_remaining, credit_remaining, shortfall, minimum_purchase 100). Parse on code and read whichever keys are present |
| IDEMPOTENCY_KEY_REQUIRED | 400 | No | Write endpoint called without Idempotency-Key |
| INVALID_IDEMPOTENCY_KEY | 400 | No | Idempotency key must match [A-Za-z0-9._:-]+ and be at most 200 characters |
| IDEMPOTENCY_CONFLICT | 409 | No | The key was already used with a different payload, or the idempotent claim could not be started; use a new key for a new payload |
| IDEMPOTENCY_IN_PROGRESS | 409 | Yes | The first request with this key is still processing; retry the SAME key after a short delay. A stuck in-progress claim is reclaimed after 15 minutes |
| IDEMPOTENCY_REPLAY_EXPIRED | 409 | No | The original task is past its 24-hour retention and cannot be recovered; start a new conversion with a new key |
| FORMAT_REQUIRED | 400 | No | Conversion request missing required format |
| INVALID_FORMAT | 422 | No | Unsupported conversion format |
| CLIENT_REFERENCE_CONFLICT | 400 | No | client_reference and external_invoice_id differ |
| INVALID_CLIENT_METADATA | 400 | No | client_reference, external_invoice_id, or source_system exceeds its length limit or contains control characters |
| INVALID_SELLER_MASTER_DATA | 400 | No | use_seller_master_data or seller_master_data is not parseable or fails field validation |
| METHOD_NOT_ALLOWED | 405 | No | Conversion paths accept POST only and task paths accept GET only; the response includes Allow: POST, OPTIONS (conversion) or Allow: GET, OPTIONS (task) |
| DOWNLOAD_FORMAT_REQUIRED | 400 | No | Task result request missing required download query |
| INVALID_DOWNLOAD_FORMAT | 400 | No | Task result download query must be xml or pdf |
| AUTH_SERVICE_UNAVAILABLE | 503 | Yes | Auth backend unavailable |
| RATE_LIMIT_SERVICE_UNAVAILABLE | 503 | Yes | The rate-limit service could not be reached; retry with backoff |
| PLAN_TIER_CHECK_FAILED | 503 | Yes | Plan/API access could not be verified right now; retry with backoff |
| API_CREDIT_SERVICE_UNAVAILABLE | 503 | Yes | Prepaid API credit or channel allowance verification is temporarily unavailable on conversion uploads |
| RATE_LIMITED | 429 | Yes | Respect Retry-After. Retry-After, X-RateLimit-Limit-Minute, and X-RateLimit-Limit-Hour are returned on 429 responses only; the body carries details.minute_count, details.hour_count, details.limit_minute, and details.limit_hour |
| BAD_REQUEST | 400 | No | Invalid JSON or invalid UUID path parameter |
| INVALID_QUERY_PARAMETER | 400 | No | include_validation_report_html must be true or false |
| PAYLOAD_TOO_LARGE | 413 | No | Over upload size limit |
| INVALID_UPLOAD | 400 | No | Upload read/parsing failure |
| UPLOAD_FAILED | 422 | No | An optional context field (jurisdiction, transaction_scope, delivery_channel) held an unrecognized value; the allowed values are in the message |
| INVALID_PROFILE | 422 | No | The value is not a recognized profile name; details.allowed_profiles lists the accepted set |
| TASK_NOT_READY | 202 | Yes | Poll again for async completion |
| TASK_NOT_FOUND | 404 | No | The task is unknown, not owned by the tenant, or past its 24-hour retention after reaching a terminal state |
| VALIDATION_FAILED | 422 | No | Blocking validation issues remain, including strict ZUGFeRD prerequisite failures and unresolved blocking_source_conflict items; correct invoice data before retrying |
| AUTHORITATIVE_VALIDATION_UNAVAILABLE | 503 | Yes | Authoritative validation, proof persistence, or hybrid-generation dependency unavailable; retry later |
| TASK_STATUS_FAILED | 4xx/5xx | Conditional | Retry if transient service condition |
| TASK_RESULT_FAILED | 4xx/5xx | Conditional | Retry if transient service condition |
| TASK_FAILED | 500 | Conditional | Conversion failure on the result endpoint. Read details.code and details.retryable: MULTIPLE_INVOICES_IN_DOCUMENT, NO_INVOICE_DETECTED, INSUFFICIENT_INVOICE_SIGNAL, SCHEMA_PARSE_FAILED, and ARTIFACT_PARITY_FAILED are terminal; PROVIDER_ERROR and any unrecognized details.code follow details.retryable, and details.retryable=true means start a new conversion with a new Idempotency-Key instead of re-polling the same task. The failed conversion does not consume a billing unit |
| MULTIPLE_INVOICES_IN_DOCUMENT | 500 (details code) | No | Terminal: the source document contains more than one invoice, corroborated by distinct invoice identifiers or a reported invoice count. details.retryable and details.can_review are false. Split the PDF into one file per invoice and start a separate conversion for each invoice |
| NO_INVOICE_DETECTED | 500 (details code) | No | Terminal: the document does not look like an invoice. Route to human handling |
| INSUFFICIENT_INVOICE_SIGNAL | 500 (details code) | No | Terminal: not enough invoice data for reliable extraction. Supply a better source document or use structured conversion |
| SCHEMA_PARSE_FAILED | 500 (details code) | No | Terminal for that input: extraction returned a payload that failed schema parsing. Start a new conversion; escalate if it repeats on the same document |
| PROVIDER_ERROR | 500 (details code) | Conditional | Extraction-provider failure; details.retryable is authoritative. When details.classification is provider_context_too_large, use a smaller source document |
| XML_GENERATION_FAILED | 500 | Yes | Transient XML generation failure or timeout |
| PDF_GENERATION_FAILED | 500 | Yes | Transient PDF generation failure or timeout |
| ARTIFACT_GENERATION_RERUN_REQUIRED | 503 | No | Strict artifact generation failed after server-side retries; start a new conversion after the dependency recovers |
| EXTRACTION_INCOMPLETE_GROUP_FAILURE | 503 | No | Extraction finished with one or more failed field groups. The same task will not recover: start a NEW conversion. details carries type "dependency", dependency "parallel_extraction", stage "extraction", retryable true, same_task_retryable false, recovery "start_new_conversion", and failed_groups |
| ARTIFACT_GENERATION_FAILED | 503 (details code) | No | Recorded on failed tasks for retryable strict issuance failures; result downloads surface 503 ARTIFACT_GENERATION_RERUN_REQUIRED with this code in details |
| ARTIFACT_PARITY_FAILED | 500 (details code) | No | Reported in the details of 500 TASK_FAILED when the strict artifact does not match the final reviewed invoice data; escalate with the correlation ID |
| INTERNAL_ARTIFACT_INVARIANT_FAILED | 500 | No | Completed strict task has no safe stored artifact for the requested download; escalate with the correlation ID |
| PROFILE_MISMATCH | 422 | No | Requested profile does not match the CustomizationID of the stored result on result download |
| ZUGFERD_SOURCE_PDF_INCOMPATIBLE | 422 | No | Strict hybrid PDF generation cannot embed XML into the uploaded source PDF |
| ZUGFERD_SOURCE_PDF_REQUIRED | 422 | No | download=pdf for ZUGFERD requires a PDF source upload (DOCX/TXT sources cannot carry the hybrid PDF); request download=xml instead |
| VALIDATION_REPORT_NOT_FOUND | 404 | No | No validation report is bound to the current delivered artifact proof |
| VALIDATION_REPORT_FAILED | 4xx/5xx | Conditional | Validation report retrieval failed; retry only transient 5xx cases |
| OUTPUT_PROFILE_REQUIRED | 422 | No | A generic output contract requires an explicit profile when no unambiguous default can be determined |
| OUTPUT_PROFILE_CONFLICT | 422 | No | Profile contradicts the selected output format or explicit variant |
| PROXY_ERROR | 502/504 | Yes | Transport failure rather than a conversion outcome: proxy/upstream failure (504 for timeout). Retry with backoff and the same idempotency key |
Common errors and what to do
- Retry with backoff:
429,502,504,503with a retryable code, and transient500s that are notTASK_FAILEDorINTERNAL_ARTIFACT_INVARIANT_FAILED.500 TASK_FAILEDis retryable only whendetails.retryableistrue, and then only as a new conversion. - Do not retry:
400,401,402,403,404,405,413,422,409 IDEMPOTENCY_CONFLICT,409 IDEMPOTENCY_REPLAY_EXPIRED,500 TASK_FAILEDwhendetails.retryableis nottrue, and500 INTERNAL_ARTIFACT_INVARIANT_FAILED. - Fix request or source data:
400,413,422. - Fix access or credentials:
401 INVALID_API_KEY.403 API_NOT_ENABLED_FOR_TENANTmeans the key is valid but External API access is not enabled for the account — contact support. - Confirm the included monthly allowance or buy a prepaid API-credit package:
402 INSUFFICIENT_API_CREDITS. Read whicheverdetailskeys are present (remainingfor prepaid accounts, orincluded_remaining/credit_remaining/shortfallwhen an included allowance is enforced). - Keep polling later:
202 TASK_NOT_READY. - For
500 TASK_FAILED, readdetails.codeanddetails.retryable.MULTIPLE_INVOICES_IN_DOCUMENT,NO_INVOICE_DETECTED,INSUFFICIENT_INVOICE_SIGNAL,SCHEMA_PARSE_FAILED, andARTIFACT_PARITY_FAILEDare terminal;PROVIDER_ERRORand any unrecognized code followdetails.retryable, andtruemeans start a NEW conversion instead of re-polling the same task. A failed conversion does not consume a billing unit. - For
422 VALIDATION_FAILED, show the returned field, rule ID, and remediation to a human reviewer before retrying with corrected invoice data. - For
503 AUTHORITATIVE_VALIDATION_UNAVAILABLE, fetch the same task result later; no unverified artifact was delivered. For503 ARTIFACT_GENERATION_RERUN_REQUIREDand503 EXTRACTION_INCOMPLETE_GROUP_FAILURE, start a new conversion instead. 502and504 PROXY_ERRORare transport failures rather than conversion outcomes; retry with backoff and the same idempotency key.
Rate & payload limits
Per-key rate limits and payload size constraints are enforced for all API calls. Rejected conversions do not consume prepaid API credits; rate limits are calculated separately per endpoint.
- Endpoint-aware limits are cost-weighted, and each endpoint has its own bucket so polling cannot starve conversion throughput. Defaults per API key:
POST /invoices:convertandPOST /invoices:convert-structured30/minand500/hour;GET /tasks/{task_id}10/minand120/hour;GET /tasks/{task_id}/result10/minand about134/hour;GET /tasks/{task_id}/validation-report10/minand120/hour. - Quota headers are returned on
429 RATE_LIMITEDresponses only. Successful responses do not carry quota headers, so treat the table above as the working contract and read exact effective values from a429. - The status bucket is the binding constraint for polling: wait about
20 secondsafter the accepted202before the first status call, then back off (20s, 30s, 45s, 60s, and 60s from there on) and stop oncompletedorfailed. Do not poll every 10 seconds; a single task polled that way burns its whole hourly budget in 20 minutes. - Source document upload max size:
20 MBfor PDF, DOCX, or TXT files. - Structured data upload max size:
2 MBtotal across alldata_fileparts. - JSON payload max size:
1 MB 429responses includeRetry-After,X-RateLimit-Limit-Minute, andX-RateLimit-Limit-Hour, plusdetails.minute_count,details.hour_count,details.limit_minute, anddetails.limit_hour.
Retry guidance
- Use exponential backoff with jitter, and reuse the same
Idempotency-Keyon every retry of a write request. - Branch on the machine-readable
code— and ondetails.codeplusdetails.retryablefor500 TASK_FAILED— never on the HTTP status alone. A500is not automatically retryable in this API. - Safe to retry:
429,502,504,503with a retryable code, transient500s that are NOTTASK_FAILEDorINTERNAL_ARTIFACT_INVARIANT_FAILED, and500 TASK_FAILEDwhendetails.retryableistrue(transient provider failures: rate limiting, timeout, transport error) — retry that case as a NEW conversion with a newIdempotency-Key, not by re-polling the same task. - Never retry:
400,401,402,403,404,405,413,422,409 IDEMPOTENCY_CONFLICT,409 IDEMPOTENCY_REPLAY_EXPIRED,500 TASK_FAILEDwhendetails.retryableis nottrue, and500 INTERNAL_ARTIFACT_INVARIANT_FAILED. A terminally failed conversion does not consume a billing unit. 409 IDEMPOTENCY_IN_PROGRESSis retryable with the SAME key after a short delay; a stuck in-progress claim is reclaimed after 15 minutes.503 ARTIFACT_GENERATION_RERUN_REQUIREDand503 EXTRACTION_INCOMPLETE_GROUP_FAILUREneed a NEW conversion rather than a retry of the same task.
Task lifecycle & retention
- A task and its stored artifacts are retained for
24 hoursafter the task reaches a terminal state (completedorfailed), then purged. After purge, status, result, and validation-report requests return404 TASK_NOT_FOUND. - There is no fixed conversion timeout. A task is failed after a
5 minutestall window with no stage or progress update, or once total processing exceeds the absolute15 minutehard cap. - Set your client-side timeout to about
16 minutesfrom the accepted202. Most conversions finish in well under two minutes. - Idempotency records live for
24 hours, matching task retention. A request stuck in progress is reclaimed after15 minutes. - Rate-limit counters reset on a rolling window.
Support model
- Business-hours support on commercially reasonable efforts.
- No formal SLA, service credit, or response-time commitment unless agreed in an order form.
Changelog
Recent externally visible API changes.
2026-08-07
Documentation release 1.13.0: Enterprise is available through direct checkout for EUR 50 per month or EUR 420 per year. Every active Enterprise subscription includes 100 conversion units per month shared by Email Import and External API V1; additional units use prepaid credits at EUR 0.50 each. Email Import and External API V1 no longer require manual account approval. Email Import still requires profile enablement and a verified sender.
2026-07-29
Documentation release 1.12.0. No runtime behavior changed on this date; these entries document behavior that was already live. MULTIPLE_INVOICES_IN_DOCUMENT is now published in the error catalog. It is returned as 500 TASK_FAILED with details.code=MULTIPLE_INVOICES_IN_DOCUMENT, details.retryable=false, and details.can_review=false. It is terminal: split the source into one document per invoice. The failed attempt does not consume a billing unit. Retry guidance corrected: a 500 is not automatically retryable. Branch on code, and on details.code plus details.retryable for 500 TASK_FAILED, instead of on the HTTP status alone. Treat 500 TASK_FAILED as terminal unless details.retryable is true (transient provider failures such as rate limiting, timeouts, and transport errors), in which case start a new conversion with a new Idempotency-Key rather than re-polling the same task. Never retry 500 INTERNAL_ARTIFACT_INVARIANT_FAILED. Billing is documented as included-allowance-then-credits, so 402 INSUFFICIENT_API_CREDITS has two details shapes: prepaid (remaining, minimum_purchase) and included allowance (included_remaining, credit_remaining, shortfall, minimum_purchase). Newly documented runtime error codes that were already being returned: 403 API_NOT_ENABLED_FOR_TENANT, 409 IDEMPOTENCY_IN_PROGRESS, 409 IDEMPOTENCY_REPLAY_EXPIRED, 422 INVALID_PROFILE, 422 UPLOAD_FAILED, 400 INVALID_IDEMPOTENCY_KEY, 503 PLAN_TIER_CHECK_FAILED, 503 RATE_LIMIT_SERVICE_UNAVAILABLE, and 503 EXTRACTION_INCOMPLETE_GROUP_FAILURE. The 409 class is split by retry semantics: IDEMPOTENCY_IN_PROGRESS is retryable with the same key after a short delay, while IDEMPOTENCY_CONFLICT and IDEMPOTENCY_REPLAY_EXPIRED require a new key. Validation-report header passthrough fixed, and X-Validation-Report-Format, X-Validation-Report-Source, and X-Report-Source-Artifact-Format are now published. On the validation-report endpoint, X-Artifact-Sha256 is the SHA-256 of the result artifact the report validates, not of the returned report bytes; X-Validation-Report-Proof-Id identifies the proof that supplied the report payload. Added retention and lifecycle statements: 24-hour task/artifact retention after a terminal state, 24-hour idempotency records, a 15-minute in-progress reclaim, a 5-minute stall window, a 15-minute hard cap, and a recommended ~16-minute client timeout. Rate limits and polling guidance replaced with per-endpoint numbers, including the previously missing validation-report bucket. Quota headers are returned on 429 responses only, and the former "poll every 10-15 seconds" advice is replaced with a first-poll delay plus backoff. Published a closed format x profile compatibility table with the default profile for each format, and corrected download=xml on a completed task from "always available" to expected-available. Corrected 405 METHOD_NOT_ALLOWED to return Allow: POST, OPTIONS on conversion paths and Allow: GET, OPTIONS on task paths, and corrected 422 PROFILE_MISMATCH: there is no profile query parameter, and the fix is to start a new conversion with an aligned profile.
2026-07-28
External API conversions now run the same document-scope gate as the interactive product, including on forced extraction modes that previously skipped it. A source document whose extraction reports multiple invoices, corroborated by two or more distinct invoice identifiers or by an invoice count with no identifiers, now fails terminally with MULTIPLE_INVOICES_IN_DOCUMENT. The failure is not retryable: split the source into one document per invoice and submit each separately. An uncorroborated multiple_invoices verdict no longer fails the conversion. On strict API issuance it returns 422 VALIDATION_FAILED with a blocking_source_conflict issue entry, which covers duplicate renditions such as an original plus its copy, a reprint, or a second-language rendition.
2026-07-26
When seller master data is enabled, every supplied profile value replaces the corresponding extracted seller or payment value. Fields absent from the profile remain unchanged. Source differences are non-blocking review warnings.
2026-07-25
Superseded by the 2026-07-26 entry above. Seller master data filled missing seller and payment fields only; explicit invoice values remained unchanged, and material profile/source conflicts blocked strict issuance until review. Since 2026-07-26 every supplied profile value replaces the corresponding extracted value instead.
2026-07-10
Documentation backfill; no runtime behavior change. The error catalog now documents the previously undocumented runtime error codes, including API_CREDIT_SERVICE_UNAVAILABLE, TASK_NOT_FOUND, INVALID_CLIENT_METADATA, INVALID_SELLER_MASTER_DATA, PROFILE_MISMATCH, ZUGFERD_SOURCE_PDF_REQUIRED, VALIDATION_REPORT_NOT_FOUND, VALIDATION_REPORT_FAILED, INVALID_QUERY_PARAMETER, and METHOD_NOT_ALLOWED. Clients that parse error responses by the machine-readable code field need no changes; clients that switch on a fixed list of codes should add the newly documented values. Corrected changelog dates: DOCX/TXT source support shipped on 2026-06-30, not 2026-07-06.
2026-07-06
Completed task payloads may include additive _processing_warnings and _validation_warnings entries with SOURCE_CONTEXT_* rule IDs when source evidence was unavailable, suspect, or truncated before extraction. Treat SOURCE_CONTEXT_* entries as review signals for customer-side exception handling; strict artifact downloads remain governed by validation proof and artifact checks.
2026-07-03
Strict ZUGFeRD prerequisite failures (missing mandatory fields for hybrid generation) now fail as 422 VALIDATION_FAILED with the blocking rule IDs instead of a retryable 503; route these to a data-correction flow, not a retry loop. For XML-only formats (XRECHNUNG, EN16931, UBL, CII), the PDF rendering is now a best-effort convenience artifact: download=xml stays authoritative on completed tasks while download=pdf can be unavailable if the rendering failed after XML issuance. Conversions with unresolved blocking source conflicts now fail as 422 VALIDATION_FAILED with blocking_source_conflict issue entries instead of issuing an artifact.
2026-06-30
POST /api/v1/invoices:convert now accepts PDF, DOCX, and TXT invoice source documents in the file field. Legacy DOC, RTF, image, and other unsupported source files are rejected before conversion starts. ZUGFeRD/Factur-X hybrid PDF downloads still require a PDF source upload; use XML downloads for DOCX/TXT source conversions. Added optional include_validation_report_html=true on GET /api/v1/tasks/{task_id} to inline the sanitized validation report HTML when available. Conversion uploads now accept optional use_seller_master_data and seller_master_data fields on both endpoints so approved tenants can opt into stored or request-scoped seller defaults.
2026-06-29
Added GET /api/v1/tasks/{task_id}/validation-report?download=html|xml to retrieve the validation report tied to the current strict result artifact proof. Validation report responses expose task ID, artifact SHA-256, validation proof ID, report proof ID, report content type, and correlation ID headers.
2026-06-10
Invoice data you submit is now the source of truth during hybrid ZUGFeRD generation; the server no longer overrides submitted quantities or totals with values recovered from the uploaded PDF. Deterministic cleanup and tax normalization still apply. Long-running conversions are no longer failed at a fixed 5-minute processing timeout. Tasks now fail only when they stop making progress for the stall window or exceed the absolute 15-minute hard cap, and extraction retries are bounded by a total wall-clock budget.
2026-06-09
Clarified that usage-tracking persistence failures are fail-open for response delivery: ready validated artifact responses are not denied, no extra prepaid API credit is consumed, and failed usage events are queued internally for reconciliation.
2026-06-02
External API access is now documented as approved gated access rather than ungated key creation. Clarified that no formal SLA, service credit, or contractual penalty applies unless agreed in an order form. format is now required on both conversion endpoints; missing values return 400 FORMAT_REQUIRED and unsupported values return 422 INVALID_FORMAT. download is now required on task-result requests; missing values return 400 DOWNLOAD_FORMAT_REQUIRED and unsupported values return 400 INVALID_DOWNLOAD_FORMAT. Conversion uploads now accept client_reference/external_invoice_id and source_system for customer-side reconciliation. Accepted conversion and task-status responses now include status_url, primary_result_format, primary_result_url, and supplied reconciliation fields.
2026-06-01
Structured conversion now accepts all public output formats: XRECHNUNG, ZUGFeRD, EN16931, UBL, and CII. Structured conversion now accepts repeatable data_file parts plus data_files and data_files[] aliases for split ERP exports. Structured multi-file bundles must describe exactly one invoice and fail fast on conflicting or missing bundle invoice IDs. Clarified that multiple invoice documents should be submitted as separate conversion tasks, each with its own idempotency key.
2026-05-27
Added POST /api/v1/invoices:convert-structured for carrier-PDF plus CSV/JSON/XML/XLSX/TXT structured-data conversion across supported output formats. Documented that structured data is the only semantic source on this endpoint; the PDF is used for hybrid embedding. Updated OpenAPI and Postman artifacts for structured conversion.
2026-05-26
Strict XML and hybrid ZUGFeRD PDF result artifacts now carry internal artifact parity metadata; public clients should use task-status result_artifacts for artifact readiness and validation-state diagnostics. Updated the documented production base URL to https://www.invoice-converter.com/api/v1.
2026-05-19
Task-result downloads are now strict retrieval-only: no XML/PDF generation, AI call, repair, or validation runs on GET /api/v1/tasks/{task_id}/result. Strict tasks complete only after a validated artifact is stored; completed tasks without a current proof fail closed with 500 INTERNAL_ARTIFACT_INVARIANT_FAILED. External API conversions are permanently pinned to strict issuance: no draft output, no warning override, and artifact validation always required. Conversions run on a dedicated processing tier chosen by the service. Added additive result_artifacts diagnostics to the task status response, and documented the canonical delivery_channel values PEPPOL, DIRECT_XML, PORTAL, EMAIL_PDF, and UNKNOWN. Documented 422 ZUGFERD_SOURCE_PDF_INCOMPATIBLE, and clarified that missing XRechnung/Peppol target metadata such as BT-10, BT-49, and BG-16 is a validation correction flow rather than a transport retry.
2026-05-08
Added prepaid External API credits for non-Enterprise tenants. Documented 402 INSUFFICIENT_API_CREDITS for approved tenants without Enterprise order-form billing or prepaid credits. Confirmed idempotent replays do not consume additional API credits. Clarified that External API V1 model routing is managed server-side while profile and delivery context stay caller-controlled.
2026-03-28
Task status responses expose artifact readiness diagnostics for XML/PDF result availability. Documented that strict result downloads only return files after server-side artifact gates pass.
2026-03-26
Successful task-result downloads are backed by a server-side validation proof for the returned bytes. The result endpoint returns 503 AUTHORITATIVE_VALIDATION_UNAVAILABLE when required authoritative validation, proof persistence, or hybrid-generation dependencies are unavailable. Cached task-result downloads are reused only when the cached artifact still has a persisted validation proof.
2026-03-06
Made task-result downloads format-faithful for CII and ZUGFERD outputs. Added cached result artifact reuse for repeated XML/PDF downloads of the same task. Aligned polling quotas with endpoint-scoped weighted rate-limit buckets.
2026-02-23
Added clearer, consistent API error responses across all endpoints. Expanded convert options and documented XML/PDF download behavior for task results. Improved retry safety with stricter idempotency requirements and validation. Updated OpenAPI/Postman artifacts to match current API behavior.
Delivery Artifacts
Download machine-readable integration artifacts for the Developer API.
Use Postman and OpenAPI
- Import the Postman collection and set the
base_url,api_key, andidempotency_keycollection variables. - Run the collection in order: convert, poll status, then fetch result.
- Use the OpenAPI JSON to generate typed clients, but keep file upload, polling, and binary result handling covered by integration tests.
- Record
X-Correlation-IDin logs so support can trace requests end-to-end.
Send Technical Feedback
Share implementation questions, risks, and required contract changes with our team.