# Invoice Converter External API

Version: 1.28.0 · Last updated: 2026-11-03 · Base URL: `https://www.invoice-converter.com/api/v1`

Convert invoice documents (PDF, DOCX, TXT) or structured invoice data from your ERP, billing, or CRM system into validated XRechnung, ZUGFeRD/Factur-X, EN 16931, UBL, or CII e-invoices.

**Base URL** `https://www.invoice-converter.com/api/v1` · **Auth** `Authorization: Bearer <api_key>` · **Contract** OpenAPI 3.1 (this document)

This page is the complete documentation: the guide sections below explain the flow, and the endpoint and schema sections list every field, value, and response.

## Overview

The API converts one invoice per request into a validated e-invoice. Every conversion is asynchronous:

1. **Convert.** `POST /invoices:convert` (PDF, DOCX, or TXT document) or `POST /invoices:convert-structured` (your invoice data plus a carrier PDF). Response: `202` with `task_id`.
2. **Poll.** `GET /tasks/{task_id}` until `status` is `completed` or `failed`.
3. **Download.** `GET /tasks/{task_id}/result?download=xml|pdf`. Optional: `GET /tasks/{task_id}/validation-report?download=html|xml`.

A task completes only when the artifact passed validation for the requested profile. There is no draft or warning-override output. V1 has no webhooks, no batch endpoint, and no task-list endpoint.

| Endpoint | Purpose | Rate limit per API key |
|---|---|---|
| `POST /invoices:convert` | Convert a document | 30/min, 500/h |
| `POST /invoices:convert-structured` | Convert structured data | 30/min, 500/h |
| `GET /tasks/{task_id}` | Task status | 60/min, 1,500/h |
| `GET /tasks/{task_id}/result` | Download the artifact | 60/min, 1,000/h |
| `GET /tasks/{task_id}/validation-report` | Download the validation report | 30/min, 500/h |

## Authentication and access

- Header: `Authorization: Bearer <api_key>`.
- Keys are tenant-scoped live credentials with the prefix `icp_...`. Create, rotate, and revoke them on the profile page with an active Enterprise subscription. No separate approval is necessary.
- Keep keys on your server. Never put them in browser or mobile code, logs, or tickets.
- Missing token: `401 AUTHENTICATION_REQUIRED`. Unknown or revoked key: `401 INVALID_API_KEY`. Valid key without API access: `403 API_NOT_ENABLED_FOR_TENANT`. Key of a deleted account: `410 ACCOUNT_DELETED` (the deletion is permanent; do not retry).

## Quickstart

```bash
# 1. Convert
curl -X POST 'https://www.invoice-converter.com/api/v1/invoices:convert' \
  -H 'Authorization: Bearer <api_key>' \
  -H 'Idempotency-Key: erp-inv-2026-0001' \
  -F 'file=@invoice.pdf' \
  -F 'format=XRECHNUNG' \
  -F 'client_reference=ERP-2026-0001'

# 2. Poll (first call about 20 s later)
curl 'https://www.invoice-converter.com/api/v1/tasks/<task_id>' \
  -H 'Authorization: Bearer <api_key>'

# 3. Download
download_tmp=$(mktemp) || exit 1
download_meta=$(curl --silent --show-error --output "$download_tmp" \
  --write-out '%{http_code} %{content_type}' --dump-header headers.txt \
  'https://www.invoice-converter.com/api/v1/tasks/<task_id>/result?download=xml' \
  -H 'Authorization: Bearer <api_key>') || { rm -f "$download_tmp"; exit 1; }
case "$download_meta" in
  '200 application/xml'|'200 application/xml;'*|'200 text/xml'|'200 text/xml;'*)
    mv "$download_tmp" invoice.xml ;;
  *)
    rm -f "$download_tmp"
    printf 'Download not saved (%s). Continue polling on 202.\n' "$download_meta" >&2
    exit 1 ;;
esac
```

The `202` body contains `task_id`, `status` (`pending` or `processing`), `status_url`, and `primary_result_url`. Branch on `status`, not on `message`. Store `X-Correlation-ID` from every response; support needs it. A completed status response (abridged):

```json
{
  "task_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "progress": 100,
  "created_at": "2026-09-30T08:00:00+00:00",
  "completed_at": "2026-09-30T08:01:12+00:00",
  "error": null,
  "client_reference": "ERP-2026-0001",
  "primary_result_url": "/api/v1/tasks/550e8400-e29b-41d4-a716-446655440000/result?download=xml",
  "result_artifacts": {
    "xml": { "state": "cached", "artifact_state": "compliant", "validation_state": "passed" }
  }
}
```

For `failed`, `error` holds a summary (string or object); call `/result` for the typed error.

## Formats and profiles

`format` is required and selects the syntax and container. `profile` is optional and selects the rule set. If you omit `profile`, the default for the format applies.

| `format` | Accepted `profile` | Default | `download=xml` | `download=pdf` |
|---|---|---|---|---|
| `XRECHNUNG` | `XRECHNUNG` | `XRECHNUNG` | UBL | rendered PDF (best effort) |
| `EN16931` | `EN16931` | `EN16931` | UBL | rendered PDF (best effort) |
| `UBL` | `XRECHNUNG`, `PEPPOL`, `EN16931` | `EN16931` | UBL | rendered PDF (best effort) |
| `CII` | `XRECHNUNG`, `EN16931`, `ZUGFERD_EN16931`, `ZUGFERD_FACTURX_EXTENDED`, `ZUGFERD_XRECHNUNG` | `EN16931` | CII | rendered PDF (best effort) |
| `ZUGFERD` | `ZUGFERD_EN16931`, `ZUGFERD_FACTURX_EXTENDED`, `ZUGFERD_XRECHNUNG` | `ZUGFERD_EN16931` | CII | hybrid ZUGFeRD/Factur-X PDF |

- `format` and `profile` are case-insensitive. Aliases: `EXTENDED` → `ZUGFERD_FACTURX_EXTENDED`; `ZUGFERD`, `FACTURX`, `FACTUR-X`, `FACTUR_X` → `ZUGFERD_EN16931`.
- A profile not listed for the format: `422 OUTPUT_PROFILE_CONFLICT`. An unknown profile name: `422 INVALID_PROFILE` with `details.allowed_profiles`.
- For XML formats, `download=xml` is the primary artifact. The PDF rendering is a convenience and can be unavailable.
- `format=ZUGFERD` needs a PDF source. A DOCX or TXT upload is rejected at upload time with `422 ZUGFERD_SOURCE_PDF_REQUIRED`.
- `jurisdiction` (ISO 3166-1 alpha-2), `transaction_scope` (`B2B`, `B2G`, `B2C`), and `delivery_channel` (`PEPPOL`, `DIRECT_XML`, `PORTAL`, `EMAIL_PDF`, `UNKNOWN`) are optional context hints. For German B2G or Peppol flows, provide the caller context on upload. An invalid value returns `422 UPLOAD_FAILED`.

## Document conversion

`POST /invoices:convert`, `multipart/form-data`:

- `file` (required): `.pdf`, `.docx`, or `.txt`. One invoice per file. A document with several invoices fails with `422 DOCUMENT_NOT_CONVERTIBLE`, `details.code=MULTIPLE_INVOICES_IN_DOCUMENT`.
- `format` (required), `profile`, context fields as above.
- `client_reference` (≤ 200 chars) or its alias `external_invoice_id`, and `source_system` (≤ 100 chars): echoed on the `202` and on task status.
- `use_embedded_xml` (default `false`): embedded Factur-X/ZUGFeRD/XRechnung XML in a PDF is ignored unless this is `true`.
- `email_input`: optional free-text instructions for the extraction (PDF only, ≤ 10,000 chars, not with `use_embedded_xml=true`).
- `use_seller_master_data` and `seller_master_data`: see *Seller master data*.

The extraction reads the document. It does not invent legal, tax, routing, bank, or buyer-reference data. If mandatory data is missing, the task fails and `/result` returns `422 VALIDATION_FAILED`.

## Structured invoice data

`POST /invoices:convert-structured` converts data from your ERP, billing, or CRM system (for example Salesforce).

- `pdf_file` (required): the carrier PDF. For `ZUGFERD` the validated XML is embedded into it; for XML formats it is stored as the original PDF. **It never supplies invoice data.**
- `data_file` (required, repeatable; aliases `data_files`, `data_files[]`): `.json`, `.csv`, `.xml`, `.xlsx`, or `.txt`, together ≤ 2 MB.
- `format`, `profile`, context, client-reference, and seller-master-data fields as for document conversion. `email_input` and `use_embedded_xml` are not accepted.

### Deterministic versus interpreted mapping

| Input | Mapping | Result |
|---|---|---|
| **One** JSON `data_file` in the canonical invoice JSON shape, at the top level or wrapped in `invoice_data` | Deterministic, no AI | Same input, same output |
| One UBL 2.1 Invoice or CII D16B XML file | Deterministic, no AI | Existing invoice XML parser |
| Several consistent canonical JSON `data_file` parts | Deterministic merge, no AI | Disjoint fields and lines are combined |
| CSV, XLSX, TXT, other XML, custom or flat JSON, or mixed-format parts | AI mapping | Works with clear labels; not deterministic |

For a repeatable integration, send one canonical JSON file:

- JSON Schema: <https://www.invoice-converter.com/developer-api/v1/invoice-data.schema.json>
- Example (German B2G XRechnung, passes EN 16931, XRechnung, and strict ZUGFeRD checks): <https://www.invoice-converter.com/developer-api/v1/invoice-data.example.json>

The shape uses UBL 2.1 / EN 16931 element names. The canonical path is detected when at least 3 of the top-level keys `ID`, `IssueDate`, `InvoiceTypeCode`, `DocumentCurrencyCode`, `AccountingSupplierParty`, `AccountingCustomerParty`, `TaxTotal`, `LegalMonetaryTotal`, `InvoiceLine` are present, including `ID`, `InvoiceLine`, or `LegalMonetaryTotal`.

Unknown fields in canonical JSON return `400 INVALID_UPLOAD` before task creation. `details.unknown_paths` lists up to 100 offending JSON paths; `details.unknown_path_count` gives the total. Remove undeclared fields instead of relying on them being discarded.

The AI mapping is told not to invent missing fields. Missing data therefore fails validation instead of being guessed.

**Split exports.** For one invoice split across files (for example header and lines), repeat `data_file`. Send one request per invoice.

- Every part must contain the same invoice number in a column or key named `invoice number`, `invoice no`, `invoice no.`, `invoice id`, `rechnungsnr`, `rechnungsnr.`, `rechnung nr`, `rechnung nr.`, `belegnr`, or `belegnr.`.
- Names are case-insensitive, and `_` and `-` count as spaces, so `Invoice_Number` works. `document no` and `document number` are a weaker fallback.
- camelCase names such as `invoiceNumber` and Salesforce API names such as `Invoice_Number__c` are recognized.
- A missing or conflicting number returns `400 INVALID_UPLOAD` with `details.reason` `bundle_invoice_id_missing` or `bundle_invoice_id_mismatch`.

Canonical JSON parts use the same top-level `ID`. Each part must meet the canonical detection rule above. Lines need unique explicit `InvoiceLine[].ID` values within each part. Identical repeated lines across parts are deduplicated; conflicting values or different lines with the same ID return `400 INVALID_UPLOAD`, `details.reason=canonical_bundle_conflict`, and `details.path`. The server does not choose one conflicting value or recalculate totals. A null value is treated as absent when another part supplies the fact.

### Required data

| Always | For XRechnung (also `UBL`/`CII` with profile `XRECHNUNG`, and `ZUGFERD_XRECHNUNG`) | For strict ZUGFeRD |
|---|---|---|
| `ID`, `IssueDate`, `InvoiceTypeCode`, `DocumentCurrencyCode`, seller and buyer name, VAT breakdown, totals, at least one line | `BuyerReference` (Leitweg-ID, BR-DE-15); `PaymentMeans` (BR-DE-1); seller contact name, phone, e-mail (BR-DE-2/5/6/7); seller and buyer city and post code; seller and buyer `EndpointID` with `@schemeID`; VAT `Percent` per subtotal; seller VAT ID or tax number | A delivery date, an invoice period, or line periods; a delivery country where applicable |

Missing data ends the task as `failed`; `/result` returns `422 VALIDATION_FAILED` with `details.items[]` (`field`, `business_term`, `rule_id`, `severity`, `source`, `message`, `suggestion`).

### Most-used JSON paths

`AccountingSupplierParty.Party` is abbreviated as `Seller`, `AccountingCustomerParty.Party` as `Buyer`. XR = required for XRechnung.

| JSON path | EN 16931 | XR |
|---|---|---|
| `ID` | BT-1 | yes |
| `IssueDate` | BT-2 | yes |
| `InvoiceTypeCode` (for example `380` commercial invoice) | BT-3 | yes |
| `DocumentCurrencyCode` | BT-5 | yes |
| `DueDate` | BT-9 | – |
| `BuyerReference` | BT-10 | yes |
| `OrderReference.ID` | BT-13 | – |
| `InvoicePeriod.StartDate` / `.EndDate` | BT-73 / BT-74 | – |
| `PaymentTerms.Note` | BT-20 | – |
| `Seller.PartyLegalEntity.RegistrationName` | BT-27 | yes |
| `Seller.PartyTaxScheme.CompanyID` (VAT ID) | BT-31 | yes¹ |
| `Seller.EndpointID` (`#text`, `@schemeID`) | BT-34 | yes |
| `Seller.PostalAddress.StreetName` | BT-35 | – |
| `Seller.PostalAddress.CityName` / `.PostalZone` | BT-37 / BT-38 | yes |
| `Seller.PostalAddress.Country.IdentificationCode` | BT-40 | yes |
| `Seller.Contact.Name` / `.Telephone` / `.ElectronicMail` | BT-41 / BT-42 / BT-43 | yes |
| `Buyer.PartyLegalEntity.RegistrationName` | BT-44 | yes |
| `Buyer.EndpointID` (`#text`, `@schemeID`) | BT-49 | yes |
| `Buyer.PostalAddress.CityName` / `.PostalZone` | BT-52 / BT-53 | yes |
| `Buyer.PostalAddress.Country.IdentificationCode` | BT-55 | yes |
| `Delivery.ActualDeliveryDate` | BT-72 | – |
| `PaymentMeans.PaymentMeansCode` | BT-81 | yes |
| `PaymentMeans.PayeeFinancialAccount.ID` (IBAN) | BT-84 | for credit transfer |
| `TaxTotal.TaxAmount` | BT-110 | yes |
| `TaxTotal.TaxSubtotal[].TaxableAmount` / `.TaxAmount` | BT-116 / BT-117 | yes |
| `TaxTotal.TaxSubtotal[].TaxCategory.ID` / `.Percent` | BT-118 / BT-119 | yes |
| `LegalMonetaryTotal.LineExtensionAmount` / `.TaxExclusiveAmount` | BT-106 / BT-109 | yes |
| `LegalMonetaryTotal.TaxInclusiveAmount` / `.PayableAmount` | BT-112 / BT-115 | yes |
| `InvoiceLine[].ID` / `.InvoicedQuantity` / `.unitCode` | BT-126 / BT-129 / BT-130 | yes |
| `InvoiceLine[].LineExtensionAmount` | BT-131 | yes |
| `InvoiceLine[].Price.PriceAmount` | BT-146 | yes |
| `InvoiceLine[].Item.Name` | BT-153 | yes |
| `InvoiceLine[].Item.ClassifiedTaxCategory.ID` / `.Percent` | BT-151 / BT-152 | yes |

¹ Seller VAT ID (BT-31) or tax number (BT-32, `PartyTaxScheme` with `TaxScheme.ID` `FC`).

## Seller master data

`seller_master_data` is a JSON object string. It applies only when `use_seller_master_data=true`; when the flag is omitted, the account default applies. Keys: `business_name`, `trading_name`, `street`, `additional_address`, `postal_code`, `city`, `country`, `vat_id`, `tax_number`, `electronic_address`, `electronic_address_scheme`, `contact_name`, `contact_email`, `contact_phone`, `payment_means_code` (`30`, `42`, or `58`), `payment_accounts` (up to 5 accounts, each with `iban`, optional `bic` and `account_name`), `payment_terms_note`. The OpenAPI schema `SellerMasterData` gives the EN 16931 term of each key.

- Every supplied value replaces the corresponding extracted seller or payment value. A non-empty `payment_accounts` list replaces all credit-transfer accounts, in saved order. Extracted IBAN, BIC and account-name values for those accounts are ignored. Other payment means retain their existing selection rules.
- Each account requires a valid, unique IBAN; BIC must be valid when supplied. The scalar keys `payment_iban`, `payment_bic` and `payment_account_name` are removed: send the list instead.
- `electronic_address` and `electronic_address_scheme` are a pair: send both or neither.
- Invalid JSON, unknown keys, invalid accounts, more than five accounts, or an incomplete pair: `400 INVALID_SELLER_MASTER_DATA`.

## Idempotency and retries

- `Idempotency-Key` is required on both POST endpoints. Format: 1–200 characters, first character a letter or digit, then letters, digits, `.`, `_`, `:`, or `-` (`^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$`). A good key is your invoice ID plus a version, for example `sf-a0B5g00000XyZ12-v1`.
- Scope: tenant and endpoint, not the individual API key. Records are kept 24 hours.
- Reuse the same key **and** the same payload on every retry. A replay returns the original `202` with `Idempotency-Replayed: true` and no second charge.
- **One key, one task.** Once an upload is accepted, every retry with the same key and payload returns that task: the same `task_id` and the same `202` body. This is also true when you did not receive the first response, or received a `5xx` after the task was accepted. A retry never starts a second task and never reserves or charges a second unit.
- Requests with the same key run one at a time: the others get `409 IDEMPOTENCY_IN_PROGRESS`. A retry after the task failed returns that failed task; to try again, use a new key.
- The same key with a different payload: `409 IDEMPOTENCY_CONFLICT`. The first request still running: `409 IDEMPOTENCY_IN_PROGRESS` (retry the same key later). The original task already deleted: `409 IDEMPOTENCY_REPLAY_EXPIRED` (new key). The key was already used for a completed conversion and its 24 h records have expired: `409 IDEMPOTENCY_KEY_ALREADY_USED` (new key).
- Retrying `429` or a `5xx` with the same key is safe: those responses do not block the key. A retry with the same key never charges twice: when a task was already accepted, it returns that task; otherwise it runs the upload again. A `5xx` alone does not tell whether a task was accepted, so always retry with the same key.

