E-invoices: create, validate, parse
Send the invoice as JSON (the InvoiceInput schema: seller, buyer, lines, VAT, allowances and charges, payment, references) and format: xrechnung-ubl (XRechnung 3.0, UBL 2.1), xrechnung-cii (XRechnung 3.0, CII D16B), zugferd (ZUGFeRD 2.x / Factur-X 1.0, profile EN 16931: a PDF/A-3 with the CII embedded as factur-x.xml) or peppol-bis (Peppol BIS Billing 3.0, UBL 2.1, with the Belgian rules). The answer is the file itself, with its validation summary in the Veriport-Validation header; ?envelope=json returns { file (base64), contentType, validation, defaults } instead.
Nothing is ever dropped silently: every field of the input is written, or the request is refused with 422 einvoice_unsupported naming the feature and its path (feature, path, unsupported[]). The input is checked against the engine's rules first (422 einvoice_invalid with the published rule ids and the JSON paths), the arithmetic is computed (line nets, VAT per breakdown, totals), the file is written, and the file is then run through the XML schema and the official schematron (CEN EN 16931 1.3.16, XRechnung 3.0.2, Peppol BIS 3.0.21); a fatal finding there withholds the file. Every value the engine adds (a VATEX code for reverse charge, the § 19 UStG mention, a 0208 Peppol address, a due date from paymentTermsDays) is listed in defaults and counted in the Veriport-Defaults header.
v1 writes: EUR; a seller in Germany (XRechnung, ZUGFeRD) or Belgium (Peppol BIS); a buyer in any EU member state; VAT categories S, Z, E, AE and K; invoice 380, credit note 381, corrected invoice 384; SEPA credit transfer or credit transfer; up to 500 lines; document-level allowances and charges. It does not send the invoice (no Peppol access point), does not store it, and gives no tax advice. Up to 4.5 MB (4500000 bytes) per request. Send an Idempotency-Key (1–128 characters): a retry replays the same file without a second charge for 24 hours; nothing of the invoice is kept for that, only the time of the first build.
/einvoice/createCreate an e-invoice (XRechnung, ZUGFeRD / Factur-X, Peppol BIS)
Send the invoice as JSON (the InvoiceInput schema: seller, buyer, lines, VAT, allowances and charges, payment, references) and format: xrechnung-ubl (XRechnung 3.0, UBL 2.1), xrechnung-cii (XRechnung 3.0, CII D16B), zugferd (ZUGFeRD 2.x / Factur-X 1.0, profile EN 16931: a PDF/A-3 with the CII embedded as factur-x.xml) or peppol-bis (Peppol BIS Billing 3.0, UBL 2.1, with the Belgian rules). The answer is the file itself, with its validation summary in the Veriport-Validation header; ?envelope=json returns { file (base64), contentType, validation, defaults } instead.
Nothing is ever dropped silently: every field of the input is written, or the request is refused with 422 einvoice_unsupported naming the feature and its path (feature, path, unsupported[]). The input is checked against the engine's rules first (422 einvoice_invalid with the published rule ids and the JSON paths), the arithmetic is computed (line nets, VAT per breakdown, totals), the file is written, and the file is then run through the XML schema and the official schematron (CEN EN 16931 1.3.16, XRechnung 3.0.2, Peppol BIS 3.0.21); a fatal finding there withholds the file. Every value the engine adds (a VATEX code for reverse charge, the § 19 UStG mention, a 0208 Peppol address, a due date from paymentTermsDays) is listed in defaults and counted in the Veriport-Defaults header.
v1 writes: EUR; a seller in Germany (XRechnung, ZUGFeRD) or Belgium (Peppol BIS); a buyer in any EU member state; VAT categories S, Z, E, AE and K; invoice 380, credit note 381, corrected invoice 384; SEPA credit transfer or credit transfer; up to 500 lines; document-level allowances and charges. It does not send the invoice (no Peppol access point), does not store it, and gives no tax advice. Up to 4.5 MB (4500000 bytes) per request. Send an Idempotency-Key (1–128 characters): a retry replays the same file without a second charge for 24 hours; nothing of the invoice is kept for that, only the time of the first build.
- Tiers
- freecreditsplan
- Cost
- 20 calls per produced file; 0 when refused (400, 413, 422) and on an Idempotency-Key replay
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| envelope | query | "json" | json: { format, filename, contentType, size, file (base64), validation, defaults } instead of the file. |
| Idempotency-Key | header | string | Unique per request (^[A-Za-z0-9_.:-]{1,128}$). The same key, query and body within 24 hours replays the same file (Idempotent-Replayed: true), rebuilt from the request, not stored; another body under the key is 409. |
Request body
Media types: application/json.
| Field | Type | Description |
|---|---|---|
| format* | "xrechnung-ubl" | "xrechnung-cii" | "zugferd" | "peppol-bis" | The file to write: xrechnung-ubl (XRechnung 3.0, UBL 2.1), xrechnung-cii (XRechnung 3.0, CII D16B), zugferd (ZUGFeRD 2.x / Factur-X 1.0 EN 16931, a PDF/A-3 with the CII embedded), peppol-bis (Peppol BIS Billing 3.0, UBL 2.1). |
| type | string | BT-3: invoice 380, credit_note 381, corrected_invoice 384 (amounts stay positive; the type says what it is). |
| number* | string | BT-1 Invoice number. |
| issueDate* | string (date) | BT-2 Issue date, YYYY-MM-DD. |
| dueDate | string (date) | BT-9; or give paymentTermsDays |
| paymentTermsDays | integer | Days from the issue date to the due date (writes BT-9). |
| paymentTerms | string | BT-20 Payment terms, free text (the XRechnung #SKONTO# lines are written as given). |
| currency | string | BT-5: EUR in v1 |
| buyerReference | string | BT-10: XRechnung requires it (BR-DE-15); for a public body the Leitweg-ID |
| orderReference | string | BT-13 Purchase order reference. |
| contractReference | string | BT-12 Contract reference. |
| precedingInvoice | object | BG-3 Preceding invoice: its number (BT-25) and date (BT-26), for credit notes and corrected invoices. |
| precedingInvoice.number | string | |
| precedingInvoice.issueDate | string (date) | |
| deliveryDate | string (date) | BT-72 Actual delivery date, YYYY-MM-DD. |
| deliverToAddress | object | BG-15 deliver-to address: an intra-Community supply (K) needs its country (BR-IC-12), XRechnung also city and post code (BR-DE-10, BR-DE-11); defaults to the buyer's address for K lines |
| deliverToAddress.street | string | |
| deliverToAddress.additionalStreet | string | |
| deliverToAddress.city | string | |
| deliverToAddress.postalCode | string | |
| deliverToAddress.countryCode | string | ISO 3166-1 alpha-2 (GR for Greece in an address). |
| period | object | BG-14 Invoicing period (start and end, YYYY-MM-DD). |
| period.start | string (date) | |
| period.end | string (date) | |
| notes | string[] | BT-22 (Peppol admits one, PEPPOL-EN16931-R002) |
| language | "de" | "en" | "fr" | "nl" | The language of the texts the engine adds (statutory mentions, the visible page of the ZUGFeRD PDF): de, en, fr, nl. Defaults to the seller's country (de for DE, fr for BE). |
| seller* | object | BG-4 Seller: in Germany for the XRechnung and ZUGFeRD formats, in Belgium for peppol-bis (v1). |
| seller.name | string | BT-27 Seller name (legal registration name). |
| seller.tradingName | string | BT-28 Seller trading name. |
| seller.address | object | |
| seller.vatId | string | BT-31, with the country prefix |
| seller.taxNumber | string | BT-32 Seller tax registration identifier: the German Steuernummer (written under scheme FC). Without a VAT identifier it is also repeated as BT-29 (BR-CO-26). |
| seller.legalRegistration | object | BT-30 Seller legal registration identifier and its ISO 6523 scheme (BT-30-1), e.g. a Belgian enterprise number under 0208. |
| seller.electronicAddress | object | BT-34; defaults: 0208 + enterprise number for a Belgian seller on peppol-bis, EM + the contact e-mail otherwise |
| seller.contact | object | BG-6: BT-41, BT-42, BT-43 (XRechnung requires all three, BR-DE-2 … 7) |
| seller.vatScheme | "standard" | "small_business" | small_business: § 19 UStG (Kleinunternehmer) or the Belgian franchise (art. 56bis): every line is category E, the statutory mention is written. |
| buyer* | object | BG-7 Buyer: in any EU member state. |
| buyer.name | string | BT-44 Buyer name. |
| buyer.tradingName | string | BT-45 Buyer trading name. |
| buyer.address | object | |
| buyer.vatId | string | BT-48, with the country prefix; required for reverse charge (BR-AE-02) and intra-Community supplies (BR-IC-02) |
| buyer.legalRegistration | object | BT-47 Buyer legal registration identifier and its ISO 6523 scheme (BT-47-1). |
| buyer.electronicAddress | object | BT-49: XRechnung and Peppol require it (PEPPOL-EN16931-R010); for a public body in Germany the Leitweg-ID under 0204. Defaults: 0208 + enterprise number for a Belgian buyer on peppol-bis, EM + the contact e-mail otherwise |
| buyer.contact | object | BG-9: BT-56, BT-57, BT-58 |
| payment | object | BG-16 Payment instructions (XRechnung requires them, BR-DE-1). |
| payment.means | string | BT-81: SEPA credit transfer (58) or credit transfer (30). |
| payment.iban | string | BT-84 IBAN of the payee account. |
| payment.bic | string | BT-86 BIC of the payee account (optional for SEPA). |
| payment.accountName | string | BT-85 Account name. |
| payment.reference | string | BT-83 remittance information; a Belgian structured communication « +++123/4567/89002+++ » is checked (VP-BE-002). |
| lines* | object[] | BG-25 Invoice lines, 1 to 500; the line net amount is quantity × unit price, rounded to cents. |
| allowances | object[] | BG-20 Document-level allowances (discounts), each with its VAT category and rate. |
| charges | object[] | BG-21 Document-level charges (freight, packaging…), each with its VAT category and rate. |
{
"number": "2026-017",
"issueDate": "2026-10-20",
"paymentTermsDays": 14,
"buyerReference": "EK-2026-0345",
"deliveryDate": "2026-10-15",
"seller": {
"name": "Lena Hartmann — Webdesign",
"address": {
"street": "Lindenstraße 14",
"postalCode": "10969",
"city": "Berlin",
"countryCode": "DE"
},
"vatId": "DE136695976",
"contact": {
"name": "Lena Hartmann",
"phone": "+49 30 1234567",
"email": "rechnung@hartmann-webdesign.example"
}
},
"buyer": {
"name": "Mustermann Maschinenbau GmbH",
"address": {
"street": "Industrieweg 7",
"postalCode": "70565",
"city": "Stuttgart",
"countryCode": "DE"
},
"contact": {
"email": "buchhaltung@mustermann.example"
}
},
"payment": {
"iban": "DE02120300000000202051"
},
"lines": [
{
"name": "Relaunch Website, Konzeption und Umsetzung",
"quantity": 24,
"unitCode": "HUR",
"unitPrice": 95,
"vat": {
"category": "S",
"rate": 19
}
},
{
"name": "Lizenz Bildmaterial",
"quantity": 1,
"unitCode": "C62",
"unitPrice": 128.4,
"vat": {
"category": "S",
"rate": 19
}
}
],
"format": "xrechnung-ubl"
}Request
curl -X POST -H "Authorization: Bearer vp_live_YOUR_KEY" -H "Content-Type: application/json" \
-d '{"number":"2026-017","issueDate":"2026-10-20","paymentTermsDays":14,"buyerReference":"EK-2026-0345","deliveryDate":"2026-10-15","seller":{"name":"Lena Hartmann — Webdesign","address":{"street":"Lindenstraße 14","postalCode":"10969","city":"Berlin","countryCode":"DE"},"vatId":"DE136695976","contact":{"name":"Lena Hartmann","phone":"+49 30 1234567","email":"rechnung@hartmann-webdesign.example"}},"buyer":{"name":"Mustermann Maschinenbau GmbH","address":{"street":"Industrieweg 7","postalCode":"70565","city":"Stuttgart","countryCode":"DE"},"contact":{"email":"buchhaltung@mustermann.example"}},"payment":{"iban":"DE02120300000000202051"},"lines":[{"name":"Relaunch Website, Konzeption und Umsetzung","quantity":24,"unitCode":"HUR","unitPrice":95,"vat":{"category":"S","rate":19}},{"name":"Lizenz Bildmaterial","quantity":1,"unitCode":"C62","unitPrice":128.4,"vat":{"category":"S","rate":19}}],"format":"xrechnung-ubl"}' \
"https://veriport.io/api/v1/einvoice/create"Response 200
The e-invoice file (or, with ?envelope=json, the envelope).
Media types: application/xml, application/pdf, application/json.
| Field | Type | Description |
|---|---|---|
| format* | "xrechnung-ubl" | "xrechnung-cii" | "zugferd" | "peppol-bis" | |
| filename* | string | |
| contentType* | string | |
| size | integer | |
| file* | string | |
| validation* | EInvoiceValidation | |
| defaults* | object[] |
Headers: RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, RateLimit-Policy, X-Quota-Remaining, X-Tier, Veriport-Validation, Veriport-Defaults, Content-Disposition.
Errors
- 400
invalid_parameter— A parameter is missing or malformed. - 401
unauthorized— The API key is missing, unknown or revoked. - 402
quota_exceeded— Monthly allowance and credits are used up. - 409
idempotency_conflict— The Idempotency-Key is in use. - 413
payload_too_large— Too many rows or too many bytes. - 422
einvoice_unsupported— The invoice uses a feature the e-invoice writers do not produce.einvoice_invalid— The invoice breaks the rules of its format. - 429
rate_limited— Too many requests per second.
/einvoice/validateValidate an e-invoice against the official rules
Send an XRechnung, Peppol BIS or EN 16931 XML (UBL 2.1 Invoice or CreditNote, UN/CEFACT CII D16B) or a ZUGFeRD / Factur-X hybrid PDF, as the raw body (Content-Type application/xml or application/pdf) or as the file field of multipart/form-data. The XML schema and the official schematron of the document's profile run in-process: CEN EN 16931 1.3.16 always, XRechnung 3.0.2 (2.6.0) for an XRechnung, Peppol BIS Billing 3.0.21 for a Peppol document, with the severities of the KoSIT XRechnung configuration. Rule ids and messages are the published ones (CEN and Peppol in English, the XRechnung BR-DE rules in German); Veriport's own checks of national practice (VP-DE-*, VP-BE-*, VP-EU-*) come as warnings only. The evidence that this check names the same rules as the KoSIT validator, file by file, is at /einvoice-api. Not checked: PDF/A-3 conformance of a hybrid PDF (checks.pdfa: not_checked), Factur-X MINIMUM, BASIC WL and EXTENDED profiles (422 einvoice_unsupported). Without a key, 4 checks a day per address. The document is not stored.
- Tiers
- anonymousfreecreditsplan
- Cost
- 5 calls per report (valid or not); 0 for an unreadable file or an unsupported profile
Request body
The e-invoice file.
Media types: application/xml, application/pdf, multipart/form-data (the file as the `file` field).
Request
curl -X POST -H "Content-Type: application/xml" \
--data-binary @invoice.xml \
"https://veriport.io/api/v1/einvoice/validate"Response 200
The validation report (`valid: false` with the errors when the document breaks a rule).
| Field | Type | Description |
|---|---|---|
| valid* | boolean | No fatal finding of the schema or the official rules. |
| profile* | "xrechnung" | "peppol-bis" | "en16931" | "factur-x-basic" | What the document claims (BT-24). |
| format | "xrechnung-ubl" | "xrechnung-cii" | "zugferd" | "peppol-bis" | null | The create format of this kind of document. |
| syntax* | "ubl" | "cii" | |
| container | "xml" | "pdf" | |
| attachment | string | null | The embedded file’s name in a hybrid PDF (factur-x.xml). |
| errors* | EInvoiceFinding[] | |
| warnings* | EInvoiceFinding[] | |
| checks* | object | |
| checks.schema | object | |
| checks.ruleSets | object[] | |
| checks.pdfa | "not_checked" | null | |
| checks.veriport | integer | Veriport practice checks reported as warnings. |
| ms | integer |
{
"valid": true,
"profile": "xrechnung",
"format": "xrechnung-ubl",
"syntax": "ubl",
"container": "xml",
"attachment": null,
"errors": [],
"warnings": [],
"checks": {
"schema": {
"status": "passed",
"name": "UBL 2.1 (OASIS) and UN/CEFACT CII D16B XML schemas, from the KoSIT XRechnung validator configuration v2026-08-31"
},
"ruleSets": [
{
"id": "cen-ubl",
"name": "CEN EN 16931 validation artefacts (UBL)",
"release": "1.3.16",
"sha256": "bafada015efbc5248bf5e05ad2191e1d9833ef96e9dd5f4bce420a747342da85",
"fatal": 0,
"warnings": 0
},
{
"id": "xrechnung-ubl",
"name": "XRechnung 3.0.2 schematron (UBL)",
"release": "2.6.0",
"sha256": "ca5e07afd04e72cd283d581590ffff3a15f4aac9d2f40c993345d78e67ea22b4",
"fatal": 0,
"warnings": 0
}
],
"pdfa": null,
"veriport": 0
},
"ms": 84
}Headers: RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, RateLimit-Policy, X-Quota-Remaining, X-Tier.
Errors
- 400
invalid_parameter— A parameter is missing or malformed. - 401
unauthorized— The API key is missing, unknown or revoked. - 402
quota_exceeded— Monthly allowance and credits are used up. - 413
payload_too_large— Too many rows or too many bytes. - 422
einvoice_unreadable— The file is not an e-invoice the API can read.einvoice_unsupported— The invoice uses a feature the e-invoice writers do not produce. - 429
rate_limited— Too many requests per second.
/einvoice/parseRead an e-invoice as invoice JSON or a readable PDF
Send an XML or hybrid PDF e-invoice (raw body or the file field of multipart/form-data). The answer is the invoice in the create model (the same JSON POST /einvoice/create accepts), its format and profile, and notInJson: everything the document holds that the JSON does not (attachments, line periods, a paid amount, other payment means, totals that differ from the recomputation…), so nothing is dropped silently. A file the API wrote parses with an empty list and writes the same file again. ?as=pdf returns a readable PDF/A-3 copy instead (?lang=de|en|fr|nl). The document is not stored.
- Tiers
- freecreditsplan
- Cost
- 5 calls per answer; 0 for an unreadable file
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| as | query | "json" | "pdf" | json (default) or pdf (a readable copy). |
| lang | query | "de" | "en" | "fr" | "nl" | Labels of the readable PDF: de, en, fr, nl (default from the seller’s country). |
Request body
The e-invoice file.
Media types: application/xml, application/pdf, multipart/form-data (the file as the `file` field).
Request
curl -X POST -H "Authorization: Bearer vp_live_YOUR_KEY" -H "Content-Type: application/xml" \
--data-binary @invoice.xml \
"https://veriport.io/api/v1/einvoice/parse"Response 200
The invoice JSON (or the PDF with ?as=pdf).
Media types: application/json, application/pdf.
| Field | Type | Description |
|---|---|---|
| invoice* | InvoiceInput | The invoice (EN 16931 business terms named in each field). Strict: an unknown field is refused, never ignored. |
| format | "xrechnung-ubl" | "xrechnung-cii" | "zugferd" | "peppol-bis" | null | |
| formatLabel | string | null | |
| profile* | string | |
| syntax* | "ubl" | "cii" | |
| container* | "xml" | "pdf" | |
| attachment | string | null | |
| notInJson* | object[] | What the document holds that the JSON does not. |
{
"invoice": {
"format": "xrechnung-ubl",
"type": "invoice",
"number": "2026-017",
"issueDate": "2026-10-20",
"dueDate": "2026-11-03",
"currency": "EUR",
"buyerReference": "EK-2026-0345",
"deliveryDate": "2026-10-15",
"seller": {
"name": "Lena Hartmann — Webdesign",
"address": {
"street": "Lindenstraße 14",
"city": "Berlin",
"postalCode": "10969",
"countryCode": "DE"
},
"vatId": "DE136695976",
"electronicAddress": {
"scheme": "EM",
"id": "rechnung@hartmann-webdesign.example"
},
"contact": {
"name": "Lena Hartmann",
"phone": "+49 30 1234567",
"email": "rechnung@hartmann-webdesign.example"
},
"vatScheme": "standard"
},
"buyer": {
"name": "Mustermann Maschinenbau GmbH",
"address": {
"street": "Industrieweg 7",
"city": "Stuttgart",
"postalCode": "70565",
"countryCode": "DE"
},
"electronicAddress": {
"scheme": "EM",
"id": "buchhaltung@mustermann.example"
},
"contact": {
"email": "buchhaltung@mustermann.example"
}
},
"payment": {
"means": "sepa_credit_transfer",
"iban": "DE02120300000000202051"
},
"lines": [
{
"id": "1",
"name": "Relaunch Website, Konzeption und Umsetzung",
"quantity": 24,
"unitCode": "HUR",
"unitPrice": 95,
"vat": {
"category": "S",
"rate": 19
}
},
{
"id": "2",
"name": "Lizenz Bildmaterial",
"quantity": 1,
"unitCode": "C62",
"unitPrice": 128.4,
"vat": {
"category": "S",
"rate": 19
}
}
]
},
"format": "xrechnung-ubl",
"formatLabel": "XRechnung 3.0 (UBL 2.1)",
"profile": "xrechnung",
"syntax": "ubl",
"container": "xml",
"attachment": null,
"notInJson": []
}Headers: RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, RateLimit-Policy, X-Quota-Remaining, X-Tier.
Errors
- 400
invalid_parameter— A parameter is missing or malformed. - 401
unauthorized— The API key is missing, unknown or revoked. - 402
quota_exceeded— Monthly allowance and credits are used up. - 413
payload_too_large— Too many rows or too many bytes. - 422
einvoice_unreadable— The file is not an e-invoice the API can read. - 429
rate_limited— Too many requests per second.