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.

POST/einvoice/create

Create 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

NameInTypeDescription
envelopequery"json"json: { format, filename, contentType, size, file (base64), validation, defaults } instead of the file.
Idempotency-KeyheaderstringUnique 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.

FieldTypeDescription
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).
typestringBT-3: invoice 380, credit_note 381, corrected_invoice 384 (amounts stay positive; the type says what it is).
number*stringBT-1 Invoice number.
issueDate*string (date)BT-2 Issue date, YYYY-MM-DD.
dueDatestring (date)BT-9; or give paymentTermsDays
paymentTermsDaysintegerDays from the issue date to the due date (writes BT-9).
paymentTermsstringBT-20 Payment terms, free text (the XRechnung #SKONTO# lines are written as given).
currencystringBT-5: EUR in v1
buyerReferencestringBT-10: XRechnung requires it (BR-DE-15); for a public body the Leitweg-ID
orderReferencestringBT-13 Purchase order reference.
contractReferencestringBT-12 Contract reference.
precedingInvoiceobjectBG-3 Preceding invoice: its number (BT-25) and date (BT-26), for credit notes and corrected invoices.
precedingInvoice.numberstring
precedingInvoice.issueDatestring (date)
deliveryDatestring (date)BT-72 Actual delivery date, YYYY-MM-DD.
deliverToAddressobjectBG-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.streetstring
deliverToAddress.additionalStreetstring
deliverToAddress.citystring
deliverToAddress.postalCodestring
deliverToAddress.countryCodestringISO 3166-1 alpha-2 (GR for Greece in an address).
periodobjectBG-14 Invoicing period (start and end, YYYY-MM-DD).
period.startstring (date)
period.endstring (date)
notesstring[]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*objectBG-4 Seller: in Germany for the XRechnung and ZUGFeRD formats, in Belgium for peppol-bis (v1).
seller.namestringBT-27 Seller name (legal registration name).
seller.tradingNamestringBT-28 Seller trading name.
seller.addressobject
seller.vatIdstringBT-31, with the country prefix
seller.taxNumberstringBT-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.legalRegistrationobjectBT-30 Seller legal registration identifier and its ISO 6523 scheme (BT-30-1), e.g. a Belgian enterprise number under 0208.
seller.electronicAddressobjectBT-34; defaults: 0208 + enterprise number for a Belgian seller on peppol-bis, EM + the contact e-mail otherwise
seller.contactobjectBG-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*objectBG-7 Buyer: in any EU member state.
buyer.namestringBT-44 Buyer name.
buyer.tradingNamestringBT-45 Buyer trading name.
buyer.addressobject
buyer.vatIdstringBT-48, with the country prefix; required for reverse charge (BR-AE-02) and intra-Community supplies (BR-IC-02)
buyer.legalRegistrationobjectBT-47 Buyer legal registration identifier and its ISO 6523 scheme (BT-47-1).
buyer.electronicAddressobjectBT-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.contactobjectBG-9: BT-56, BT-57, BT-58
paymentobjectBG-16 Payment instructions (XRechnung requires them, BR-DE-1).
payment.meansstringBT-81: SEPA credit transfer (58) or credit transfer (30).
payment.ibanstringBT-84 IBAN of the payee account.
payment.bicstringBT-86 BIC of the payee account (optional for SEPA).
payment.accountNamestringBT-85 Account name.
payment.referencestringBT-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.
allowancesobject[]BG-20 Document-level allowances (discounts), each with its VAT category and rate.
chargesobject[]BG-21 Document-level charges (freight, packaging…), each with its VAT category and rate.
application/json
{
  "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
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.

FieldTypeDescription
format*"xrechnung-ubl" | "xrechnung-cii" | "zugferd" | "peppol-bis"
filename*string
contentType*string
sizeinteger
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

  • 400invalid_parameter — A parameter is missing or malformed.
  • 401unauthorized — The API key is missing, unknown or revoked.
  • 402quota_exceeded — Monthly allowance and credits are used up.
  • 409idempotency_conflict — The Idempotency-Key is in use.
  • 413payload_too_large — Too many rows or too many bytes.
  • 422einvoice_unsupported — The invoice uses a feature the e-invoice writers do not produce. einvoice_invalid — The invoice breaks the rules of its format.
  • 429rate_limited — Too many requests per second.
POST/einvoice/validate

Validate 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
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).

FieldTypeDescription
valid*booleanNo 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" | nullThe create format of this kind of document.
syntax*"ubl" | "cii"
container"xml" | "pdf"
attachmentstring | nullThe embedded file’s name in a hybrid PDF (factur-x.xml).
errors*EInvoiceFinding[]
warnings*EInvoiceFinding[]
checks*object
checks.schemaobject
checks.ruleSetsobject[]
checks.pdfa"not_checked" | null
checks.veriportintegerVeriport practice checks reported as warnings.
msinteger
200 OK · application/json
{
  "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

  • 400invalid_parameter — A parameter is missing or malformed.
  • 401unauthorized — The API key is missing, unknown or revoked.
  • 402quota_exceeded — Monthly allowance and credits are used up.
  • 413payload_too_large — Too many rows or too many bytes.
  • 422einvoice_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.
  • 429rate_limited — Too many requests per second.
POST/einvoice/parse

Read 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

NameInTypeDescription
asquery"json" | "pdf"json (default) or pdf (a readable copy).
langquery"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
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.

FieldTypeDescription
invoice*InvoiceInputThe 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
formatLabelstring | null
profile*string
syntax*"ubl" | "cii"
container*"xml" | "pdf"
attachmentstring | null
notInJson*object[]What the document holds that the JSON does not.
200 OK · application/json
{
  "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

  • 400invalid_parameter — A parameter is missing or malformed.
  • 401unauthorized — The API key is missing, unknown or revoked.
  • 402quota_exceeded — Monthly allowance and credits are used up.
  • 413payload_too_large — Too many rows or too many bytes.
  • 422einvoice_unreadable — The file is not an e-invoice the API can read.
  • 429rate_limited — Too many requests per second.