## Limits, polling, and bursts

**Rate limits** are per API key, one bucket per endpoint (table in *Overview*), in fixed calendar-minute and calendar-hour windows. A refused request does not count. `429 RATE_LIMITED` carries `Retry-After`, `X-RateLimit-Limit-Minute`, `X-RateLimit-Limit-Hour`, and `details.minute_count`, `hour_count`, `limit_minute`, `limit_hour`. Successful responses carry no quota headers.

**Polling.** First status call about 20 s after the `202`, then after 20, 30, 45, and 60 s, then every 60 s. Stop on `completed` or `failed`. Most conversions finish within two minutes. The server fails a task after 5 minutes without progress or 15 minutes in total, so set your client timeout to about 16 minutes.

**Size.** The two upload paths at `www.invoice-converter.com` route directly to the backend, without a Vercel Function. Default limits: source `file` or carrier `pdf_file` ≤ 20,000,000 bytes (20 MB); `data_file` parts ≤ 2,000,000 bytes (2 MB) total. Whole multipart bodies allow 1,000,000 bytes of overhead: 21 MB for document uploads, 23 MB for structured uploads. At most 20 file parts and 50 text fields (`400 INVALID_UPLOAD`). Exceeding a file or body limit returns JSON `413 PAYLOAD_TOO_LARGE` with `details.limit_bytes`. Authentication runs before body admission. Infrastructure failures can still return a non-JSON response.

**Bursts** (for example hundreds of recurring invoices on the first of the month): accepted tasks wait in a shared processing queue. API uploads collectively use at most half its configured slots per backend process, rounded down. The default eight-slot queue admits four API tasks and leaves four slots for web or other channels. This protects admission capacity; it does not promise processing speed or priority. A full queue or API share returns `503 SERVER_BUSY` with `Retry-After: 15` before consuming a conversion rate slot or reserving a unit. Accepted-task replays do not need another queue slot. Recommended client pattern:

1. Keep a client-side queue with about 2–4 conversions in flight; adapt to `SERVER_BUSY`.
2. On `429` and `503 SERVER_BUSY`, wait `Retry-After`, then retry with the **same** `Idempotency-Key`.
3. Poll each task with the backoff above; start the next conversion when one finishes. V1 has no completion webhook, batch, or task-list endpoint.

## Errors

Every JSON error has `code`, `message`, `correlation_id`, and usually `details`. Branch on `code`; for `500 TASK_FAILED` also on `details.code` and `details.retryable`. `details.type` is usually present, but not always. Never branch on the HTTP status or `message` alone.

The complete catalog (every code with HTTP status, retry rule, and action) is `ErrorEnvelope.code` in the OpenAPI reference. The codes you meet most:

| Code | HTTP | Retry? | Action |
|---|---|---|---|
| `AUTHENTICATION_REQUIRED`, `INVALID_API_KEY` | 401 | no | Fix the key. |
| `ACCOUNT_DELETED` | 410 | no | The account of this key was deleted. The deletion is permanent. |
| `IDEMPOTENCY_KEY_REQUIRED`, `INVALID_IDEMPOTENCY_KEY` | 400 | no | Send a valid `Idempotency-Key`. |
| `FORMAT_REQUIRED` / `INVALID_FORMAT` | 400 / 422 | no | Send a supported `format`. |
| `OUTPUT_PROFILE_CONFLICT`, `INVALID_PROFILE` | 422 | no | Use a profile from the table or omit it. |
| `INVALID_UPLOAD` | 400 / 415 | no | Fix the multipart body, file type, or split-export invoice numbers. |
| `FUNCTION_PAYLOAD_TOO_LARGE` (plain text) / `PAYLOAD_TOO_LARGE` | 413 | no | Send a smaller request. |
| `API_NOT_ENABLED_FOR_TENANT` | 403 | no | Activate API access at `details.action_url`. |
| `INSUFFICIENT_API_CREDITS` | 402 | no | Buy credits at `details.action_url` or wait for the next month. |
| `IDEMPOTENCY_IN_PROGRESS` | 409 | same key | Retry after a short delay. |
| `IDEMPOTENCY_CONFLICT`, `IDEMPOTENCY_REPLAY_EXPIRED`, `IDEMPOTENCY_KEY_ALREADY_USED` | 409 | no | Use a new key. |
| `RATE_LIMITED` | 429 | same key | Wait `Retry-After`. |
| `SERVER_BUSY` | 503 | same key | Processing queue full. Wait `Retry-After`. |
| `UPLOAD_FAILED` | 503 / 500 | same key | The upload was not accepted, or it was accepted but its first response could not be rebuilt. Retry with backoff and the same key. |
| `UPLOAD_FAILED` | 422 | no | Invalid `jurisdiction`, `transaction_scope`, or `delivery_channel`. |
| `TASK_NOT_READY` | 202 | poll | Keep polling status. |
| `VALIDATION_FAILED` | 422 | no | Correct the data (`details.items`), then convert again. |
| `DOCUMENT_NOT_CONVERTIBLE` | 422 | no | Fix the source document (`details.recovery_hint`), then convert again. |
| `TASK_FAILED` | 500 | if `details.retryable` | Read `details.code`. Retryable: new conversion with a new key. |
| `ARTIFACT_GENERATION_RERUN_REQUIRED`, `EXTRACTION_INCOMPLETE_GROUP_FAILURE` | 409 | new task | The task cannot recover. Start a new conversion with a new key. |
| `INTERNAL_ARTIFACT_INVARIANT_FAILED` | 500 | no | Escalate with the correlation ID. |
| `TASK_NOT_FOUND` | 404 | no | Unknown task, another tenant's task, or deleted after 24 h. |
| `PROXY_ERROR` | 502 / 504 | same key | Retry with backoff. |

`500 TASK_FAILED` reasons in `details.code`: `SCHEMA_PARSE_FAILED`, `ARTIFACT_PARITY_FAILED` (terminal); `SOURCE_TEXT_UNAVAILABLE`, `PROVIDER_ERROR` (follow `details.retryable`); `task_interrupted` (retryable: the server stopped before the conversion finished). `422 DOCUMENT_NOT_CONVERTIBLE` reasons: `MULTIPLE_INVOICES_IN_DOCUMENT`, `NO_INVOICE_DETECTED`, `INSUFFICIENT_INVOICE_SIGNAL`, `EMBEDDED_INVOICE_XML_INVALID`, `EMBEDDED_INVOICE_XML_UNREPRESENTABLE`, and a non-retryable `SOURCE_TEXT_UNAVAILABLE` or `PROVIDER_ERROR` with `classification=provider_context_too_large`. `409 ARTIFACT_GENERATION_RERUN_REQUIRED` with `details.code=AUTHORITATIVE_VALIDATION_UNAVAILABLE`: the validator or another artifact dependency stayed unavailable after server-side retries. A failed task stays failed: recover only with a new conversion and a new key.

## Results, proofs, and the validation report

- `/result` is pure retrieval. It returns `200` only for a stored artifact with a current validation proof. Only tasks accepted through `POST /invoices:convert` or `POST /invoices:convert-structured` have a result; for any other task of your account, `GET /tasks/{task_id}` and `/result` return `404 TASK_NOT_FOUND`.
- Record the response headers: `X-Correlation-ID`, `X-Artifact-Sha256` (hash of the delivered bytes), `X-Validation-Proof-Id`, `X-Artifact-State` (`compliant`), `X-Validation-State` (`passed`).
- `/validation-report?download=html|xml` (required parameter) returns the report bound to the delivered artifact: the KoSIT report, or for Factur-X a `validation-evidence` XML with `source="facturx_php"`. Factur-X evidence proves the stored XML validation only, not source fidelity or PDF/A conformance. On this endpoint `X-Artifact-Sha256` is the hash of the validated result artifact, not of the report. No report for the current artifact: `404 VALIDATION_REPORT_NOT_FOUND`.
- `result_artifacts.<xml|pdf>.state` on task status: `cached`, `not_ready`, `validation_failed`, `dependency_failed`, `artifact_generation_rerun_required`, `artifact_invariant_failed`.

## Retention, billing, and archiving

- **Retention.** Tasks, artifacts, and idempotency records are deleted 24 hours after the task finishes. After that, every task endpoint returns `404 TASK_NOT_FOUND`. Quality-assurance evidence follows the retention schedule in section 9 of the [Data Processing Agreement](https://www.invoice-converter.com/en/dpa).
- **Billing.** Each accepted conversion uses one unit. Enterprise includes an allowance shared with Email Import and bulk runs: 100 units per calendar month with monthly billing, or 1,200 units per contract year with annual billing, available at once from the first annual payment (100 per month during the trial). Unused units expire when the period ends. Further units use prepaid credits: 100 for EUR 50, 200 for EUR 100, 500 for EUR 250, 1,000 for EUR 400. Replays, failed conversions, and all task calls are free. When nothing covers a unit: `402 INSUFFICIENT_API_CREDITS` (two `details` shapes, see the OpenAPI `PaymentRequired` response).
- **Archiving.** Build your archive package during the flow, not later: original PDF, generated XML or hybrid PDF, validation report, and a metadata record with `task_id`, `client_reference`, format/profile, `X-Artifact-Sha256`, `X-Validation-Proof-Id`, `X-Validation-Report-Proof-Id`, `created_at`/`completed_at`, and correlation IDs.

## Support and contract

- Contact: `contact@invoice-converter.com`. Quote the `X-Correlation-ID`.
- The API is provided under the standard Terms and DPA and any Enterprise order form. No uptime, processing-time, or support SLA applies unless an order form says so.
- Poor source documents and edge cases need human review. Keep your own process for exceptions, correction, delivery, and archiving.
- API access is for your own business use. Resale, white-label, or service-bureau use needs a partner agreement.

## Reference artifacts

- OpenAPI 3.1: <https://www.invoice-converter.com/developer-api/v1/openapi.json>
- Postman collection: <https://www.invoice-converter.com/developer-api/v1/postman.json> (set `base_url`, `api_key`, `idempotency_key`)
- Structured invoice JSON Schema and example: see *Structured invoice data*
- Email invoice channel: <https://www.invoice-converter.com/en/developer-api/email-invoices>
- This documentation as Markdown (for LLMs and offline reading): <https://www.invoice-converter.com/en/developer-api/md>

## Endpoints

### POST /invoices:convert — Convert an invoice document

Upload one invoice document and start a strict conversion.

- `file`: `.pdf`, `.docx`, or `.txt`, one invoice per file. Source file ≤ 20 MB (20,000,000 bytes); whole multipart body ≤ 21 MB.
- `format` is required; `profile` is optional (default per format below).
- Embedded XML in a PDF is ignored unless `use_embedded_xml=true`.
- Rate limit: 30/min and 500/h per API key.

| `format` | Accepted `profile` | Default | `download=xml` | `download=pdf` |
|---|---|---|---|---|
| `XRECHNUNG` | `XRECHNUNG` | `XRECHNUNG` | UBL | rendered PDF (best effort) |
| `EN16931` | `EN16931` | `EN16931` | UBL | rendered PDF (best effort) |
| `UBL` | `XRECHNUNG`, `PEPPOL`, `EN16931` | `EN16931` | UBL | rendered PDF (best effort) |
| `CII` | `XRECHNUNG`, `EN16931`, `ZUGFERD_EN16931`, `ZUGFERD_FACTURX_EXTENDED`, `ZUGFERD_XRECHNUNG` | `EN16931` | CII | rendered PDF (best effort) |
| `ZUGFERD` | `ZUGFERD_EN16931`, `ZUGFERD_FACTURX_EXTENDED`, `ZUGFERD_XRECHNUNG` | `ZUGFERD_EN16931` | CII | hybrid ZUGFeRD/Factur-X PDF |

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | string | yes | Required on both POST endpoints. Reuse the same key with the same payload on every retry; a replay returns the original `202` without a second charge. Scope: tenant + endpoint, kept 24 h. Missing → `400 IDEMPOTENCY_KEY_REQUIRED`; malformed → `400 INVALID_IDEMPOTENCY_KEY`; same key with another payload → `409 IDEMPOTENCY_CONFLICT`. |
| `X-Correlation-ID` | header | string (uuid) |  | Optional UUID for tracing. A missing or non-UUID value is replaced by a server-generated UUID. Returned in the `X-Correlation-ID` response header; quote it to support. |

**Request body** (`multipart/form-data`)

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `file` | string (binary) | yes | The invoice document: `.pdf`, `.docx`, or `.txt`, one invoice per file. `.doc`, `.rtf`, and images are rejected (`400 INVALID_UPLOAD`). `format=ZUGFERD` needs a PDF (`422 ZUGFERD_SOURCE_PDF_REQUIRED`). |
| `format` | string: `XRECHNUNG`, `ZUGFERD`, `EN16931`, `UBL`, `CII` | yes | Target output format. Required; there is no default. Matched case-insensitively. Missing → `400 FORMAT_REQUIRED`; unknown → `422 INVALID_FORMAT`. |
| `profile` | string: `XRECHNUNG`, `PEPPOL`, `EN16931`, `ZUGFERD_EN16931`, `ZUGFERD_FACTURX_EXTENDED`, `ZUGFERD_XRECHNUNG` |  | Rule set the artifact is validated against. Optional: each `format` has a default (see the operation table). Matched case-insensitively. Aliases: `EXTENDED` → `ZUGFERD_FACTURX_EXTENDED`; `ZUGFERD`, `FACTURX`, `FACTUR-X`, `FACTUR_X` → `ZUGFERD_EN16931`; `ZUGFERD-XRECHNUNG` → `ZUGFERD_XRECHNUNG`. Not accepted for this format → `422 OUTPUT_PROFILE_CONFLICT`; unknown name → `422 INVALID_PROFILE`. |
| `jurisdiction` | string |  | ISO 3166-1 alpha-2 country of the transaction, for example `DE`. Optional context. Invalid → `422 UPLOAD_FAILED`. |
| `transaction_scope` | string: `B2B`, `B2G`, `B2C` |  | Optional context hint. Invalid → `422 UPLOAD_FAILED`. |
| `delivery_channel` | string: `PEPPOL`, `DIRECT_XML`, `PORTAL`, `EMAIL_PDF`, `UNKNOWN` |  | Optional context hint: `EMAIL_PDF` for hybrid PDF delivery, `DIRECT_XML` for direct XML integration, `PEPPOL` for network delivery. Invalid → `422 UPLOAD_FAILED`. |
| `client_reference` | string |  | Your invoice or job reference. Echoed on the 202 and on task status. No control characters. `external_invoice_id` is accepted as an alias; if both are sent they must match, else `400 CLIENT_REFERENCE_CONFLICT`. |
| `source_system` | string |  | Label of the calling ERP or billing system. Echoed on the 202 and on task status. |
| `use_embedded_xml` | boolean |  | Use Factur-X/ZUGFeRD/XRechnung XML embedded in the PDF as the extraction source. Default `false`: the embedded XML is ignored and the visible document is read. |
| `email_input` | string |  | Free-text instructions for the extraction, in any language (PDF source only). Not combinable with `use_embedded_xml=true`. Part of the idempotency identity. Invalid → `400 INVALID_EMAIL_INPUT`. |
| `use_seller_master_data` | boolean |  | Apply seller master data. Omitted: the account default applies. `false`: ignore saved seller data for this request. `true`: apply saved data and `seller_master_data`. |
| `seller_master_data` | string |  | JSON object string (schema: `SellerMasterData`). Applied only when `use_seller_master_data=true`. Each supplied value replaces the extracted seller or payment value; absent keys leave the invoice unchanged. Invalid → `400 INVALID_SELLER_MASTER_DATA`. |

```json
{
  "$ref": "#/components/schemas/ConvertInvoiceRequest"
}
```

**Responses**

- `202`: Accepted. Poll `status_url`. A retry with the same Idempotency-Key and the same payload returns the task that was already accepted: the same task_id and the same 202 body, with the header Idempotency-Replayed: true. This is also true when the first response was lost or was a 5xx after the task was accepted, and after the task failed. It never starts a second task and never reserves or charges a second unit.

`application/json`

```json
{
  "$ref": "#/components/schemas/ConvertAcceptedResponse"
}
```

- `400`: Invalid request. Not retryable: fix the request. See `ErrorEnvelope.code` for all 400 codes.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `401`: Authentication failed. Not retryable.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `402`: `402 INSUFFICIENT_API_CREDITS`. Not retryable: buy a prepaid credit package at `details.action_url` or wait for the next allowance period. Two `details` shapes; read the keys that are present.

`application/json`

```json
{
  "oneOf": [
    {
      "$ref": "#/components/schemas/InsufficientApiCreditsPrepaidError"
    },
    {
      "$ref": "#/components/schemas/InsufficientApiCreditsAllowanceError"
    }
  ]
}
```

- `403`: `403 API_NOT_ENABLED_FOR_TENANT`. Not retryable: activate an Enterprise subscription at `details.action_url` or contact support.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `405`: `405 METHOD_NOT_ALLOWED`: conversion paths accept POST; OPTIONS returns 204. The backend returns a JSON error with `correlation_id` for unsupported methods. HEAD returns no body.

`application/json`

```json
{
  "$ref": "#/components/schemas/EdgeError"
}
```

- `409`: Idempotency conflict. `IDEMPOTENCY_IN_PROGRESS`: retry the same key after a short delay (a stuck claim is released after 15 min). `IDEMPOTENCY_CONFLICT`, `IDEMPOTENCY_REPLAY_EXPIRED` and `IDEMPOTENCY_KEY_ALREADY_USED`: use a new key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `410`: 410 ACCOUNT_DELETED. The API key still authenticates, but its account was deleted. The deletion is permanent, so the response is 410 Gone on every path that reports it. Not retryable. A revoked key returns 401 INVALID_API_KEY instead.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `413`: Request too large. Not retryable: send a smaller request. Uploads route directly to the backend. File and multipart body limits return JSON `413 PAYLOAD_TOO_LARGE` with `details.limit_bytes`. Default limits: source or carrier file 20 MB, structured data parts 2 MB total; whole multipart body 21 MB for document uploads or 23 MB for structured uploads (including 1 MB overhead).

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

`text/plain`

```json
{
  "type": "string"
}
```

- `415`: `415 INVALID_UPLOAD`: send `multipart/form-data`. Not retryable.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `422`: Upload or request option validation failed. Not retryable: correct the request. Codes: `INVALID_FORMAT`, `INVALID_PROFILE`, `OUTPUT_PROFILE_CONFLICT`, `OUTPUT_PROFILE_REQUIRED`, `UPLOAD_FAILED` (invalid context value), `ZUGFERD_SOURCE_PDF_REQUIRED`.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `429`: `429 RATE_LIMITED`. Retryable: wait `Retry-After` seconds and retry with the same Idempotency-Key. Limits are per API key and endpoint, in fixed calendar-minute and calendar-hour windows. Refused requests do not count.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `500`: Server-side failure. A 500 is not retryable by default. `TASK_FAILED`: read `details.code`; only `details.retryable: true` allows a retry, and only as a NEW conversion with a new Idempotency-Key. `INTERNAL_ARTIFACT_INVARIANT_FAILED`: escalate. `UPLOAD_FAILED` on upload: retry with the same key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `502`: `502 PROXY_ERROR`: the edge could not reach the backend. Retry with backoff and the same Idempotency-Key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `503`: Temporarily unavailable. Retry with the same Idempotency-Key. `SERVER_BUSY`: the processing queue is full; wait `Retry-After` seconds. `AUTH_SERVICE_UNAVAILABLE`, `PLAN_TIER_CHECK_FAILED`, `RATE_LIMIT_SERVICE_UNAVAILABLE`, `API_CREDIT_SERVICE_UNAVAILABLE`, `UPLOAD_FAILED` (other acceptance failure): retry with backoff.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `504`: `504 PROXY_ERROR`: the backend did not answer in time. Retry with backoff and the same Idempotency-Key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

### POST /invoices:convert-structured — Convert structured invoice data

Convert invoice data from your system. `data_file` is the only data source; `pdf_file` is only the carrier (embedded for ZUGFeRD, stored as the original PDF otherwise).

- **Deterministic:** one JSON `data_file` in the `StructuredInvoiceData` shape, consistent canonical JSON parts, or one UBL 2.1 Invoice / CII D16B XML file maps without AI ([schema](https://www.invoice-converter.com/developer-api/v1/invoice-data.schema.json), [example](https://www.invoice-converter.com/developer-api/v1/invoice-data.example.json)).
- **Interpreted:** CSV, XLSX, TXT, other XML, custom JSON, and mixed-format parts use AI mapping, which leaves missing fields empty.
- Split exports: repeat `data_file`; all parts need the same invoice number. Columns such as `Invoice Number`, `Rechnungsnr`, `invoiceNumber`, and `Invoice_Number__c` are recognized; canonical JSON uses `ID`.
- Canonical JSON: unknown fields return `400 INVALID_UPLOAD` with `details.unknown_paths`; conflicting bundle values return `details.reason=canonical_bundle_conflict` and `details.path`. Lines require unique explicit `InvoiceLine[].ID` values within each part.
- Limits: `pdf_file` ≤ 20 MB, `data_file` parts ≤ 2 MB total, whole multipart body ≤ 23 MB. Rate limit: 30/min and 500/h per API key.
- `format` and `profile` rules are the same as for `POST /invoices:convert`.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | string | yes | Required on both POST endpoints. Reuse the same key with the same payload on every retry; a replay returns the original `202` without a second charge. Scope: tenant + endpoint, kept 24 h. Missing → `400 IDEMPOTENCY_KEY_REQUIRED`; malformed → `400 INVALID_IDEMPOTENCY_KEY`; same key with another payload → `409 IDEMPOTENCY_CONFLICT`. |
| `X-Correlation-ID` | header | string (uuid) |  | Optional UUID for tracing. A missing or non-UUID value is replaced by a server-generated UUID. Returned in the `X-Correlation-ID` response header; quote it to support. |

**Request body** (`multipart/form-data`)

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `pdf_file` | string (binary) | yes | Carrier PDF. For `ZUGFERD` the validated XML is embedded into it; for XML formats it is stored as the original PDF. It never supplies invoice data. |
| `data_file` | oneOf(string (binary), array of string (binary)) | yes | Invoice data: `.json`, `.csv`, `.xml`, `.xlsx`, or `.txt` (≤ 2 MB total). Canonical JSON (top level or wrapped in `invoice_data`), consistent canonical JSON parts, and one UBL 2.1 Invoice / CII D16B XML file map without AI; other formats use AI mapping. Unknown canonical fields and conflicting bundle facts return `400 INVALID_UPLOAD`. Repeat the part for one invoice split across files; all parts need the same invoice number, and canonical lines need unique explicit IDs. Schema: https://www.invoice-converter.com/developer-api/v1/invoice-data.schema.json. The field names `data_files` and `data_files[]` are accepted as aliases. |
| `format` | string: `XRECHNUNG`, `ZUGFERD`, `EN16931`, `UBL`, `CII` | yes | Target output format. Required; there is no default. Matched case-insensitively. Missing → `400 FORMAT_REQUIRED`; unknown → `422 INVALID_FORMAT`. |
| `profile` | string: `XRECHNUNG`, `PEPPOL`, `EN16931`, `ZUGFERD_EN16931`, `ZUGFERD_FACTURX_EXTENDED`, `ZUGFERD_XRECHNUNG` |  | Rule set the artifact is validated against. Optional: each `format` has a default (see the operation table). Matched case-insensitively. Aliases: `EXTENDED` → `ZUGFERD_FACTURX_EXTENDED`; `ZUGFERD`, `FACTURX`, `FACTUR-X`, `FACTUR_X` → `ZUGFERD_EN16931`; `ZUGFERD-XRECHNUNG` → `ZUGFERD_XRECHNUNG`. Not accepted for this format → `422 OUTPUT_PROFILE_CONFLICT`; unknown name → `422 INVALID_PROFILE`. |
| `jurisdiction` | string |  | ISO 3166-1 alpha-2 country of the transaction, for example `DE`. Optional context. Invalid → `422 UPLOAD_FAILED`. |
| `transaction_scope` | string: `B2B`, `B2G`, `B2C` |  | Optional context hint. Invalid → `422 UPLOAD_FAILED`. |
| `delivery_channel` | string: `PEPPOL`, `DIRECT_XML`, `PORTAL`, `EMAIL_PDF`, `UNKNOWN` |  | Optional context hint: `EMAIL_PDF` for hybrid PDF delivery, `DIRECT_XML` for direct XML integration, `PEPPOL` for network delivery. Invalid → `422 UPLOAD_FAILED`. |
| `client_reference` | string |  | Your invoice or job reference. Echoed on the 202 and on task status. No control characters. `external_invoice_id` is accepted as an alias; if both are sent they must match, else `400 CLIENT_REFERENCE_CONFLICT`. |
| `source_system` | string |  | Label of the calling ERP or billing system. Echoed on the 202 and on task status. |
| `use_seller_master_data` | boolean |  | Apply seller master data. Omitted: the account default applies. `false`: ignore saved seller data for this request. `true`: apply saved data and `seller_master_data`. |
| `seller_master_data` | string |  | JSON object string (schema: `SellerMasterData`). Applied only when `use_seller_master_data=true`. Each supplied value replaces the extracted seller or payment value; absent keys leave the invoice unchanged. Invalid → `400 INVALID_SELLER_MASTER_DATA`. |

```json
{
  "$ref": "#/components/schemas/ConvertStructuredInvoiceRequest"
}
```

**Responses**

- `202`: Accepted. Poll `status_url`. A retry with the same Idempotency-Key and the same payload returns the task that was already accepted: the same task_id and the same 202 body, with the header Idempotency-Replayed: true. This is also true when the first response was lost or was a 5xx after the task was accepted, and after the task failed. It never starts a second task and never reserves or charges a second unit.

`application/json`

```json
{
  "$ref": "#/components/schemas/ConvertAcceptedResponse"
}
```

- `400`: Invalid request. Not retryable: fix the request. See `ErrorEnvelope.code` for all 400 codes.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `401`: Authentication failed. Not retryable.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `402`: `402 INSUFFICIENT_API_CREDITS`. Not retryable: buy a prepaid credit package at `details.action_url` or wait for the next allowance period. Two `details` shapes; read the keys that are present.

`application/json`

```json
{
  "oneOf": [
    {
      "$ref": "#/components/schemas/InsufficientApiCreditsPrepaidError"
    },
    {
      "$ref": "#/components/schemas/InsufficientApiCreditsAllowanceError"
    }
  ]
}
```

- `403`: `403 API_NOT_ENABLED_FOR_TENANT`. Not retryable: activate an Enterprise subscription at `details.action_url` or contact support.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `405`: `405 METHOD_NOT_ALLOWED`: conversion paths accept POST; OPTIONS returns 204. The backend returns a JSON error with `correlation_id` for unsupported methods. HEAD returns no body.

`application/json`

```json
{
  "$ref": "#/components/schemas/EdgeError"
}
```

- `409`: Idempotency conflict. `IDEMPOTENCY_IN_PROGRESS`: retry the same key after a short delay (a stuck claim is released after 15 min). `IDEMPOTENCY_CONFLICT`, `IDEMPOTENCY_REPLAY_EXPIRED` and `IDEMPOTENCY_KEY_ALREADY_USED`: use a new key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `410`: 410 ACCOUNT_DELETED. The API key still authenticates, but its account was deleted. The deletion is permanent, so the response is 410 Gone on every path that reports it. Not retryable. A revoked key returns 401 INVALID_API_KEY instead.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `413`: Request too large. Not retryable: send a smaller request. Uploads route directly to the backend. File and multipart body limits return JSON `413 PAYLOAD_TOO_LARGE` with `details.limit_bytes`. Default limits: source or carrier file 20 MB, structured data parts 2 MB total; whole multipart body 21 MB for document uploads or 23 MB for structured uploads (including 1 MB overhead).

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

`text/plain`

```json
{
  "type": "string"
}
```

- `415`: `415 INVALID_UPLOAD`: send `multipart/form-data`. Not retryable.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `422`: Upload or request option validation failed. Not retryable: correct the request. Codes: `INVALID_FORMAT`, `INVALID_PROFILE`, `OUTPUT_PROFILE_CONFLICT`, `OUTPUT_PROFILE_REQUIRED`, `UPLOAD_FAILED` (invalid context value), `ZUGFERD_SOURCE_PDF_REQUIRED`.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `429`: `429 RATE_LIMITED`. Retryable: wait `Retry-After` seconds and retry with the same Idempotency-Key. Limits are per API key and endpoint, in fixed calendar-minute and calendar-hour windows. Refused requests do not count.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `500`: Server-side failure. A 500 is not retryable by default. `TASK_FAILED`: read `details.code`; only `details.retryable: true` allows a retry, and only as a NEW conversion with a new Idempotency-Key. `INTERNAL_ARTIFACT_INVARIANT_FAILED`: escalate. `UPLOAD_FAILED` on upload: retry with the same key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `502`: `502 PROXY_ERROR`: the edge could not reach the backend. Retry with backoff and the same Idempotency-Key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `503`: Temporarily unavailable. Retry with the same Idempotency-Key. `SERVER_BUSY`: the processing queue is full; wait `Retry-After` seconds. `AUTH_SERVICE_UNAVAILABLE`, `PLAN_TIER_CHECK_FAILED`, `RATE_LIMIT_SERVICE_UNAVAILABLE`, `API_CREDIT_SERVICE_UNAVAILABLE`, `UPLOAD_FAILED` (other acceptance failure): retry with backoff.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `504`: `504 PROXY_ERROR`: the backend did not answer in time. Retry with backoff and the same Idempotency-Key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

### GET /tasks/{task_id} — Get task status

Return the task state. Poll until `status` is `completed` or `failed`.

- Backoff: first call ~20 s after the `202`, then 20, 30, 45, 60 s, then every 60 s. Stop after ~16 min.
- `completed`: download from `primary_result_url`. `failed`: call `/result` for the typed error.
- Unknown task, a task not accepted through this API (for example a web upload), or more than 24 h after completion: `404 TASK_NOT_FOUND`.
- Rate limit: 60/min and 1,500/h per API key.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `task_id` | path | string (uuid) | yes | `task_id` from the `202` response. Not a UUID → `400 BAD_REQUEST`. |
| `include_validation_report_html` | query | string: `true`, `false` |  | `true` adds the sanitized validation report HTML as `validation_report_html`. Other values than `true`/`false` → `400 INVALID_QUERY_PARAMETER`. |
| `X-Correlation-ID` | header | string (uuid) |  | Optional UUID for tracing. A missing or non-UUID value is replaced by a server-generated UUID. Returned in the `X-Correlation-ID` response header; quote it to support. |

**Responses**

- `200`: Current task state.

`application/json`

```json
{
  "$ref": "#/components/schemas/TaskStatusResponse"
}
```

- `400`: Invalid request. Not retryable: fix the request. See `ErrorEnvelope.code` for all 400 codes.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `401`: Authentication failed. Not retryable.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `403`: `403 API_NOT_ENABLED_FOR_TENANT`. Not retryable: activate an Enterprise subscription at `details.action_url` or contact support.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `404`: `404 TASK_NOT_FOUND`: unknown task, another tenant's task, a task not accepted through this API, or deleted 24 h after completion. Not retryable.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `405`: `405 METHOD_NOT_ALLOWED`: task paths accept GET only. Sent by the edge proxy, so the body has no `correlation_id`.

`application/json`

```json
{
  "$ref": "#/components/schemas/EdgeError"
}
```

- `410`: 410 ACCOUNT_DELETED. The API key still authenticates, but its account was deleted. The deletion is permanent, so the response is 410 Gone on every path that reports it. Not retryable. A revoked key returns 401 INVALID_API_KEY instead.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `429`: `429 RATE_LIMITED`. Retryable: wait `Retry-After` seconds and retry with the same Idempotency-Key. Limits are per API key and endpoint, in fixed calendar-minute and calendar-hour windows. Refused requests do not count.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `500`: Server-side failure. A 500 is not retryable by default. `TASK_FAILED`: read `details.code`; only `details.retryable: true` allows a retry, and only as a NEW conversion with a new Idempotency-Key. `INTERNAL_ARTIFACT_INVARIANT_FAILED`: escalate. `UPLOAD_FAILED` on upload: retry with the same key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `502`: `502 PROXY_ERROR`: the edge could not reach the backend. Retry with backoff and the same Idempotency-Key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `503`: Temporarily unavailable. Retry with backoff: `AUTH_SERVICE_UNAVAILABLE`, `PLAN_TIER_CHECK_FAILED`, `RATE_LIMIT_SERVICE_UNAVAILABLE`.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `504`: `504 PROXY_ERROR`: the backend did not answer in time. Retry with backoff and the same Idempotency-Key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

### GET /tasks/{task_id}/result — Download the result

Download the validated artifact. Pure retrieval: nothing is generated, repaired, or validated on this call.

- `download=xml`: UBL (`XRECHNUNG`, `EN16931`, `UBL`) or CII (`CII`, `ZUGFERD`). Always the primary artifact for XML formats.
- `download=pdf`: hybrid ZUGFeRD/Factur-X PDF for `ZUGFERD`; a best-effort rendering for the other formats.
- Only tasks accepted through the two conversion endpoints have a result. Any other task (for example a web upload) returns `404 TASK_NOT_FOUND`.
- While processing: `202 TASK_NOT_READY`. Failed task: its typed error (`409 ARTIFACT_GENERATION_RERUN_REQUIRED`, `422 VALIDATION_FAILED`, `422 DOCUMENT_NOT_CONVERTIBLE`, `500 TASK_FAILED`).
- Rate limit: 60/min and 1,000/h per API key.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `task_id` | path | string (uuid) | yes | `task_id` from the `202` response. Not a UUID → `400 BAD_REQUEST`. |
| `download` | query | string: `xml`, `pdf` | yes | Artifact to download (case-insensitive). Missing → `400 DOWNLOAD_FORMAT_REQUIRED`; other values → `400 INVALID_DOWNLOAD_FORMAT`. |
| `X-Correlation-ID` | header | string (uuid) |  | Optional UUID for tracing. A missing or non-UUID value is replaced by a server-generated UUID. Returned in the `X-Correlation-ID` response header; quote it to support. |

**Responses**

- `200`: The artifact bytes. The `X-*` headers describe the delivered bytes; record them for your archive.

`application/xml`

```json
{
  "type": "string"
}
```

`application/pdf`

```json
{
  "type": "string",
  "format": "binary"
}
```

- `202`: `202 TASK_NOT_READY`: still processing. The body is an error envelope, not a file. Keep polling task status.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `400`: Invalid request. Not retryable: fix the request. See `ErrorEnvelope.code` for all 400 codes.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `401`: Authentication failed. Not retryable.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `403`: `403 API_NOT_ENABLED_FOR_TENANT`. Not retryable: activate an Enterprise subscription at `details.action_url` or contact support.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `404`: `404 TASK_NOT_FOUND`: unknown task, another tenant's task, a task not accepted through this API, or deleted 24 h after completion. `404 TASK_RESULT_FAILED`: the task exists but its result data is unavailable; escalate with the correlation ID. Not retryable.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `405`: `405 METHOD_NOT_ALLOWED`: task paths accept GET only. Sent by the edge proxy, so the body has no `correlation_id`.

`application/json`

```json
{
  "$ref": "#/components/schemas/EdgeError"
}
```

- `409`: `409`: the task failed for a transient reason and cannot recover; repeating this request never succeeds. Start a new conversion with a new Idempotency-Key. Codes: `ARTIFACT_GENERATION_RERUN_REQUIRED` (reason in `details.code`, for example `AUTHORITATIVE_VALIDATION_UNAVAILABLE`), `EXTRACTION_INCOMPLETE_GROUP_FAILURE`.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `410`: 410 ACCOUNT_DELETED. The API key still authenticates, but its account was deleted. The deletion is permanent, so the response is 410 Gone on every path that reports it. Not retryable. A revoked key returns 401 INVALID_API_KEY instead.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `422`: The invoice cannot be issued. Not retryable: correct the data or the source document and start a new conversion. Codes: `VALIDATION_FAILED` (`details.items`), `DOCUMENT_NOT_CONVERTIBLE` (`details.code`, `details.recovery_hint`), `PROFILE_MISMATCH`, `ZUGFERD_SOURCE_PDF_INCOMPATIBLE`, `PROTECTED_BANK_DETAILS_MISMATCH` (`details.items`).

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `429`: `429 RATE_LIMITED`. Retryable: wait `Retry-After` seconds and retry with the same Idempotency-Key. Limits are per API key and endpoint, in fixed calendar-minute and calendar-hour windows. Refused requests do not count.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `500`: Server-side failure. A 500 is not retryable by default. `TASK_FAILED`: read `details.code`; only `details.retryable: true` allows a retry, and only as a NEW conversion with a new Idempotency-Key. `INTERNAL_ARTIFACT_INVARIANT_FAILED`: escalate. `UPLOAD_FAILED` on upload: retry with the same key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `502`: `502 PROXY_ERROR`: the edge could not reach the backend. Retry with backoff and the same Idempotency-Key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `503`: Temporarily unavailable. Retry with backoff: `AUTH_SERVICE_UNAVAILABLE`, `PLAN_TIER_CHECK_FAILED`, `RATE_LIMIT_SERVICE_UNAVAILABLE`.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `504`: `504 PROXY_ERROR`: the backend did not answer in time. Retry with backoff and the same Idempotency-Key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

### GET /tasks/{task_id}/validation-report — Download the validation report

Download the validation report bound to the delivered artifact.

- `download=html` for people; `download=xml` for the KoSIT report, or Factur-X `validation-evidence` XML (`source="facturx_php"`, not KoSIT format).
- The `X-Artifact-*` headers describe the validated result artifact, not the report bytes.
- Factur-X evidence proves stored XML validation only, not source fidelity or PDF/A conformance.
- Rate limit: 30/min and 500/h per API key.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `task_id` | path | string (uuid) | yes | `task_id` from the `202` response. Not a UUID → `400 BAD_REQUEST`. |
| `download` | query | string: `html`, `xml` | yes | `html` for a readable report, `xml` for the machine-readable report. Missing → `400 DOWNLOAD_FORMAT_REQUIRED`; other values → `400 INVALID_DOWNLOAD_FORMAT`. |
| `X-Correlation-ID` | header | string (uuid) |  | Optional UUID for tracing. A missing or non-UUID value is replaced by a server-generated UUID. Returned in the `X-Correlation-ID` response header; quote it to support. |

**Responses**

- `200`: The report.

`text/html`

```json
{
  "type": "string"
}
```

`application/xml`

```json
{
  "type": "string"
}
```

- `202`: `202 TASK_NOT_READY`: still processing. The body is an error envelope, not a file. Keep polling task status.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `400`: Invalid request. Not retryable: fix the request. See `ErrorEnvelope.code` for all 400 codes.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `401`: Authentication failed. Not retryable.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `403`: `403 API_NOT_ENABLED_FOR_TENANT`. Not retryable: activate an Enterprise subscription at `details.action_url` or contact support.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `404`: `404 TASK_NOT_FOUND` (unknown or expired task) or `404 VALIDATION_REPORT_NOT_FOUND` (no report bound to the current artifact; `details.reason`). Not retryable.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `405`: `405 METHOD_NOT_ALLOWED`: task paths accept GET only. Sent by the edge proxy, so the body has no `correlation_id`.

`application/json`

```json
{
  "$ref": "#/components/schemas/EdgeError"
}
```

- `409`: `409`: the task failed for a transient reason and cannot recover; repeating this request never succeeds. Start a new conversion with a new Idempotency-Key. Codes: `ARTIFACT_GENERATION_RERUN_REQUIRED` (reason in `details.code`, for example `AUTHORITATIVE_VALIDATION_UNAVAILABLE`), `EXTRACTION_INCOMPLETE_GROUP_FAILURE`.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `410`: 410 ACCOUNT_DELETED. The API key still authenticates, but its account was deleted. The deletion is permanent, so the response is 410 Gone on every path that reports it. Not retryable. A revoked key returns 401 INVALID_API_KEY instead.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `422`: The invoice cannot be issued. Not retryable: correct the data or the source document and start a new conversion. Codes: `VALIDATION_FAILED` (`details.items`), `DOCUMENT_NOT_CONVERTIBLE` (`details.code`, `details.recovery_hint`), `PROFILE_MISMATCH`, `ZUGFERD_SOURCE_PDF_INCOMPATIBLE`, `PROTECTED_BANK_DETAILS_MISMATCH` (`details.items`).

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `429`: `429 RATE_LIMITED`. Retryable: wait `Retry-After` seconds and retry with the same Idempotency-Key. Limits are per API key and endpoint, in fixed calendar-minute and calendar-hour windows. Refused requests do not count.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `500`: Server-side failure. A 500 is not retryable by default. `TASK_FAILED`: read `details.code`; only `details.retryable: true` allows a retry, and only as a NEW conversion with a new Idempotency-Key. `INTERNAL_ARTIFACT_INVARIANT_FAILED`: escalate. `UPLOAD_FAILED` on upload: retry with the same key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `502`: `502 PROXY_ERROR`: the edge could not reach the backend. Retry with backoff and the same Idempotency-Key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `503`: Temporarily unavailable. Retry with backoff: `AUTH_SERVICE_UNAVAILABLE`, `PLAN_TIER_CHECK_FAILED`, `RATE_LIMIT_SERVICE_UNAVAILABLE`.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

- `504`: `504 PROXY_ERROR`: the backend did not answer in time. Retry with backoff and the same Idempotency-Key.

`application/json`

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

## Schemas

### `ConvertInvoiceRequest`

```json
{
  "type": "object",
  "required": [
    "file",
    "format"
  ],
  "properties": {
    "file": {
      "type": "string",
      "format": "binary",
      "description": "The invoice document: `.pdf`, `.docx`, or `.txt`, one invoice per file. `.doc`, `.rtf`, and images are rejected (`400 INVALID_UPLOAD`). `format=ZUGFERD` needs a PDF (`422 ZUGFERD_SOURCE_PDF_REQUIRED`)."
    },
    "format": {
      "type": "string",
      "enum": [
        "XRECHNUNG",
        "ZUGFERD",
        "EN16931",
        "UBL",
        "CII"
      ],
      "description": "Target output format. Required; there is no default. Matched case-insensitively. Missing → `400 FORMAT_REQUIRED`; unknown → `422 INVALID_FORMAT`.",
      "examples": [
        "XRECHNUNG"
      ]
    },
    "profile": {
      "type": "string",
      "enum": [
        "XRECHNUNG",
        "PEPPOL",
        "EN16931",
        "ZUGFERD_EN16931",
        "ZUGFERD_FACTURX_EXTENDED",
        "ZUGFERD_XRECHNUNG"
      ],
      "description": "Rule set the artifact is validated against. Optional: each `format` has a default (see the operation table). Matched case-insensitively. Aliases: `EXTENDED` → `ZUGFERD_FACTURX_EXTENDED`; `ZUGFERD`, `FACTURX`, `FACTUR-X`, `FACTUR_X` → `ZUGFERD_EN16931`; `ZUGFERD-XRECHNUNG` → `ZUGFERD_XRECHNUNG`. Not accepted for this format → `422 OUTPUT_PROFILE_CONFLICT`; unknown name → `422 INVALID_PROFILE`.",
      "examples": [
        "XRECHNUNG"
      ]
    },
    "jurisdiction": {
      "type": "string",
      "description": "ISO 3166-1 alpha-2 country of the transaction, for example `DE`. Optional context. Invalid → `422 UPLOAD_FAILED`.",
      "examples": [
        "DE"
      ]
    },
    "transaction_scope": {
      "type": "string",
      "enum": [
        "B2B",
        "B2G",
        "B2C"
      ],
      "description": "Optional context hint. Invalid → `422 UPLOAD_FAILED`."
    },
    "delivery_channel": {
      "type": "string",
      "enum": [
        "PEPPOL",
        "DIRECT_XML",
        "PORTAL",
        "EMAIL_PDF",
        "UNKNOWN"
      ],
      "description": "Optional context hint: `EMAIL_PDF` for hybrid PDF delivery, `DIRECT_XML` for direct XML integration, `PEPPOL` for network delivery. Invalid → `422 UPLOAD_FAILED`."
    },
    "client_reference": {
      "type": "string",
      "maxLength": 200,
      "description": "Your invoice or job reference. Echoed on the 202 and on task status. No control characters. `external_invoice_id` is accepted as an alias; if both are sent they must match, else `400 CLIENT_REFERENCE_CONFLICT`.",
      "examples": [
        "ERP-2026-0001"
      ]
    },
    "source_system": {
      "type": "string",
      "maxLength": 100,
      "description": "Label of the calling ERP or billing system. Echoed on the 202 and on task status.",
      "examples": [
        "salesforce"
      ]
    },
    "use_embedded_xml": {
      "type": "boolean",
      "default": false,
      "description": "Use Factur-X/ZUGFeRD/XRechnung XML embedded in the PDF as the extraction source. Default `false`: the embedded XML is ignored and the visible document is read."
    },
    "email_input": {
      "type": "string",
      "maxLength": 10000,
      "description": "Free-text instructions for the extraction, in any language (PDF source only). Not combinable with `use_embedded_xml=true`. Part of the idempotency identity. Invalid → `400 INVALID_EMAIL_INPUT`.",
      "examples": [
        "Use purchase order number PO-42."
      ]
    },
    "use_seller_master_data": {
      "type": "boolean",
      "description": "Apply seller master data. Omitted: the account default applies. `false`: ignore saved seller data for this request. `true`: apply saved data and `seller_master_data`."
    },
    "seller_master_data": {
      "type": "string",
      "contentMediaType": "application/json",
      "contentSchema": {
        "$ref": "#/components/schemas/SellerMasterData"
      },
      "description": "JSON object string (schema: `SellerMasterData`). Applied only when `use_seller_master_data=true`. Each supplied value replaces the extracted seller or payment value; absent keys leave the invoice unchanged. Invalid → `400 INVALID_SELLER_MASTER_DATA`.",
      "examples": [
        "{\"business_name\":\"Seller GmbH\",\"vat_id\":\"DE123456789\",\"city\":\"Berlin\",\"country\":\"DE\"}"
      ]
    }
  },
  "additionalProperties": false
}
```

### `ConvertStructuredInvoiceRequest`

```json
{
  "type": "object",
  "required": [
    "pdf_file",
    "data_file",
    "format"
  ],
  "properties": {
    "pdf_file": {
      "type": "string",
      "format": "binary",
      "description": "Carrier PDF. For `ZUGFERD` the validated XML is embedded into it; for XML formats it is stored as the original PDF. It never supplies invoice data."
    },
    "data_file": {
      "oneOf": [
        {
          "type": "string",
          "format": "binary"
        },
        {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string",
            "format": "binary"
          }
        }
      ],
      "description": "Invoice data: `.json`, `.csv`, `.xml`, `.xlsx`, or `.txt` (≤ 2 MB total). Canonical JSON (top level or wrapped in `invoice_data`), consistent canonical JSON parts, and one UBL 2.1 Invoice / CII D16B XML file map without AI; other formats use AI mapping. Unknown canonical fields and conflicting bundle facts return `400 INVALID_UPLOAD`. Repeat the part for one invoice split across files; all parts need the same invoice number, and canonical lines need unique explicit IDs. Schema: https://www.invoice-converter.com/developer-api/v1/invoice-data.schema.json. The field names `data_files` and `data_files[]` are accepted as aliases."
    },
    "format": {
      "type": "string",
      "enum": [
        "XRECHNUNG",
        "ZUGFERD",
        "EN16931",
        "UBL",
        "CII"
      ],
      "description": "Target output format. Required; there is no default. Matched case-insensitively. Missing → `400 FORMAT_REQUIRED`; unknown → `422 INVALID_FORMAT`.",
      "examples": [
        "XRECHNUNG"
      ]
    },
    "profile": {
      "type": "string",
      "enum": [
        "XRECHNUNG",
        "PEPPOL",
        "EN16931",
        "ZUGFERD_EN16931",
        "ZUGFERD_FACTURX_EXTENDED",
        "ZUGFERD_XRECHNUNG"
      ],
      "description": "Rule set the artifact is validated against. Optional: each `format` has a default (see the operation table). Matched case-insensitively. Aliases: `EXTENDED` → `ZUGFERD_FACTURX_EXTENDED`; `ZUGFERD`, `FACTURX`, `FACTUR-X`, `FACTUR_X` → `ZUGFERD_EN16931`; `ZUGFERD-XRECHNUNG` → `ZUGFERD_XRECHNUNG`. Not accepted for this format → `422 OUTPUT_PROFILE_CONFLICT`; unknown name → `422 INVALID_PROFILE`.",
      "examples": [
        "XRECHNUNG"
      ]
    },
    "jurisdiction": {
      "type": "string",
      "description": "ISO 3166-1 alpha-2 country of the transaction, for example `DE`. Optional context. Invalid → `422 UPLOAD_FAILED`.",
      "examples": [
        "DE"
      ]
    },
    "transaction_scope": {
      "type": "string",
      "enum": [
        "B2B",
        "B2G",
        "B2C"
      ],
      "description": "Optional context hint. Invalid → `422 UPLOAD_FAILED`."
    },
    "delivery_channel": {
      "type": "string",
      "enum": [
        "PEPPOL",
        "DIRECT_XML",
        "PORTAL",
        "EMAIL_PDF",
        "UNKNOWN"
      ],
      "description": "Optional context hint: `EMAIL_PDF` for hybrid PDF delivery, `DIRECT_XML` for direct XML integration, `PEPPOL` for network delivery. Invalid → `422 UPLOAD_FAILED`."
    },
    "client_reference": {
      "type": "string",
      "maxLength": 200,
      "description": "Your invoice or job reference. Echoed on the 202 and on task status. No control characters. `external_invoice_id` is accepted as an alias; if both are sent they must match, else `400 CLIENT_REFERENCE_CONFLICT`.",
      "examples": [
        "ERP-2026-0001"
      ]
    },
    "source_system": {
      "type": "string",
      "maxLength": 100,
      "description": "Label of the calling ERP or billing system. Echoed on the 202 and on task status.",
      "examples": [
        "salesforce"
      ]
    },
    "use_seller_master_data": {
      "type": "boolean",
      "description": "Apply seller master data. Omitted: the account default applies. `false`: ignore saved seller data for this request. `true`: apply saved data and `seller_master_data`."
    },
    "seller_master_data": {
      "type": "string",
      "contentMediaType": "application/json",
      "contentSchema": {
        "$ref": "#/components/schemas/SellerMasterData"
      },
      "description": "JSON object string (schema: `SellerMasterData`). Applied only when `use_seller_master_data=true`. Each supplied value replaces the extracted seller or payment value; absent keys leave the invoice unchanged. Invalid → `400 INVALID_SELLER_MASTER_DATA`.",
      "examples": [
        "{\"business_name\":\"Seller GmbH\",\"vat_id\":\"DE123456789\",\"city\":\"Berlin\",\"country\":\"DE\"}"
      ]
    }
  },
  "additionalProperties": false
}
```

### `StructuredInvoiceData`

```json
{
  "additionalProperties": false,
  "properties": {
    "CustomizationID": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Customizationid"
    },
    "ProfileID": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Profileid"
    },
    "ID": {
      "title": "Id",
      "type": "string"
    },
    "IssueDate": {
      "title": "Issuedate",
      "type": "string"
    },
    "DueDate": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Duedate"
    },
    "TaxCurrencyCode": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Taxcurrencycode"
    },
    "TaxPointDate": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Taxpointdate"
    },
    "InvoicePeriod": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_InvoicePeriod"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "InvoiceTypeCode": {
      "title": "Invoicetypecode",
      "type": "string"
    },
    "DocumentCurrencyCode": {
      "title": "Documentcurrencycode",
      "type": "string"
    },
    "OrderReference": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_OrderReference"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "SalesOrderReference": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_SalesOrderReference"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "ContractDocumentReference": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_ContractDocumentReference"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "ProjectReference": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_ProjectReference"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "TenderOrLotReference": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_TenderOrLotReference"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "DespatchDocumentReference": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_DespatchDocumentReference"
        },
        {
          "items": {
            "$ref": "#/components/schemas/StructuredInvoice_DespatchDocumentReference"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Despatchdocumentreference"
    },
    "PrecedingInvoiceReference": {
      "anyOf": [
        {
          "items": {
            "$ref": "#/components/schemas/StructuredInvoice_PrecedingInvoiceReference"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Precedinginvoicereference"
    },
    "AdditionalDocumentReference": {
      "anyOf": [
        {
          "items": {
            "$ref": "#/components/schemas/StructuredInvoice_AdditionalDocumentReference"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Additionaldocumentreference"
    },
    "AdvancePaymentSettlement": {
      "anyOf": [
        {
          "items": {
            "$ref": "#/components/schemas/StructuredInvoice_AdvancePaymentSettlementRow"
          },
          "maxItems": 200,
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Advancepaymentsettlement"
    },
    "UninvoicedPrepaidAmount": {
      "anyOf": [
        {
          "minimum": 0,
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Gross payment already received without an advance invoice. Included in BT-113 in addition to the numbered AdvancePaymentSettlement rows, and shown separately in the settlement annex. Do not also include it in a numbered advance row.",
      "title": "Uninvoicedprepaidamount"
    },
    "AllowanceCharge": {
      "anyOf": [
        {
          "items": {
            "$ref": "#/components/schemas/StructuredInvoice_AllowanceCharge"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Allowancecharge"
    },
    "AccountingSupplierParty": {
      "$ref": "#/components/schemas/StructuredInvoice_AccountingSupplierParty"
    },
    "AccountingCustomerParty": {
      "$ref": "#/components/schemas/StructuredInvoice_AccountingCustomerParty"
    },
    "PayeeParty": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_PayeeParty"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "TaxRepresentativeParty": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_TaxRepresentativeParty"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "Delivery": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_Delivery"
        },
        {
          "items": {
            "$ref": "#/components/schemas/StructuredInvoice_Delivery"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Delivery"
    },
    "DeliveryTerms": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_DeliveryTerms"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "PaymentMeans": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_PaymentMeans"
        },
        {
          "items": {
            "$ref": "#/components/schemas/StructuredInvoice_PaymentMeans"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Paymentmeans"
    },
    "PaymentTerms": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_PaymentTerms"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "TaxTotal": {
      "$ref": "#/components/schemas/StructuredInvoice_TaxTotal"
    },
    "LegalMonetaryTotal": {
      "$ref": "#/components/schemas/StructuredInvoice_LegalMonetaryTotal"
    },
    "InvoiceLine": {
      "items": {
        "$ref": "#/components/schemas/StructuredInvoice_InvoiceLine"
      },
      "title": "Invoiceline",
      "type": "array"
    },
    "Note": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Note"
    },
    "BuyerReference": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Buyerreference"
    },
    "BuyerAccountingReference": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Buyeraccountingreference"
    }
  },
  "required": [
    "ID",
    "IssueDate",
    "InvoiceTypeCode",
    "DocumentCurrencyCode",
    "AccountingSupplierParty",
    "AccountingCustomerParty",
    "TaxTotal",
    "LegalMonetaryTotal",
    "InvoiceLine"
  ],
  "title": "Invoice Converter structured invoice JSON",
  "type": "object",
  "description": "Canonical invoice JSON for POST /api/v1/invoices:convert-structured. Element names follow UBL 2.1 / EN 16931. Send one invoice as one JSON data_file, either at the top level or wrapped in an 'invoice_data' object; this shape is mapped without AI interpretation. Detection needs at least 3 of the top-level keys ID, IssueDate, InvoiceTypeCode, DocumentCurrencyCode, AccountingSupplierParty, AccountingCustomerParty, TaxTotal, LegalMonetaryTotal, InvoiceLine, including ID, InvoiceLine, or LegalMonetaryTotal. Downloadable: https://www.invoice-converter.com/developer-api/v1/invoice-data.schema.json",
  "examples": [
    {
      "ID": "RE-2026-00123",
      "IssueDate": "2026-09-30",
      "DueDate": "2026-10-30",
      "InvoiceTypeCode": "380",
      "DocumentCurrencyCode": "EUR",
      "BuyerReference": "04011000-1234512345-06",
      "OrderReference": {
        "ID": "PO-4711"
      },
      "InvoicePeriod": {
        "StartDate": "2026-09-01",
        "EndDate": "2026-09-30"
      },
      "Note": "Monthly subscription September 2026",
      "AccountingSupplierParty": {
        "Party": {
          "EndpointID": {
            "#text": "billing@seller.example",
            "@schemeID": "EM"
          },
          "PartyName": {
            "Name": "Seller GmbH"
          },
          "PostalAddress": {
            "StreetName": "Hauptstraße 1",
            "CityName": "Berlin",
            "PostalZone": "10115",
            "Country": {
              "IdentificationCode": "DE"
            }
          },
          "PartyTaxScheme": {
            "CompanyID": "DE123456789",
            "TaxScheme": {
              "ID": "VAT"
            }
          },
          "PartyLegalEntity": {
            "RegistrationName": "Seller GmbH",
            "CompanyID": "HRB 12345"
          },
          "Contact": {
            "Name": "Erika Muster",
            "Telephone": "+49 30 123456",
            "ElectronicMail": "erika@seller.example"
          }
        }
      },
      "AccountingCustomerParty": {
        "Party": {
          "EndpointID": {
            "#text": "04011000-1234512345-06",
            "@schemeID": "0204"
          },
          "PartyName": {
            "Name": "Buyer AG"
          },
          "PostalAddress": {
            "StreetName": "Marktplatz 5",
            "CityName": "München",
            "PostalZone": "80331",
            "Country": {
              "IdentificationCode": "DE"
            }
          },
          "PartyTaxScheme": {
            "CompanyID": "DE987654321",
            "TaxScheme": {
              "ID": "VAT"
            }
          },
          "PartyLegalEntity": {
            "RegistrationName": "Buyer AG"
          }
        }
      },
      "Delivery": {
        "ActualDeliveryDate": "2026-09-30",
        "DeliveryLocation": {
          "Address": {
            "StreetName": "Marktplatz 5",
            "CityName": "München",
            "PostalZone": "80331",
            "Country": {
              "IdentificationCode": "DE"
            }
          }
        }
      },
      "PaymentMeans": {
        "PaymentMeansCode": "58",
        "PaymentID": "RE-2026-00123",
        "PayeeFinancialAccount": {
          "ID": "DE02120300000000202051",
          "Name": "Seller GmbH",
          "FinancialInstitutionBranch": {
            "ID": "BYLADEM1001"
          }
        }
      },
      "PaymentTerms": {
        "Note": "Zahlbar innerhalb von 30 Tagen ohne Abzug",
        "NetDays": 30
      },
      "TaxTotal": {
        "TaxAmount": "285.00",
        "TaxSubtotal": [
          {
            "TaxableAmount": "1500.00",
            "TaxAmount": "285.00",
            "TaxCategory": {
              "ID": "S",
              "Percent": 19,
              "TaxScheme": {
                "ID": "VAT"
              }
            }
          }
        ]
      },
      "LegalMonetaryTotal": {
        "LineExtensionAmount": "1500.00",
        "TaxExclusiveAmount": "1500.00",
        "TaxInclusiveAmount": "1785.00",
        "PayableAmount": "1785.00"
      },
      "InvoiceLine": [
        {
          "ID": "1",
          "InvoicedQuantity": 10,
          "unitCode": "HUR",
          "LineExtensionAmount": "1200.00",
          "Item": {
            "Name": "Consulting",
            "SellersItemIdentification": {
              "ID": "SRV-01"
            },
            "ClassifiedTaxCategory": {
              "ID": "S",
              "Percent": 19,
              "TaxScheme": {
                "ID": "VAT"
              }
            }
          },
          "Price": {
            "PriceAmount": "120.00"
          }
        },
        {
          "ID": "2",
          "InvoicedQuantity": 2,
          "unitCode": "C62",
          "LineExtensionAmount": "300.00",
          "Item": {
            "Name": "Software licence",
            "ClassifiedTaxCategory": {
              "ID": "S",
              "Percent": 19,
              "TaxScheme": {
                "ID": "VAT"
              }
            }
          },
          "Price": {
            "PriceAmount": "150.00"
          }
        }
      ]
    }
  ]
}
```

### `SellerMasterData`

```json
{
  "type": "object",
  "description": "Seller defaults sent as the JSON string form field `seller_master_data`. Every key is optional. `electronic_address` and `electronic_address_scheme` are a pair: send both or neither.",
  "properties": {
    "business_name": {
      "type": "string",
      "maxLength": 240,
      "description": "Legal name (BT-27)."
    },
    "trading_name": {
      "type": "string",
      "maxLength": 240,
      "description": "Trading name (BT-28)."
    },
    "street": {
      "type": "string",
      "description": "Street and number (BT-35)."
    },
    "additional_address": {
      "type": "string",
      "description": "Additional address line (BT-36)."
    },
    "postal_code": {
      "type": "string",
      "description": "Post code (BT-38)."
    },
    "city": {
      "type": "string",
      "description": "City (BT-37)."
    },
    "country": {
      "type": "string",
      "description": "ISO 3166-1 alpha-2 country code (BT-40).",
      "examples": [
        "DE"
      ]
    },
    "vat_id": {
      "type": "string",
      "description": "VAT identifier (BT-31).",
      "examples": [
        "DE123456789"
      ]
    },
    "tax_number": {
      "type": "string",
      "description": "Tax registration number (BT-32)."
    },
    "electronic_address": {
      "type": "string",
      "description": "Electronic address (BT-34). Requires `electronic_address_scheme`."
    },
    "electronic_address_scheme": {
      "type": "string",
      "description": "EAS scheme of the electronic address, for example `EM` or `0204`."
    },
    "contact_name": {
      "type": "string",
      "description": "Contact person (BT-41)."
    },
    "contact_email": {
      "type": "string",
      "description": "Contact e-mail (BT-43)."
    },
    "contact_phone": {
      "type": "string",
      "description": "Contact telephone (BT-42)."
    },
    "payment_means_code": {
      "type": "string",
      "enum": [
        "30",
        "42",
        "58"
      ],
      "description": "Credit transfer payment means code (BT-81): 30 credit transfer, 42 payment to bank account, 58 SEPA credit transfer."
    },
    "payment_accounts": {
      "type": "array",
      "maxItems": 5,
      "description": "Saved payee accounts, in output order. Each IBAN must be valid and unique. When master data applies, a non-empty list replaces all extracted credit-transfer accounts (codes 30/42/58); non-transfer means retain their existing selection rules.",
      "items": {
        "type": "object",
        "required": [
          "iban"
        ],
        "additionalProperties": false,
        "properties": {
          "iban": {
            "type": "string",
            "maxLength": 34,
            "description": "Valid payee IBAN (BT-84), normalized without spaces."
          },
          "bic": {
            "type": "string",
            "maxLength": 11,
            "description": "Payee bank BIC (BT-86), 8 or 11 characters when supplied."
          },
          "account_name": {
            "type": "string",
            "maxLength": 240,
            "description": "Payee account name (BT-85)."
          }
        }
      }
    },
    "payment_terms_note": {
      "type": "string",
      "description": "Payment terms text (BT-20)."
    }
  },
  "additionalProperties": false,
  "examples": [
    {
      "business_name": "Seller GmbH",
      "street": "Hauptstraße 1",
      "postal_code": "10115",
      "city": "Berlin",
      "country": "DE",
      "vat_id": "DE123456789",
      "electronic_address": "billing@seller.example",
      "electronic_address_scheme": "EM",
      "contact_name": "Erika Muster",
      "contact_email": "erika@seller.example",
      "contact_phone": "+49 30 123456",
      "payment_means_code": "58",
      "payment_accounts": [
        {
          "iban": "DE02120300000000202051"
        }
      ]
    }
  ]
}
```

### `ConvertAcceptedResponse`

```json
{
  "type": "object",
  "required": [
    "task_id",
    "status",
    "correlation_id"
  ],
  "properties": {
    "task_id": {
      "type": "string",
      "format": "uuid",
      "description": "Use it for all task calls."
    },
    "status": {
      "type": "string",
      "enum": [
        "pending",
        "processing"
      ],
      "description": "`pending`: queued. `processing`: started."
    },
    "message": {
      "type": "string",
      "description": "Human-readable confirmation. Do not branch on it."
    },
    "filename": {
      "type": [
        "string",
        "null"
      ],
      "description": "Uploaded document (or carrier PDF) filename."
    },
    "pdf_filename": {
      "type": [
        "string",
        "null"
      ],
      "description": "Carrier PDF filename (structured endpoint)."
    },
    "data_filename": {
      "type": [
        "string",
        "null"
      ],
      "description": "First data file name (structured endpoint)."
    },
    "data_filenames": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "All data file names (structured endpoint)."
    },
    "data_file_count": {
      "type": "integer",
      "minimum": 1,
      "description": "Number of data files (structured endpoint)."
    },
    "file_size": {
      "type": "integer",
      "minimum": 0,
      "description": "Total accepted bytes."
    },
    "pdf_file_size": {
      "type": "integer",
      "minimum": 0,
      "description": "Carrier PDF bytes (structured endpoint)."
    },
    "data_file_size": {
      "type": "integer",
      "minimum": 0,
      "description": "Data file bytes in total (structured endpoint)."
    },
    "correlation_id": {
      "type": "string",
      "format": "uuid"
    },
    "status_url": {
      "type": "string",
      "description": "Relative URL to poll."
    },
    "primary_result_format": {
      "type": "string",
      "enum": [
        "xml",
        "pdf"
      ],
      "description": "Usual download for the requested format: `pdf` for ZUGFERD, else `xml`."
    },
    "primary_result_url": {
      "type": "string",
      "description": "Relative result URL with `download=<primary_result_format>`."
    },
    "client_reference": {
      "type": "string",
      "description": "Echo of `client_reference`."
    },
    "source_system": {
      "type": "string",
      "description": "Echo of `source_system`."
    }
  },
  "additionalProperties": false
}
```

### `TaskStatusResponse`

```json
{
  "type": "object",
  "required": [
    "task_id",
    "status",
    "correlation_id"
  ],
  "properties": {
    "task_id": {
      "type": "string",
      "format": "uuid"
    },
    "status": {
      "type": "string",
      "enum": [
        "pending",
        "processing",
        "completed",
        "failed"
      ],
      "description": "`pending`: queued. `processing`: running. `completed`: a validated artifact exists. `failed`: terminal, no artifact."
    },
    "progress": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 0,
      "maximum": 100,
      "description": "Rough progress in percent. Do not use for timing."
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "description": "When the task was accepted (UTC)."
    },
    "completed_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "When the task reached `completed` or `failed` (UTC)."
    },
    "filename": {
      "type": [
        "string",
        "null"
      ]
    },
    "error": {
      "type": [
        "string",
        "object",
        "null"
      ],
      "additionalProperties": true,
      "description": "Failure summary when `status=failed`: a message or an object with `code`, `message`, `retryable`. Informational; `/result` returns the typed error envelope."
    },
    "correlation_id": {
      "type": "string",
      "format": "uuid",
      "description": "Trace ID of this status call."
    },
    "client_reference": {
      "type": [
        "string",
        "null"
      ],
      "description": "Echo of `client_reference`."
    },
    "source_system": {
      "type": [
        "string",
        "null"
      ],
      "description": "Echo of `source_system`."
    },
    "primary_result_format": {
      "type": "string",
      "enum": [
        "xml",
        "pdf"
      ],
      "description": "Usual download for the requested format."
    },
    "primary_result_url": {
      "type": "string",
      "description": "Relative result URL."
    },
    "result_artifacts": {
      "$ref": "#/components/schemas/ResultArtifacts"
    },
    "validation_report_html": {
      "$ref": "#/components/schemas/ValidationReportHtmlStatus"
    }
  },
  "additionalProperties": false
}
```

### `ResultArtifacts`

```json
{
  "type": "object",
  "description": "Download readiness per artifact.",
  "properties": {
    "xml": {
      "$ref": "#/components/schemas/ResultArtifactStatus"
    },
    "pdf": {
      "$ref": "#/components/schemas/ResultArtifactStatus"
    }
  },
  "additionalProperties": false
}
```

### `ResultArtifactStatus`

```json
{
  "type": "object",
  "required": [
    "state",
    "download_url"
  ],
  "properties": {
    "state": {
      "type": "string",
      "enum": [
        "cached",
        "not_ready",
        "validation_failed",
        "dependency_failed",
        "artifact_generation_rerun_required",
        "artifact_invariant_failed"
      ],
      "description": "`cached`: downloadable. `not_ready`: not produced yet. `validation_failed`: blocking data or source-PDF issue. `dependency_failed`: validator/storage outage. `artifact_generation_rerun_required`: start a new conversion. `artifact_invariant_failed`: escalate with the correlation ID."
    },
    "download_url": {
      "type": "string",
      "description": "Relative download URL."
    },
    "content_type": {
      "type": "string"
    },
    "filename": {
      "type": "string"
    },
    "bytes": {
      "type": "integer",
      "minimum": 0
    },
    "artifact_state": {
      "type": "string",
      "enum": [
        "compliant",
        "warning_only",
        "cannot_guarantee",
        "blocked"
      ],
      "description": "Compliance standing. `compliant` on every delivered API artifact."
    },
    "validation_state": {
      "type": "string",
      "enum": [
        "passed",
        "failed_overridable",
        "failed_blocking",
        "not_validated"
      ],
      "description": "Validation outcome. `passed` on every delivered API artifact."
    }
  },
  "additionalProperties": false
}
```

### `ValidationReportHtmlStatus`

```json
{
  "type": "object",
  "description": "Present only with `include_validation_report_html=true`.",
  "required": [
    "available"
  ],
  "properties": {
    "available": {
      "type": "boolean"
    },
    "content_type": {
      "type": "string",
      "enum": [
        "text/html; charset=utf-8"
      ]
    },
    "html": {
      "type": "string",
      "description": "Sanitized report HTML; server paths are redacted."
    },
    "source": {
      "type": "string",
      "description": "For example `artifact`, `embedded_xml`, or `source_xml`."
    },
    "source_result_format": {
      "type": "string",
      "enum": [
        "xml",
        "pdf"
      ]
    },
    "reason": {
      "type": "string",
      "description": "Why no report is available, for example `task_not_completed`, `proof_not_found`, `artifact_not_current`."
    }
  },
  "additionalProperties": false
}
```

### `ErrorEnvelope`

```json
{
  "type": "object",
  "description": "Every JSON error. Branch on `code`; for `500 TASK_FAILED` also on `details.code` and `details.retryable`. Retry a write only with the same Idempotency-Key.",
  "required": [
    "code",
    "message",
    "correlation_id"
  ],
  "properties": {
    "code": {
      "type": "string",
      "enum": [
        "AUTHENTICATION_REQUIRED",
        "INVALID_API_KEY",
        "API_NOT_ENABLED_FOR_TENANT",
        "ACCOUNT_DELETED",
        "INSUFFICIENT_API_CREDITS",
        "AUTH_SERVICE_UNAVAILABLE",
        "PLAN_TIER_CHECK_FAILED",
        "RATE_LIMIT_SERVICE_UNAVAILABLE",
        "API_CREDIT_SERVICE_UNAVAILABLE",
        "RATE_LIMITED",
        "IDEMPOTENCY_KEY_REQUIRED",
        "INVALID_IDEMPOTENCY_KEY",
        "IDEMPOTENCY_IN_PROGRESS",
        "IDEMPOTENCY_CONFLICT",
        "IDEMPOTENCY_REPLAY_EXPIRED",
        "IDEMPOTENCY_KEY_ALREADY_USED",
        "FORMAT_REQUIRED",
        "INVALID_FORMAT",
        "INVALID_PROFILE",
        "OUTPUT_PROFILE_CONFLICT",
        "OUTPUT_PROFILE_REQUIRED",
        "CLIENT_REFERENCE_CONFLICT",
        "INVALID_CLIENT_METADATA",
        "INVALID_SELLER_MASTER_DATA",
        "INVALID_EMBEDDED_XML_POLICY",
        "INVALID_EMAIL_INPUT",
        "INVALID_UPLOAD",
        "PAYLOAD_TOO_LARGE",
        "UPLOAD_FAILED",
        "SERVER_BUSY",
        "ZUGFERD_SOURCE_PDF_REQUIRED",
        "METHOD_NOT_ALLOWED",
        "NOT_FOUND",
        "BAD_REQUEST",
        "INVALID_QUERY_PARAMETER",
        "DOWNLOAD_FORMAT_REQUIRED",
        "INVALID_DOWNLOAD_FORMAT",
        "TASK_NOT_READY",
        "TASK_NOT_FOUND",
        "TASK_STATUS_FAILED",
        "TASK_RESULT_FAILED",
        "TASK_FAILED",
        "VALIDATION_FAILED",
        "DOCUMENT_NOT_CONVERTIBLE",
        "PROFILE_MISMATCH",
        "ZUGFERD_SOURCE_PDF_INCOMPATIBLE",
        "PROTECTED_BANK_DETAILS_MISMATCH",
        "ZUGFERD_CII_CONVERSION_FAILED",
        "ZUGFERD_PDF_GENERATION_FAILED",
        "XML_GENERATION_FAILED",
        "PDF_GENERATION_FAILED",
        "ARTIFACT_GENERATION_RERUN_REQUIRED",
        "EXTRACTION_INCOMPLETE_GROUP_FAILURE",
        "INTERNAL_ARTIFACT_INVARIANT_FAILED",
        "VALIDATION_REPORT_NOT_FOUND",
        "VALIDATION_REPORT_FAILED",
        "PROXY_ERROR"
      ],
      "x-enumDescriptions": {
        "AUTHENTICATION_REQUIRED": "401 · no · Send `Authorization: Bearer <api_key>`.",
        "INVALID_API_KEY": "401 · no · The key is unknown, revoked, or malformed. Fix or rotate it.",
        "API_NOT_ENABLED_FOR_TENANT": "403 · no · The key is valid but the account has no External API access. Activate an Enterprise subscription at `details.action_url` or contact support.",
        "ACCOUNT_DELETED": "410 · no · The account of this API key was deleted. The deletion is permanent. A revoked key returns `INVALID_API_KEY`.",
        "INSUFFICIENT_API_CREDITS": "402 · no · Allowance and prepaid credits are used up. Buy a credit package at `details.action_url` or wait for the next month. Two `details` shapes.",
        "AUTH_SERVICE_UNAVAILABLE": "503 · yes · Authentication is temporarily unavailable. Retry with backoff and the same Idempotency-Key.",
        "PLAN_TIER_CHECK_FAILED": "503 · yes · Plan/API access could not be verified. Retry with backoff and the same Idempotency-Key.",
        "RATE_LIMIT_SERVICE_UNAVAILABLE": "503 · yes · The rate-limit service is unavailable. Retry with backoff and the same Idempotency-Key.",
        "API_CREDIT_SERVICE_UNAVAILABLE": "503 · yes · Credit/allowance verification is unavailable. Retry the upload with the same Idempotency-Key.",
        "RATE_LIMITED": "429 · yes · Wait `Retry-After` seconds, then retry with the same Idempotency-Key.",
        "IDEMPOTENCY_KEY_REQUIRED": "400 · no · Send an `Idempotency-Key` header on both POST endpoints.",
        "INVALID_IDEMPOTENCY_KEY": "400 · no · Use 1–200 chars matching `^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$`.",
        "IDEMPOTENCY_IN_PROGRESS": "409 · yes · The first request with this key is still running. Retry the same key after a short delay.",
        "IDEMPOTENCY_CONFLICT": "409 · no · The key was used with a different payload. Use a new key for a new payload.",
        "IDEMPOTENCY_REPLAY_EXPIRED": "409 · no · The original task is past its 24 h retention. Start a new conversion with a new key.",
        "IDEMPOTENCY_KEY_ALREADY_USED": "409 · no · The key was already used for a completed conversion, and its 24 h replay records have expired. Use a new key for a new conversion.",
        "FORMAT_REQUIRED": "400 · no · Send `format` on every conversion request.",
        "INVALID_FORMAT": "422 · no · Send one of XRECHNUNG, ZUGFERD, EN16931, UBL, CII.",
        "INVALID_PROFILE": "422 · no · Unknown profile name. `details.allowed_profiles` lists the accepted values.",
        "OUTPUT_PROFILE_CONFLICT": "422 · no · The profile is not accepted for this `format`. Send a compatible profile or omit it.",
        "OUTPUT_PROFILE_REQUIRED": "422 · no · Defensive; V1 defaults a profile for every format, so this is not expected.",
        "CLIENT_REFERENCE_CONFLICT": "400 · no · `client_reference` and `external_invoice_id` differ. Send one, or the same value in both.",
        "INVALID_CLIENT_METADATA": "400 · no · Keep `client_reference`/`external_invoice_id` ≤ 200 and `source_system` ≤ 100 chars, without control characters.",
        "INVALID_SELLER_MASTER_DATA": "400 · no · Send `seller_master_data` as a JSON object string with supported keys; send `electronic_address` and `electronic_address_scheme` together.",
        "INVALID_EMBEDDED_XML_POLICY": "400 · no · Send `use_embedded_xml` as `true` or `false`, or omit it.",
        "INVALID_EMAIL_INPUT": "400 · no · Send `email_input` once, ≤ 10,000 chars, PDF source only, not with `use_embedded_xml=true`, never on convert-structured.",
        "INVALID_UPLOAD": "400/415 · no · Fix the upload: multipart/form-data, supported file type, ≤ 20 file parts and 50 fields, one invoice number across all `data_file` parts (`details.reason`).",
        "PAYLOAD_TOO_LARGE": "413 · no · A file, the `data_file` total, or the multipart body exceeds its backend limit. Inspect `details.limit_bytes`; send a smaller request.",
        "UPLOAD_FAILED": "422 · no: invalid `jurisdiction`/`transaction_scope`/`delivery_channel` value. 500/503 · yes: the upload was not accepted, or it was accepted but its first response could not be rebuilt. Retry with backoff and the same Idempotency-Key; the retry returns the accepted task.",
        "SERVER_BUSY": "503 · yes · The processing queue is full. Wait `Retry-After` seconds (15), then retry with the same Idempotency-Key.",
        "ZUGFERD_SOURCE_PDF_REQUIRED": "422 · no · `format=ZUGFERD` needs a PDF source. Upload a PDF or choose an XML format.",
        "METHOD_NOT_ALLOWED": "405 · no · Use POST on conversion paths and GET on task paths (see `Allow`).",
        "NOT_FOUND": "404 · no · Unknown path under /api/v1.",
        "BAD_REQUEST": "400 · no · `task_id` must be a UUID.",
        "INVALID_QUERY_PARAMETER": "400 · no · Send `include_validation_report_html` as `true` or `false`.",
        "DOWNLOAD_FORMAT_REQUIRED": "400 · no · Send the required `download` query parameter.",
        "INVALID_DOWNLOAD_FORMAT": "400 · no · Use `download=xml|pdf` on /result and `download=html|xml` on /validation-report.",
        "TASK_NOT_READY": "202 · poll · The task is still running. Keep polling task status with backoff.",
        "TASK_NOT_FOUND": "404 · no · Unknown task, another tenant's task, or deleted 24 h after completion. All task endpoints. On `/tasks/{task_id}` and `/result` also a task not accepted through this API.",
        "TASK_STATUS_FAILED": "5xx · yes · The status could not be read. Retry the poll with backoff.",
        "TASK_RESULT_FAILED": "404/5xx · 5xx only · The result could not be read (for example missing task metadata). Retry 5xx with backoff; escalate a 404 with the correlation ID.",
        "TASK_FAILED": "500 · only if `details.retryable` is true · Read `details.code`. Retryable failures need a NEW conversion with a new Idempotency-Key.",
        "VALIDATION_FAILED": "422 · no · Blocking validation errors. Correct the data (`details.items`) and start a new conversion.",
        "DOCUMENT_NOT_CONVERTIBLE": "422 · no · The source document cannot be converted as sent (reason in `details.code`, next step in `details.recovery_hint`). Fix the document and start a new conversion.",
        "PROFILE_MISMATCH": "422 · no · The stored document declares another profile. Start a new conversion with the correct profile.",
        "ZUGFERD_SOURCE_PDF_INCOMPATIBLE": "422 · no · The source PDF cannot carry a strict PDF/A-3 hybrid. Normalize the PDF or use `download=xml`.",
        "PROTECTED_BANK_DETAILS_MISMATCH": "422 · no · A payee IBAN (BT-84) is not one of the bank accounts that the account's control address protects. No file was issued and no unit was used. Correct the IBAN in the source document, or add the account in the profile (the control address must confirm it), then start a new conversion.",
        "ZUGFERD_CII_CONVERSION_FAILED": "422/500 · no · Hybrid CII conversion failed. Escalate with the correlation ID.",
        "ZUGFERD_PDF_GENERATION_FAILED": "500 · no · Hybrid PDF generation failed. Escalate with the correlation ID.",
        "XML_GENERATION_FAILED": "500 · yes, with backoff · Legacy on-demand generation path; not expected for strict API tasks.",
        "PDF_GENERATION_FAILED": "500 · yes, with backoff · Legacy on-demand generation path; not expected for strict API tasks.",
        "ARTIFACT_GENERATION_RERUN_REQUIRED": "409 · new task · No artifact was issued: generation or authoritative validation failed after server retries (reason in `details.code`, for example `AUTHORITATIVE_VALIDATION_UNAVAILABLE`). Start a new conversion with a new Idempotency-Key.",
        "EXTRACTION_INCOMPLETE_GROUP_FAILURE": "409 · new task · Extraction groups failed (`details.failed_groups`). Start a new conversion with a new Idempotency-Key.",
        "INTERNAL_ARTIFACT_INVARIANT_FAILED": "500 · no · Completed task without a safe stored artifact. Escalate with the correlation ID.",
        "VALIDATION_REPORT_NOT_FOUND": "404 · no · No report is bound to the current artifact (`details.reason`).",
        "VALIDATION_REPORT_FAILED": "4xx/5xx · 5xx only · Report retrieval failed. Retry transient 5xx with backoff.",
        "PROXY_ERROR": "502/504 · yes · Transport failure between edge and backend. Retry with backoff and the same Idempotency-Key."
      },
      "description": "Machine-readable error code. Format of each description: HTTP status · retry? · action."
    },
    "message": {
      "type": "string",
      "description": "Human-readable text. Do not parse it."
    },
    "correlation_id": {
      "type": "string",
      "format": "uuid",
      "description": "Quote it to support."
    },
    "details": {
      "$ref": "#/components/schemas/ErrorDetails"
    }
  },
  "additionalProperties": false
}
```

### `EdgeError`

```json
{
  "type": "object",
  "description": "Error sent by the edge proxy before the request reaches the API (`404 NOT_FOUND`, `405 METHOD_NOT_ALLOWED`). No `correlation_id`.",
  "required": [
    "code",
    "message"
  ],
  "properties": {
    "code": {
      "type": "string",
      "enum": [
        "NOT_FOUND",
        "METHOD_NOT_ALLOWED"
      ]
    },
    "message": {
      "type": "string"
    }
  }
}
```

### `ErrorDetails`

```json
{
  "type": "object",
  "description": "Structured context. The keys depend on the code; unknown keys can appear. `type` is usually present but not always (for example `{\"field\": \"download\"}`, `INVALID_UPLOAD`, `413`), so branch on the envelope `code`.",
  "properties": {
    "type": {
      "type": "string",
      "description": "Detail family, for example `validation`, `rate_limit`, `idempotency_conflict`, `idempotency_in_progress`, `profile_mismatch`, `context`, `dependency`, `artifact_generation`, `validation_report`, `access`, `message`."
    },
    "code": {
      "type": "string",
      "description": "Underlying failure code: the reason on `500 TASK_FAILED`, `422 DOCUMENT_NOT_CONVERTIBLE` and `409 ARTIFACT_GENERATION_RERUN_REQUIRED`; see `x-enumDescriptions`.",
      "examples": [
        "MULTIPLE_INVOICES_IN_DOCUMENT",
        "NO_INVOICE_DETECTED",
        "INSUFFICIENT_INVOICE_SIGNAL",
        "EMBEDDED_INVOICE_XML_INVALID",
        "EMBEDDED_INVOICE_XML_UNREPRESENTABLE",
        "SOURCE_TEXT_UNAVAILABLE",
        "SCHEMA_PARSE_FAILED",
        "ARTIFACT_PARITY_FAILED",
        "PROVIDER_ERROR",
        "task_interrupted",
        "AUTHORITATIVE_VALIDATION_UNAVAILABLE"
      ],
      "x-enumDescriptions": {
        "MULTIPLE_INVOICES_IN_DOCUMENT": "Terminal. The document holds more than one invoice. Split it and convert each invoice separately.",
        "NO_INVOICE_DETECTED": "Terminal. The document is not an invoice. Route it to a person.",
        "INSUFFICIENT_INVOICE_SIGNAL": "Terminal. Too little invoice data. Send a better source or use convert-structured.",
        "EMBEDDED_INVOICE_XML_INVALID": "Terminal. Only with `use_embedded_xml=true`: the XML embedded in the PDF could not be read. Correct it in the issuing system, or send the PDF without `use_embedded_xml`.",
        "EMBEDDED_INVOICE_XML_UNREPRESENTABLE": "Terminal. Only with `use_embedded_xml=true`: the embedded XML holds a value that cannot be transferred unchanged, for example a date not in format 102 (`YYYYMMDD`). Correct it in the issuing system, or send the PDF without `use_embedded_xml`.",
        "SOURCE_TEXT_UNAVAILABLE": "See `retryable`. false: no readable text (upload a text PDF or a clearer scan). true: OCR was temporarily unavailable; start a new conversion.",
        "SCHEMA_PARSE_FAILED": "Terminal for this attempt. Start a new conversion; escalate if it repeats.",
        "ARTIFACT_PARITY_FAILED": "Terminal. The artifact did not match the final invoice data. Escalate with the correlation ID.",
        "PROVIDER_ERROR": "See `retryable`. true: start a new conversion after a delay. `classification=provider_context_too_large`: send a smaller document.",
        "task_interrupted": "Retryable. The server running the conversion stopped before it finished. No artifact was issued and no unit was used. Start a new conversion with a new key.",
        "AUTHORITATIVE_VALIDATION_UNAVAILABLE": "On `409 ARTIFACT_GENERATION_RERUN_REQUIRED`: the validator or another artifact dependency stayed unavailable after server-side retries. No artifact was issued and no unit was used. Start a new conversion with a new Idempotency-Key."
      }
    },
    "retryable": {
      "type": "boolean",
      "description": "Authoritative where present. `true` on `TASK_FAILED`: start a NEW conversion with a new Idempotency-Key."
    },
    "can_review": {
      "type": "boolean"
    },
    "classification": {
      "type": "string",
      "description": "For example `multiple_invoices`, `not_invoice`, `provider_context_too_large`."
    },
    "category": {
      "type": "string"
    },
    "recovery_hint": {
      "type": "string",
      "description": "Human-readable next step."
    },
    "same_task_retryable": {
      "type": "boolean",
      "description": "`false`: the same task cannot recover; start a new conversion."
    },
    "recovery": {
      "type": "string",
      "description": "Machine-readable next step: `start_new_conversion`, `fix_source_document`, `buy_api_credits`, or `activate_api_access`."
    },
    "action_url": {
      "type": "string",
      "format": "uri",
      "description": "Page where the account owner resolves `402 INSUFFICIENT_API_CREDITS` (buy credits) or `403 API_NOT_ENABLED_FOR_TENANT` (activate API access)."
    },
    "dependency": {
      "type": "string"
    },
    "stage": {
      "type": "string"
    },
    "failed_groups": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Failed extraction groups on `EXTRACTION_INCOMPLETE_GROUP_FAILURE`."
    },
    "items": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/ValidationDetail"
      },
      "description": "Blocking issues on `VALIDATION_FAILED`."
    },
    "field": {
      "type": "string",
      "description": "Offending request field, for example `download` or `file`."
    },
    "reason": {
      "type": "string",
      "description": "Sub-reason, for example `bundle_invoice_id_missing`, `bundle_invoice_id_mismatch`, `different_payload_for_same_key`."
    },
    "profile": {
      "type": "string"
    },
    "format": {
      "type": "string"
    },
    "allowed_profiles": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Accepted profiles on the profile errors."
    },
    "minute_count": {
      "type": "integer"
    },
    "hour_count": {
      "type": "integer"
    },
    "limit_minute": {
      "type": "integer"
    },
    "limit_hour": {
      "type": "integer"
    },
    "limit_bytes": {
      "type": "integer",
      "description": "Size limit on `413 PAYLOAD_TOO_LARGE`."
    },
    "declared_size": {
      "type": "integer"
    },
    "received_bytes": {
      "type": "integer"
    },
    "remaining": {
      "type": "integer"
    },
    "included_remaining": {
      "type": "integer"
    },
    "credit_remaining": {
      "type": [
        "integer",
        "null"
      ]
    },
    "shortfall": {
      "type": "integer"
    },
    "minimum_purchase": {
      "type": "integer"
    },
    "bridge_status": {
      "type": "integer"
    }
  },
  "additionalProperties": true
}
```

### `ValidationDetail`

```json
{
  "type": "object",
  "description": "One blocking validation issue.",
  "properties": {
    "field": {
      "type": [
        "string",
        "null"
      ],
      "description": "Invoice field path, for example `BuyerReference`."
    },
    "business_term": {
      "type": [
        "string",
        "null"
      ],
      "description": "EN 16931 business term of the field when known, for example `BT-10`."
    },
    "rule_id": {
      "type": [
        "string",
        "null"
      ],
      "description": "Rule ID, for example `BR-DE-15`."
    },
    "severity": {
      "type": [
        "string",
        "null"
      ]
    },
    "source": {
      "type": [
        "string",
        "null"
      ]
    },
    "suggestion": {
      "type": [
        "string",
        "null"
      ],
      "description": "What to correct."
    },
    "message": {
      "type": [
        "string",
        "null"
      ]
    }
  },
  "additionalProperties": true
}
```

### `InsufficientApiCreditsPrepaidError`

```json
{
  "type": "object",
  "description": "402 shape for prepaid-only accounts.",
  "required": [
    "code",
    "message",
    "correlation_id",
    "details"
  ],
  "properties": {
    "code": {
      "type": "string",
      "const": "INSUFFICIENT_API_CREDITS"
    },
    "message": {
      "type": "string"
    },
    "correlation_id": {
      "type": "string",
      "format": "uuid"
    },
    "details": {
      "type": "object",
      "required": [
        "type",
        "remaining",
        "minimum_purchase",
        "recovery",
        "action_url"
      ],
      "properties": {
        "type": {
          "type": "string",
          "const": "context"
        },
        "remaining": {
          "type": "integer",
          "description": "Prepaid credits left."
        },
        "minimum_purchase": {
          "type": "integer",
          "description": "Smallest credit package (100)."
        },
        "recovery": {
          "type": "string",
          "const": "buy_api_credits"
        },
        "action_url": {
          "type": "string",
          "format": "uri",
          "description": "Profile page that sells API credit packages."
        }
      },
      "additionalProperties": true
    }
  },
  "additionalProperties": false
}
```

### `InsufficientApiCreditsAllowanceError`

```json
{
  "type": "object",
  "description": "402 shape for accounts with an enforced included allowance.",
  "required": [
    "code",
    "message",
    "correlation_id",
    "details"
  ],
  "properties": {
    "code": {
      "type": "string",
      "const": "INSUFFICIENT_API_CREDITS"
    },
    "message": {
      "type": "string"
    },
    "correlation_id": {
      "type": "string",
      "format": "uuid"
    },
    "details": {
      "type": "object",
      "required": [
        "type",
        "included_remaining",
        "credit_remaining",
        "shortfall",
        "minimum_purchase",
        "recovery",
        "action_url"
      ],
      "properties": {
        "type": {
          "type": "string",
          "const": "context"
        },
        "included_remaining": {
          "type": "integer",
          "description": "Allowance left this month."
        },
        "credit_remaining": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Prepaid credits left, or null."
        },
        "shortfall": {
          "type": "integer",
          "description": "Units not covered."
        },
        "minimum_purchase": {
          "type": "integer",
          "description": "Smallest credit package (100)."
        },
        "recovery": {
          "type": "string",
          "const": "buy_api_credits"
        },
        "action_url": {
          "type": "string",
          "format": "uri",
          "description": "Profile page that sells API credit packages."
        }
      },
      "additionalProperties": true
    }
  },
  "additionalProperties": false
}
```

### `StructuredInvoice_AccountingCustomerParty`

```json
{
  "additionalProperties": false,
  "properties": {
    "Party": {
      "$ref": "#/components/schemas/StructuredInvoice_Party"
    }
  },
  "required": [
    "Party"
  ],
  "title": "AccountingCustomerParty",
  "type": "object"
}
```

### `StructuredInvoice_AccountingSupplierParty`

```json
{
  "additionalProperties": false,
  "properties": {
    "Party": {
      "$ref": "#/components/schemas/StructuredInvoice_Party"
    }
  },
  "required": [
    "Party"
  ],
  "title": "AccountingSupplierParty",
  "type": "object"
}
```

### `StructuredInvoice_AdditionalDocumentReference`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Id"
    },
    "DocumentTypeCode": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Documenttypecode"
    },
    "DocumentDescription": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Documentdescription"
    },
    "Attachment": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_Attachment"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    }
  },
  "title": "AdditionalDocumentReference",
  "type": "object"
}
```

### `StructuredInvoice_AdvancePaymentSettlementRow`

```json
{
  "additionalProperties": false,
  "description": "One received advance payment that a cumulative final invoice deducts in BT-113.\n\nThe rows are not an EN 16931 group: the e-invoice carries them as a settlement-table PDF\nattachment (BG-24, ID \"advance-settlement\"). Give only values printed on the advance;\nVAT is never derived from the gross amount. The gross amounts must add up to BT-113.",
  "properties": {
    "ID": {
      "maxLength": 200,
      "minLength": 1,
      "title": "Id",
      "type": "string"
    },
    "IssueDate": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Issuedate"
    },
    "NetAmount": {
      "anyOf": [
        {
          "minimum": 0,
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Netamount"
    },
    "TaxPercent": {
      "anyOf": [
        {
          "maximum": 100,
          "minimum": 0,
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Taxpercent"
    },
    "TaxAmount": {
      "anyOf": [
        {
          "minimum": 0,
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Taxamount"
    },
    "GrossAmount": {
      "anyOf": [
        {
          "minimum": 0,
          "type": "number"
        },
        {
          "type": "string"
        }
      ],
      "title": "Grossamount"
    }
  },
  "required": [
    "ID",
    "GrossAmount"
  ],
  "title": "AdvancePaymentSettlementRow",
  "type": "object"
}
```

### `StructuredInvoice_AllowanceCharge`

```json
{
  "additionalProperties": false,
  "description": "Document-level allowance or charge (BG-20/BG-21)",
  "properties": {
    "ChargeIndicator": {
      "title": "Chargeindicator",
      "type": "boolean"
    },
    "AllowanceChargeReasonCode": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Allowancechargereasoncode"
    },
    "AllowanceChargeReason": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Allowancechargereason"
    },
    "MultiplierFactorNumeric": {
      "anyOf": [
        {
          "maximum": 100,
          "minimum": 0,
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Source percentage points exactly as printed. 30% is 30, never 0.3; 0.3% remains 0.3. Never convert percentage points to decimal factors.",
      "title": "Multiplierfactornumeric"
    },
    "BaseAmount": {
      "anyOf": [
        {
          "minimum": 0,
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Baseamount"
    },
    "Amount": {
      "anyOf": [
        {
          "minimum": 0,
          "type": "number"
        },
        {
          "type": "string"
        }
      ],
      "title": "Amount"
    },
    "TaxCategory": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_AllowanceChargeTaxCategory"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    }
  },
  "required": [
    "ChargeIndicator",
    "Amount"
  ],
  "title": "AllowanceCharge",
  "type": "object"
}
```

### `StructuredInvoice_AllowanceChargeTaxCategory`

```json
{
  "additionalProperties": false,
  "description": "Tax category for document-level allowance/charge (BG-21)",
  "properties": {
    "ID": {
      "title": "Id",
      "type": "string"
    },
    "Percent": {
      "anyOf": [
        {
          "maximum": 100,
          "minimum": 0,
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Percent"
    },
    "TaxScheme": {
      "$ref": "#/components/schemas/StructuredInvoice_TaxScheme"
    }
  },
  "required": [
    "ID",
    "TaxScheme"
  ],
  "title": "AllowanceChargeTaxCategory",
  "type": "object"
}
```

### `StructuredInvoice_Attachment`

```json
{
  "additionalProperties": false,
  "properties": {
    "EmbeddedDocumentBinaryObject": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_EmbeddedDocumentBinaryObject"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "ExternalReference": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_ExternalReference"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    }
  },
  "title": "Attachment",
  "type": "object"
}
```

### `StructuredInvoice_BuyersItemIdentification`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "title": "Id",
      "type": "string"
    }
  },
  "required": [
    "ID"
  ],
  "title": "BuyersItemIdentification",
  "type": "object"
}
```

### `StructuredInvoice_CardAccount`

```json
{
  "additionalProperties": false,
  "properties": {
    "PrimaryAccountNumberID": {
      "title": "Primaryaccountnumberid",
      "type": "string"
    },
    "NetworkID": {
      "title": "Networkid",
      "type": "string"
    },
    "HolderName": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Holdername"
    }
  },
  "required": [
    "PrimaryAccountNumberID",
    "NetworkID"
  ],
  "title": "CardAccount",
  "type": "object"
}
```

### `StructuredInvoice_ClassifiedTaxCategory`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "title": "Id",
      "type": "string"
    },
    "Percent": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Percent"
    },
    "TaxExemptionReasonCode": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Taxexemptionreasoncode"
    },
    "TaxExemptionReason": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Taxexemptionreason"
    },
    "TaxScheme": {
      "$ref": "#/components/schemas/StructuredInvoice_TaxScheme"
    }
  },
  "required": [
    "ID",
    "TaxScheme"
  ],
  "title": "ClassifiedTaxCategory",
  "type": "object"
}
```

### `StructuredInvoice_CommodityClassification`

```json
{
  "additionalProperties": false,
  "properties": {
    "ItemClassificationCode": {
      "$ref": "#/components/schemas/StructuredInvoice_ItemClassificationCode"
    }
  },
  "required": [
    "ItemClassificationCode"
  ],
  "title": "CommodityClassification",
  "type": "object"
}
```

### `StructuredInvoice_Contact`

```json
{
  "additionalProperties": false,
  "properties": {
    "Name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Name"
    },
    "Telephone": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Telephone"
    },
    "ElectronicMail": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Electronicmail"
    }
  },
  "title": "Contact",
  "type": "object"
}
```

### `StructuredInvoice_ContractDocumentReference`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "minLength": 1,
      "title": "Id",
      "type": "string"
    }
  },
  "required": [
    "ID"
  ],
  "title": "ContractDocumentReference",
  "type": "object"
}
```

### `StructuredInvoice_Country`

```json
{
  "additionalProperties": false,
  "properties": {
    "IdentificationCode": {
      "title": "Identificationcode",
      "type": "string"
    }
  },
  "required": [
    "IdentificationCode"
  ],
  "title": "Country",
  "type": "object"
}
```

### `StructuredInvoice_Delivery`

```json
{
  "additionalProperties": false,
  "properties": {
    "ActualDeliveryDate": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Actualdeliverydate"
    },
    "DeliveryLocation": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_DeliveryLocation"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "DeliveryParty": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_Party"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    }
  },
  "title": "Delivery",
  "type": "object"
}
```

### `StructuredInvoice_DeliveryAddress`

```json
{
  "additionalProperties": false,
  "properties": {
    "StreetName": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Streetname"
    },
    "AdditionalStreetName": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Additionalstreetname"
    },
    "CityName": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Cityname"
    },
    "PostalZone": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Postalzone"
    },
    "CountrySubentity": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Countrysubentity"
    },
    "Country": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_Country"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    }
  },
  "title": "DeliveryAddress",
  "type": "object"
}
```

### `StructuredInvoice_DeliveryLocation`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "additionalProperties": {
            "type": "string"
          },
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Id"
    },
    "schemeID": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Schemeid"
    },
    "Address": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_DeliveryAddress"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    }
  },
  "title": "DeliveryLocation",
  "type": "object"
}
```

### `StructuredInvoice_DeliveryTerms`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Id"
    },
    "SpecialTerms": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Specialterms"
    }
  },
  "title": "DeliveryTerms",
  "type": "object"
}
```

### `StructuredInvoice_DespatchDocumentReference`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "minLength": 1,
      "title": "Id",
      "type": "string"
    }
  },
  "required": [
    "ID"
  ],
  "title": "DespatchDocumentReference",
  "type": "object"
}
```

### `StructuredInvoice_EmbeddedDocumentBinaryObject`

```json
{
  "additionalProperties": false,
  "properties": {
    "#text": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "#Text"
    },
    "mimeCode": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Mimecode"
    },
    "filename": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Filename"
    }
  },
  "title": "EmbeddedDocumentBinaryObject",
  "type": "object"
}
```

### `StructuredInvoice_EndpointID`

```json
{
  "additionalProperties": false,
  "properties": {
    "#text": {
      "title": "#Text",
      "type": "string"
    },
    "@schemeID": {
      "title": "@Schemeid",
      "type": "string"
    }
  },
  "required": [
    "#text",
    "@schemeID"
  ],
  "title": "EndpointID",
  "type": "object"
}
```

### `StructuredInvoice_ExternalReference`

```json
{
  "additionalProperties": false,
  "properties": {
    "URI": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Uri"
    }
  },
  "title": "ExternalReference",
  "type": "object"
}
```

### `StructuredInvoice_FinancialInstitutionBranch`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "title": "Id",
      "type": "string"
    }
  },
  "required": [
    "ID"
  ],
  "title": "FinancialInstitutionBranch",
  "type": "object"
}
```

### `StructuredInvoice_InvoiceLine`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "description": "Line identifier - use the exact position number from the original invoice (e.g., '1.1.30', '10', '001'). Fall back to sequential '1', '2', '3' only when no explicit identifiers exist. NOT the item name.",
      "title": "Id",
      "type": "string"
    },
    "Note": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Note"
    },
    "InvoicedQuantity": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        }
      ],
      "title": "Invoicedquantity"
    },
    "unitCode": {
      "title": "Unitcode",
      "type": "string"
    },
    "LineExtensionAmount": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        }
      ],
      "title": "Lineextensionamount"
    },
    "PeriodStart": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Periodstart"
    },
    "PeriodEnd": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Periodend"
    },
    "InvoicePeriod": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_InvoicePeriod"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "OrderLineReference": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Orderlinereference"
    },
    "Item": {
      "$ref": "#/components/schemas/StructuredInvoice_Item"
    },
    "Price": {
      "$ref": "#/components/schemas/StructuredInvoice_Price"
    },
    "AllowanceCharge": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_AllowanceCharge"
        },
        {
          "items": {
            "$ref": "#/components/schemas/StructuredInvoice_AllowanceCharge"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Allowancecharge"
    }
  },
  "required": [
    "ID",
    "InvoicedQuantity",
    "unitCode",
    "LineExtensionAmount",
    "Item",
    "Price"
  ],
  "title": "InvoiceLine",
  "type": "object"
}
```

### `StructuredInvoice_InvoicePeriod`

```json
{
  "additionalProperties": false,
  "properties": {
    "StartDate": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Startdate"
    },
    "EndDate": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Enddate"
    },
    "DescriptionCode": {
      "anyOf": [
        {
          "enum": [
            "3",
            "35",
            "432"
          ],
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Descriptioncode"
    }
  },
  "title": "InvoicePeriod",
  "type": "object"
}
```

### `StructuredInvoice_Item`

```json
{
  "additionalProperties": false,
  "properties": {
    "Description": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Description"
    },
    "Name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Name"
    },
    "BuyersItemIdentification": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_BuyersItemIdentification"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "SellersItemIdentification": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_SellersItemIdentification"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "StandardItemIdentification": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_StandardItemIdentification"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "OriginCountry": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_OriginCountry"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "CommodityClassification": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_CommodityClassification"
        },
        {
          "items": {
            "$ref": "#/components/schemas/StructuredInvoice_CommodityClassification"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Commodityclassification"
    },
    "ClassifiedTaxCategory": {
      "$ref": "#/components/schemas/StructuredInvoice_ClassifiedTaxCategory"
    }
  },
  "required": [
    "ClassifiedTaxCategory"
  ],
  "title": "Item",
  "type": "object"
}
```

### `StructuredInvoice_ItemClassificationCode`

```json
{
  "additionalProperties": false,
  "properties": {
    "#text": {
      "title": "#Text",
      "type": "string"
    },
    "listID": {
      "title": "Listid",
      "type": "string"
    },
    "listVersionID": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Listversionid"
    }
  },
  "required": [
    "#text",
    "listID"
  ],
  "title": "ItemClassificationCode",
  "type": "object"
}
```

### `StructuredInvoice_LegalMonetaryTotal`

```json
{
  "additionalProperties": false,
  "properties": {
    "LineExtensionAmount": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        }
      ],
      "title": "Lineextensionamount"
    },
    "AllowanceTotalAmount": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Allowancetotalamount"
    },
    "ChargeTotalAmount": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Chargetotalamount"
    },
    "TaxExclusiveAmount": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        }
      ],
      "title": "Taxexclusiveamount"
    },
    "TaxInclusiveAmount": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        }
      ],
      "title": "Taxinclusiveamount"
    },
    "PrepaidAmount": {
      "anyOf": [
        {
          "minimum": 0,
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Prepaidamount"
    },
    "PayableRoundingAmount": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Payableroundingamount"
    },
    "PayableAmount": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        }
      ],
      "title": "Payableamount"
    }
  },
  "required": [
    "LineExtensionAmount",
    "TaxExclusiveAmount",
    "TaxInclusiveAmount",
    "PayableAmount"
  ],
  "title": "LegalMonetaryTotal",
  "type": "object"
}
```

### `StructuredInvoice_OrderReference`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "minLength": 1,
      "title": "Id",
      "type": "string"
    },
    "IssueDate": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Issuedate"
    }
  },
  "required": [
    "ID"
  ],
  "title": "OrderReference",
  "type": "object"
}
```

### `StructuredInvoice_OriginCountry`

```json
{
  "additionalProperties": false,
  "properties": {
    "IdentificationCode": {
      "title": "Identificationcode",
      "type": "string"
    }
  },
  "required": [
    "IdentificationCode"
  ],
  "title": "OriginCountry",
  "type": "object"
}
```

### `StructuredInvoice_Party`

```json
{
  "additionalProperties": false,
  "properties": {
    "EndpointID": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_EndpointID"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "PartyIdentification": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_PartyIdentification"
        },
        {
          "items": {
            "$ref": "#/components/schemas/StructuredInvoice_PartyIdentification"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Partyidentification"
    },
    "PartyName": {
      "anyOf": [
        {
          "additionalProperties": {
            "type": "string"
          },
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Partyname"
    },
    "PostalAddress": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_PostalAddress"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "PartyTaxScheme": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_PartyTaxScheme"
        },
        {
          "items": {
            "$ref": "#/components/schemas/StructuredInvoice_PartyTaxScheme"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Partytaxscheme"
    },
    "PartyLegalEntity": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_PartyLegalEntity"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "Contact": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_Contact"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    }
  },
  "title": "Party",
  "type": "object"
}
```

### `StructuredInvoice_PartyIdentification`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "title": "Id",
      "type": "string"
    },
    "schemeID": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Schemeid"
    }
  },
  "required": [
    "ID"
  ],
  "title": "PartyIdentification",
  "type": "object"
}
```

### `StructuredInvoice_PartyLegalEntity`

```json
{
  "additionalProperties": false,
  "properties": {
    "RegistrationName": {
      "title": "Registrationname",
      "type": "string"
    },
    "CompanyID": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Companyid"
    },
    "CompanyLegalForm": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Companylegalform"
    }
  },
  "required": [
    "RegistrationName"
  ],
  "title": "PartyLegalEntity",
  "type": "object"
}
```

### `StructuredInvoice_PartyTaxScheme`

```json
{
  "additionalProperties": false,
  "properties": {
    "CompanyID": {
      "title": "Companyid",
      "type": "string"
    },
    "TaxScheme": {
      "$ref": "#/components/schemas/StructuredInvoice_TaxScheme"
    }
  },
  "required": [
    "CompanyID",
    "TaxScheme"
  ],
  "title": "PartyTaxScheme",
  "type": "object"
}
```

### `StructuredInvoice_PayeeFinancialAccount`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "title": "Id",
      "type": "string"
    },
    "Name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Name"
    },
    "FinancialInstitutionBranch": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_FinancialInstitutionBranch"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    }
  },
  "required": [
    "ID"
  ],
  "title": "PayeeFinancialAccount",
  "type": "object"
}
```

### `StructuredInvoice_PayeeParty`

```json
{
  "additionalProperties": false,
  "properties": {
    "Party": {
      "$ref": "#/components/schemas/StructuredInvoice_Party"
    }
  },
  "required": [
    "Party"
  ],
  "title": "PayeeParty",
  "type": "object"
}
```

### `StructuredInvoice_PaymentMandate`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "title": "Id",
      "type": "string"
    },
    "PayerFinancialAccount": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_PayeeFinancialAccount"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    }
  },
  "required": [
    "ID"
  ],
  "title": "PaymentMandate",
  "type": "object"
}
```

### `StructuredInvoice_PaymentMeans`

```json
{
  "additionalProperties": false,
  "properties": {
    "PaymentMeansCode": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Paymentmeanscode"
    },
    "PaymentID": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Paymentid"
    },
    "PaymentChannelCode": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Paymentchannelcode"
    },
    "InstructionID": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Instructionid"
    },
    "InstructionNote": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Instructionnote"
    },
    "PayeeFinancialAccount": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_PayeeFinancialAccount"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "CardAccount": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_CardAccount"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "PaymentMandate": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_PaymentMandate"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    }
  },
  "title": "PaymentMeans",
  "type": "object"
}
```

### `StructuredInvoice_PaymentTerms`

```json
{
  "additionalProperties": false,
  "properties": {
    "Note": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Note"
    },
    "PenaltySurchargePercent": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Penaltysurchargepercent"
    },
    "Amount": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Amount"
    },
    "NetDays": {
      "anyOf": [
        {
          "minimum": 0,
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Netdays"
    },
    "DiscountDays": {
      "anyOf": [
        {
          "minimum": 0,
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Discountdays"
    },
    "DiscountPercent": {
      "anyOf": [
        {
          "maximum": 100,
          "minimum": 0,
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Discountpercent"
    },
    "DiscountBaseAmount": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Discountbaseamount"
    },
    "ExplicitDueDate": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Explicitduedate"
    }
  },
  "title": "PaymentTerms",
  "type": "object"
}
```

### `StructuredInvoice_PostalAddress`

```json
{
  "additionalProperties": false,
  "properties": {
    "StreetName": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Streetname"
    },
    "CityName": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Cityname"
    },
    "PostalZone": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Postalzone"
    },
    "Country": {
      "$ref": "#/components/schemas/StructuredInvoice_Country"
    },
    "AdditionalStreetName": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Additionalstreetname"
    },
    "CountrySubentity": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Countrysubentity"
    }
  },
  "required": [
    "Country"
  ],
  "title": "PostalAddress",
  "type": "object"
}
```

### `StructuredInvoice_PrecedingInvoiceReference`

```json
{
  "additionalProperties": false,
  "description": "BG-3: Reference to a preceding invoice (e.g., for Schlussrechnung referencing Abschlagsrechnungen)",
  "properties": {
    "ID": {
      "minLength": 1,
      "title": "Id",
      "type": "string"
    },
    "IssueDate": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Issuedate"
    }
  },
  "required": [
    "ID"
  ],
  "title": "PrecedingInvoiceReference",
  "type": "object"
}
```

### `StructuredInvoice_Price`

```json
{
  "additionalProperties": false,
  "properties": {
    "PriceAmount": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        }
      ],
      "title": "Priceamount"
    },
    "BaseQuantity": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ]
          },
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Basequantity"
    },
    "AllowanceCharge": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_AllowanceCharge"
        },
        {
          "items": {
            "$ref": "#/components/schemas/StructuredInvoice_AllowanceCharge"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Allowancecharge"
    }
  },
  "required": [
    "PriceAmount"
  ],
  "title": "Price",
  "type": "object"
}
```

### `StructuredInvoice_ProjectReference`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "minLength": 1,
      "title": "Id",
      "type": "string"
    }
  },
  "required": [
    "ID"
  ],
  "title": "ProjectReference",
  "type": "object"
}
```

### `StructuredInvoice_SalesOrderReference`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "minLength": 1,
      "title": "Id",
      "type": "string"
    }
  },
  "required": [
    "ID"
  ],
  "title": "SalesOrderReference",
  "type": "object"
}
```

### `StructuredInvoice_SellersItemIdentification`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "title": "Id",
      "type": "string"
    }
  },
  "required": [
    "ID"
  ],
  "title": "SellersItemIdentification",
  "type": "object"
}
```

### `StructuredInvoice_StandardItemIdentification`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "title": "Id",
      "type": "string"
    },
    "schemeID": {
      "default": "0160",
      "title": "Schemeid",
      "type": "string"
    }
  },
  "required": [
    "ID"
  ],
  "title": "StandardItemIdentification",
  "type": "object"
}
```

### `StructuredInvoice_TaxCategory`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "title": "Id",
      "type": "string"
    },
    "Percent": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Percent"
    },
    "TaxExemptionReasonCode": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Taxexemptionreasoncode"
    },
    "TaxExemptionReason": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Taxexemptionreason"
    },
    "TaxScheme": {
      "$ref": "#/components/schemas/StructuredInvoice_TaxScheme"
    }
  },
  "required": [
    "ID",
    "TaxScheme"
  ],
  "title": "TaxCategory",
  "type": "object"
}
```

### `StructuredInvoice_TaxRepresentativeParty`

```json
{
  "additionalProperties": false,
  "description": "BG-11: Seller Tax Representative Party\nRequired when tax codes S, Z, E, AE, K, G, L, M are used\nand neither BT-31 nor BT-32 is provided (BR-DE-16)",
  "properties": {
    "PartyName": {
      "minLength": 1,
      "title": "Partyname",
      "type": "string"
    },
    "PostalAddress": {
      "$ref": "#/components/schemas/StructuredInvoice_TaxRepresentativePostalAddress"
    },
    "PartyTaxScheme": {
      "$ref": "#/components/schemas/StructuredInvoice_PartyTaxScheme"
    }
  },
  "required": [
    "PartyName",
    "PostalAddress",
    "PartyTaxScheme"
  ],
  "title": "TaxRepresentativeParty",
  "type": "object"
}
```

### `StructuredInvoice_TaxRepresentativePostalAddress`

```json
{
  "additionalProperties": false,
  "description": "BG-12: Seller Tax Representative Postal Address",
  "properties": {
    "StreetName": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Streetname"
    },
    "AdditionalStreetName": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Additionalstreetname"
    },
    "CityName": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Cityname"
    },
    "PostalZone": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Postalzone"
    },
    "CountrySubentity": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Countrysubentity"
    },
    "Country": {
      "$ref": "#/components/schemas/StructuredInvoice_Country"
    }
  },
  "required": [
    "Country"
  ],
  "title": "TaxRepresentativePostalAddress",
  "type": "object"
}
```

### `StructuredInvoice_TaxScheme`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "title": "Id",
      "type": "string"
    }
  },
  "required": [
    "ID"
  ],
  "title": "TaxScheme",
  "type": "object"
}
```

### `StructuredInvoice_TaxSubtotal`

```json
{
  "additionalProperties": false,
  "properties": {
    "TaxableAmount": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        }
      ],
      "title": "Taxableamount"
    },
    "TaxAmount": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        }
      ],
      "title": "Taxamount"
    },
    "TaxCategory": {
      "$ref": "#/components/schemas/StructuredInvoice_TaxCategory"
    }
  },
  "required": [
    "TaxableAmount",
    "TaxAmount",
    "TaxCategory"
  ],
  "title": "TaxSubtotal",
  "type": "object"
}
```

### `StructuredInvoice_TaxTotal`

```json
{
  "additionalProperties": false,
  "properties": {
    "TaxAmount": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        }
      ],
      "title": "Taxamount"
    },
    "TaxSubtotal": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/StructuredInvoice_TaxSubtotal"
        },
        {
          "items": {
            "$ref": "#/components/schemas/StructuredInvoice_TaxSubtotal"
          },
          "type": "array"
        }
      ],
      "title": "Taxsubtotal"
    }
  },
  "required": [
    "TaxAmount",
    "TaxSubtotal"
  ],
  "title": "TaxTotal",
  "type": "object"
}
```

### `StructuredInvoice_TenderOrLotReference`

```json
{
  "additionalProperties": false,
  "properties": {
    "ID": {
      "minLength": 1,
      "title": "Id",
      "type": "string"
    }
  },
  "required": [
    "ID"
  ],
  "title": "TenderOrLotReference",
  "type": "object"
}
```

## Error codes

| Code | Description |
| --- | --- |
| `AUTHENTICATION_REQUIRED` | 401 · no · Send `Authorization: Bearer <api_key>`. |
| `INVALID_API_KEY` | 401 · no · The key is unknown, revoked, or malformed. Fix or rotate it. |
| `API_NOT_ENABLED_FOR_TENANT` | 403 · no · The key is valid but the account has no External API access. Activate an Enterprise subscription at `details.action_url` or contact support. |
| `ACCOUNT_DELETED` | 410 · no · The account of this API key was deleted. The deletion is permanent. A revoked key returns `INVALID_API_KEY`. |
| `INSUFFICIENT_API_CREDITS` | 402 · no · Allowance and prepaid credits are used up. Buy a credit package at `details.action_url` or wait for the next month. Two `details` shapes. |
| `AUTH_SERVICE_UNAVAILABLE` | 503 · yes · Authentication is temporarily unavailable. Retry with backoff and the same Idempotency-Key. |
| `PLAN_TIER_CHECK_FAILED` | 503 · yes · Plan/API access could not be verified. Retry with backoff and the same Idempotency-Key. |
| `RATE_LIMIT_SERVICE_UNAVAILABLE` | 503 · yes · The rate-limit service is unavailable. Retry with backoff and the same Idempotency-Key. |
| `API_CREDIT_SERVICE_UNAVAILABLE` | 503 · yes · Credit/allowance verification is unavailable. Retry the upload with the same Idempotency-Key. |
| `RATE_LIMITED` | 429 · yes · Wait `Retry-After` seconds, then retry with the same Idempotency-Key. |
| `IDEMPOTENCY_KEY_REQUIRED` | 400 · no · Send an `Idempotency-Key` header on both POST endpoints. |
| `INVALID_IDEMPOTENCY_KEY` | 400 · no · Use 1–200 chars matching `^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$`. |
| `IDEMPOTENCY_IN_PROGRESS` | 409 · yes · The first request with this key is still running. Retry the same key after a short delay. |
| `IDEMPOTENCY_CONFLICT` | 409 · no · The key was used with a different payload. Use a new key for a new payload. |
| `IDEMPOTENCY_REPLAY_EXPIRED` | 409 · no · The original task is past its 24 h retention. Start a new conversion with a new key. |
| `IDEMPOTENCY_KEY_ALREADY_USED` | 409 · no · The key was already used for a completed conversion, and its 24 h replay records have expired. Use a new key for a new conversion. |
| `FORMAT_REQUIRED` | 400 · no · Send `format` on every conversion request. |
| `INVALID_FORMAT` | 422 · no · Send one of XRECHNUNG, ZUGFERD, EN16931, UBL, CII. |
| `INVALID_PROFILE` | 422 · no · Unknown profile name. `details.allowed_profiles` lists the accepted values. |
| `OUTPUT_PROFILE_CONFLICT` | 422 · no · The profile is not accepted for this `format`. Send a compatible profile or omit it. |
| `OUTPUT_PROFILE_REQUIRED` | 422 · no · Defensive; V1 defaults a profile for every format, so this is not expected. |
| `CLIENT_REFERENCE_CONFLICT` | 400 · no · `client_reference` and `external_invoice_id` differ. Send one, or the same value in both. |
| `INVALID_CLIENT_METADATA` | 400 · no · Keep `client_reference`/`external_invoice_id` ≤ 200 and `source_system` ≤ 100 chars, without control characters. |
| `INVALID_SELLER_MASTER_DATA` | 400 · no · Send `seller_master_data` as a JSON object string with supported keys; send `electronic_address` and `electronic_address_scheme` together. |
| `INVALID_EMBEDDED_XML_POLICY` | 400 · no · Send `use_embedded_xml` as `true` or `false`, or omit it. |
| `INVALID_EMAIL_INPUT` | 400 · no · Send `email_input` once, ≤ 10,000 chars, PDF source only, not with `use_embedded_xml=true`, never on convert-structured. |
| `INVALID_UPLOAD` | 400/415 · no · Fix the upload: multipart/form-data, supported file type, ≤ 20 file parts and 50 fields, one invoice number across all `data_file` parts (`details.reason`). |
| `PAYLOAD_TOO_LARGE` | 413 · no · A file, the `data_file` total, or the multipart body exceeds its backend limit. Inspect `details.limit_bytes`; send a smaller request. |
| `UPLOAD_FAILED` | 422 · no: invalid `jurisdiction`/`transaction_scope`/`delivery_channel` value. 500/503 · yes: the upload was not accepted, or it was accepted but its first response could not be rebuilt. Retry with backoff and the same Idempotency-Key; the retry returns the accepted task. |
| `SERVER_BUSY` | 503 · yes · The processing queue is full. Wait `Retry-After` seconds (15), then retry with the same Idempotency-Key. |
| `ZUGFERD_SOURCE_PDF_REQUIRED` | 422 · no · `format=ZUGFERD` needs a PDF source. Upload a PDF or choose an XML format. |
| `METHOD_NOT_ALLOWED` | 405 · no · Use POST on conversion paths and GET on task paths (see `Allow`). |
| `NOT_FOUND` | 404 · no · Unknown path under /api/v1. |
| `BAD_REQUEST` | 400 · no · `task_id` must be a UUID. |
| `INVALID_QUERY_PARAMETER` | 400 · no · Send `include_validation_report_html` as `true` or `false`. |
| `DOWNLOAD_FORMAT_REQUIRED` | 400 · no · Send the required `download` query parameter. |
| `INVALID_DOWNLOAD_FORMAT` | 400 · no · Use `download=xml\|pdf` on /result and `download=html\|xml` on /validation-report. |
| `TASK_NOT_READY` | 202 · poll · The task is still running. Keep polling task status with backoff. |
| `TASK_NOT_FOUND` | 404 · no · Unknown task, another tenant's task, or deleted 24 h after completion. All task endpoints. On `/tasks/{task_id}` and `/result` also a task not accepted through this API. |
| `TASK_STATUS_FAILED` | 5xx · yes · The status could not be read. Retry the poll with backoff. |
| `TASK_RESULT_FAILED` | 404/5xx · 5xx only · The result could not be read (for example missing task metadata). Retry 5xx with backoff; escalate a 404 with the correlation ID. |
| `TASK_FAILED` | 500 · only if `details.retryable` is true · Read `details.code`. Retryable failures need a NEW conversion with a new Idempotency-Key. |
| `VALIDATION_FAILED` | 422 · no · Blocking validation errors. Correct the data (`details.items`) and start a new conversion. |
| `DOCUMENT_NOT_CONVERTIBLE` | 422 · no · The source document cannot be converted as sent (reason in `details.code`, next step in `details.recovery_hint`). Fix the document and start a new conversion. |
| `PROFILE_MISMATCH` | 422 · no · The stored document declares another profile. Start a new conversion with the correct profile. |
| `ZUGFERD_SOURCE_PDF_INCOMPATIBLE` | 422 · no · The source PDF cannot carry a strict PDF/A-3 hybrid. Normalize the PDF or use `download=xml`. |
| `PROTECTED_BANK_DETAILS_MISMATCH` | 422 · no · A payee IBAN (BT-84) is not one of the bank accounts that the account's control address protects. No file was issued and no unit was used. Correct the IBAN in the source document, or add the account in the profile (the control address must confirm it), then start a new conversion. |
| `ZUGFERD_CII_CONVERSION_FAILED` | 422/500 · no · Hybrid CII conversion failed. Escalate with the correlation ID. |
| `ZUGFERD_PDF_GENERATION_FAILED` | 500 · no · Hybrid PDF generation failed. Escalate with the correlation ID. |
| `XML_GENERATION_FAILED` | 500 · yes, with backoff · Legacy on-demand generation path; not expected for strict API tasks. |
| `PDF_GENERATION_FAILED` | 500 · yes, with backoff · Legacy on-demand generation path; not expected for strict API tasks. |
| `ARTIFACT_GENERATION_RERUN_REQUIRED` | 409 · new task · No artifact was issued: generation or authoritative validation failed after server retries (reason in `details.code`, for example `AUTHORITATIVE_VALIDATION_UNAVAILABLE`). Start a new conversion with a new Idempotency-Key. |
| `EXTRACTION_INCOMPLETE_GROUP_FAILURE` | 409 · new task · Extraction groups failed (`details.failed_groups`). Start a new conversion with a new Idempotency-Key. |
| `INTERNAL_ARTIFACT_INVARIANT_FAILED` | 500 · no · Completed task without a safe stored artifact. Escalate with the correlation ID. |
| `VALIDATION_REPORT_NOT_FOUND` | 404 · no · No report is bound to the current artifact (`details.reason`). |
| `VALIDATION_REPORT_FAILED` | 4xx/5xx · 5xx only · Report retrieval failed. Retry transient 5xx with backoff. |
| `PROXY_ERROR` | 502/504 · yes · Transport failure between edge and backend. Retry with backoff and the same Idempotency-Key. |
