Create UBL Invoice using REST-API
Generate a complete UBL 2.1 invoice from structured form data. Submit seller and buyer details and line items — totals and tax breakdown are calculated automatically. The API produces a validated Peppol BIS Billing 3.0 compliant UBL 2.1 XML, checked against EN 16931 Schematron rules and Peppol-specific constraints, ready for transmission to any Peppol-certified access point worldwide.
https://api.invoicexml.com/v1/create/ubl
Code Example
Totals and tax breakdown are omitted — the API calculates them automatically from the line items.
curl -X POST https://api.invoicexml.com/v1/create/ubl \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "InvoiceNumber=INV-2025-001" \ -F "IssueDate=2025-07-01" \ -F "PaymentDueDate=2025-08-01" \ -F "Currency=EUR" -F "Profile=peppol-bis-3" \ \ -F "SellerName=Acme GmbH" \ -F "SellerTaxId=DE123456789" \ -F "SellerStreet=Musterstr. 1" \ -F "SellerPostcode=10115" \ -F "SellerCity=Berlin" \ -F "SellerCountry=DE" \ -F "BuyerName=Example Corp" \ -F "BuyerStreet=12 Rue de Rivoli" \ -F "BuyerPostcode=75001" \ -F "BuyerCity=Paris" \ -F "BuyerCountry=FR" \ -F "Lines[0].Description=Consulting Services" \ -F "Lines[0].Quantity=10" \ -F "Lines[0].UnitPrice=150.00" \ -F "Lines[0].TaxPercentage=19" \ -F "PaymentMeansCode=30" \ -o invoice-ubl.xml
Try it out online — no coding required
Fill in the form and download a compliant invoice instantly, right in your browser.
Request
Submit invoice data as multipart/form-data.
All monetary values use decimal format (e.g. 1234.56).
Totals and tax breakdown are auto-calculated when omitted — only line items are required.
Document
| Field | Type | Description |
|---|---|---|
| InvoiceNumber * | string | Unique invoice identifier. Max 50 chars. (BT-1) |
| IssueDate * | string | Issue date in YYYY-MM-DD format. (BT-2) |
| PaymentDueDate * | string | Payment due date in YYYY-MM-DD format. (BT-9) |
| Currency * | string | ISO 4217 currency code. Default: EUR. (BT-5) |
| Profile | string | UBL CIUS profile. Controls the CustomizationID embedded in the output. See profile table below. Defaults to peppol-bis-3. |
| Language | string | Language for PDF labels and date formatting. Values: en, de, fr. Defaults to en. |
UBL Profile
The Profile field controls which
CustomizationID is embedded in the generated UBL document.
Defaults to peppol-bis-3 when omitted.
Profile value |
CustomizationID applied | Use case |
|---|---|---|
| peppol-bis-3 (default) | urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0 | Peppol — BE, DK, SE, HR, cross-border EU |
| en16931 | urn:cen.eu:en16931:2017 | Generic EN 16931, no CIUS |
| nlcius | urn:cen.eu:en16931:2017#compliant#urn:fdc:nen.nl:nlcius:v1.0 | Netherlands public sector |
| ehf | urn:cen.eu:en16931:2017#compliant#urn:fdc:anskaffelser.no:2019:ehf:spec:3.0 | Norway (EHF) |
| xrechnung | urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_3.0 | Germany B2G (XRechnung UBL syntax) |
| pint | urn:peppol:pint:billing-1 | Cross-regional Peppol PINT base |
| pint-sg | urn:peppol:pint:billing-1@sg-1 | Singapore |
| pint-au | urn:peppol:pint:billing-1@au-1 | Australia |
| pint-jp | urn:peppol:pint:billing-1@jp-1 | Japan |
| pint-my | urn:peppol:pint:billing-1@my-1 | Malaysia |
| pint-nz | urn:peppol:pint:billing-1@nz-1 | New Zealand |
Seller
| Field | Type | Description |
|---|---|---|
| SellerName * | string | Legal business name. (BT-27) |
| SellerStreet * | string | Street address. (BT-35) |
| SellerPostcode * | string | Postal code. (BT-38) |
| SellerCity * | string | City name. (BT-37) |
| SellerCountry * | string | ISO 3166-1 alpha-2 country code. Default: FR. (BT-40) |
| SellerLegalId | string | Legal registration number (e.g. SIRET, HRB). Required for Factur-X. (BT-30) |
| SellerTaxId | string | VAT identification number (e.g. DE123456789). Required for Factur-X, ZUGFeRD, XRechnung. (BT-31) |
Buyer
| Field | Type | Description |
|---|---|---|
| BuyerName * | string | Legal business name. (BT-44) |
| BuyerStreet * | string | Street address. (BT-50) |
| BuyerPostcode * | string | Postal code. (BT-53) |
| BuyerCity * | string | City name. (BT-52) |
| BuyerCountry * | string | ISO 3166-1 alpha-2 country code. (BT-55) |
| BuyerLegalId | string | Legal registration number. Recommended. (BT-47) |
| BuyerReference | string | Buyer reference. Required for XRechnung (Leitweg-ID, e.g. 991-12345-67). (BT-10) |
| PurchaseOrder | string | Purchase order reference. (BT-13) |
| BuyerTaxId | string | VAT identification number. Required for EU cross-border / reverse charge. (BT-48) |
Payment
| Field | Type | Description |
|---|---|---|
| PaymentMeansCode * | string | UNTDID 4461 code. Default: 30 (credit transfer). Other: 58 (SEPA), 54 (card). (BT-81) |
| IBAN | string | Seller bank account IBAN. Required for Factur-X, ZUGFeRD. (BT-84) |
| BIC | string | Seller bank BIC/SWIFT code. (BT-86) |
Line Items
Submit one or more line items using indexed field names: Lines[0].Description, Lines[1].Description, etc. At least one line item is required.
| Field | Type | Description |
|---|---|---|
| Lines[n].Description * | string | Description of the goods or service. (BT-153) |
| Lines[n].Quantity * | decimal | Quantity of items. Must be ≥ 0.0001. (BT-129) |
| Lines[n].UnitPrice * | decimal | Price per unit (net, excluding VAT). (BT-146) |
| Lines[n].LineTotal | decimal | Line net total. Auto-calculated as Quantity × UnitPrice when omitted. (BT-131) |
| Lines[n].UnitCode | string | UN/ECE Rec 20 unit code. Default: C62 (unit). Common: HUR (hour), DAY. (BT-130) |
| Lines[n].TaxPercentage * | decimal | VAT rate for this line (e.g. 20 for 20%). (BT-152) |
| Lines[n].TaxCategoryCode | string | VAT category. Default: S. Values: S (standard), Z (zero), E (exempt), AE (reverse charge), K (intra-community), G (export), O (not subject). (BT-151) |
Totals (auto-calculated when omitted)
All totals are rounded to 2 decimal places. If provided, your values are used as-is (still rounded). If omitted, they are calculated from the line items.
| Field | Type | Default | Description |
|---|---|---|---|
| LineTotalAmount | decimal | computed | = sum(Lines[].LineTotal) (BT-106) |
| TaxBasisTotal | decimal | computed | = LineTotalAmount (BT-109) |
| TaxTotalAmount | decimal | computed | = sum(TaxBreakdown[].TaxAmount) (BT-110) |
| GrandTotalAmount | decimal | computed | = TaxBasisTotal + TaxTotalAmount (BT-112) |
Tax Breakdown (auto-generated when omitted)
When omitted entirely, the array is auto-generated by grouping Lines[] on (TaxCategoryCode, TaxPercentage). Only required if you provide the breakdown manually.
| Field | Type | Description |
|---|---|---|
| TaxBreakdown[n].BasisAmount | decimal | Sum of line totals for this rate. (BT-116) |
| TaxBreakdown[n].TaxAmount | decimal | Tax amount for this rate. (BT-117) |
| TaxBreakdown[n].TaxPercentage | decimal | VAT rate percentage. (BT-119) |
| TaxBreakdown[n].TaxCategoryCode | string | Default: S. (BT-118) |
| TaxBreakdown[n].ExemptionReasonCode | string | Auto-resolved from TaxCategoryCode. Your value takes precedence if provided. (BT-121) |
| TaxBreakdown[n].ExemptionReason | string | Auto-resolved from TaxCategoryCode. Your value takes precedence if provided. (BT-120) |
Exemption defaults auto-resolved from TaxCategoryCode
| TaxCategoryCode | ExemptionReasonCode | ExemptionReason |
|---|---|---|
| AE | VATEX-EU-AE | Reverse charge |
| E | VATEX-EU-132 | Exempt from tax |
| K | VATEX-EU-IC | Intra-Community supply |
| G | VATEX-EU-G | Export outside the EU |
| O | VATEX-EU-O | Not subject to VAT |
| S | — | none needed |
| Z | — | none needed |
Standard-specific Requirements
Some fields are only required for specific output standards. Fields not listed here follow the rules in the tables above.
| Field | UBL | CII | Factur-X | ZUGFeRD | XRechnung |
|---|---|---|---|---|---|
| SellerLegalId | — | — | ✓ | — | — |
| SellerTaxId | — | — | ✓ | ✓ | ✓ |
| IBAN | — | — | ✓ | ✓ | — |
| BuyerReference | — | — | — | — | ✓ |
| SellerContactName | — | — | — | — | ✓ |
| SellerPhone | — | — | — | — | ✓ |
| SellerEmail | — | — | — | — | ✓ |
| SellerElectronicAddress | — | — | — | — | ✓* |
| BuyerElectronicAddress | — | — | — | — | ✓* |
✓* = required but auto-defaulted from another field when omitted.
XRechnung Fields (optional for other standards)
The following fields are required for XRechnung and optional for all other standards. When not provided, some fields are auto-defaulted from other values.
Seller Contact (BG-6)
| Field | Type | Description |
|---|---|---|
| SellerContactName | string | Contact person name. Required for XRechnung. (BT-41) |
| SellerPhone | string | Contact phone number. Required for XRechnung. (BT-42) |
| SellerEmail | string | Contact email address. Required for XRechnung. (BT-43) |
Electronic Addresses
| Field | Type | Auto-default | Description |
|---|---|---|---|
| SellerElectronicAddress | string | SellerEmail |
Seller endpoint identifier. Required for XRechnung — auto-defaulted from SellerEmail when omitted. (BT-34) |
| SellerElectronicAddressScheme | string | EM |
Scheme for seller endpoint. Defaults to EM when auto-defaulted from email. (BT-34-1) |
| BuyerElectronicAddress | string | BuyerTaxId |
Buyer endpoint identifier. Required for XRechnung — auto-defaulted from BuyerTaxId when omitted. (BT-49) |
| BuyerElectronicAddressScheme | string | 9930 |
Scheme for buyer endpoint. Defaults to 9930 when auto-defaulted from VAT ID. (BT-49-1) |
Electronic Address Scheme — most common codes
| Code | Name | Use when |
|---|---|---|
| EM | The endpoint is an email address | |
| 9930 | VAT number | Generic EU VAT registration number |
| 0204 | Leitweg-ID | German routing identifier |
| 0088 | GLN (GS1) | GS1 Global Location Number |
| 0184 | PEPPOL participant | OpenPEPPOL participant identifier |
| 9958 | German VAT | German Umsatzsteuer-ID |
| 0009 | SIRET | French SIRET identifier |
| 0060 | DUNS | Dun & Bradstreet number |
| 0190 | Dutch OIN | Netherlands Overheids Identificatie Nummer |
| 0192 | Organisasjonsnummer | Norwegian organization number |
Options
| Field | Type | Description |
|---|---|---|
| strict | boolean | Defaults to false. When true, treat validation warnings as errors — the request is rejected if any warning is raised, not just errors. |
| version | string | Standard version (e.g. 2.3.2). Defaults to the latest supported version. |
| profile | string | Compliance profile. Values: minimum, basicwl, basic, en16931, extended. Defaults to en16931. |
| syntax | string | XML syntax: cii (Cross Industry Invoice) or ubl (Universal Business Language). Defaults to cii. |
Headers
| Header | Value |
|---|---|
| Authorization * | Bearer YOUR_API_KEY |
| Content-Type | multipart/form-data |
Response
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Model Validation Failed",
"status": 400,
"errorCode": 4002,
"detail": "One or more fields are invalid.",
"errors": {
"SellerName": ["Seller name is required."],
"Lines[0].Description": ["Line item description is required."]
}
}
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "XML Validation Failed",
"status": 400,
"errorCode": 4001,
"detail": "The generated invoice contains 2 validation error(s).",
"errors": {
"xml": [
"[BR-CO-15] Invoice total amount with VAT = 1785.00 expected 1500.00 + 285.00.",
"[BR-S-08] VAT category tax amount must equal category basis × rate."
],
"friendly": [
{
"rule": "BR-CO-15",
"line": null,
"message": "The invoice total with VAT does not match. Expected 1500.00 + 285.00 = 1785.00."
},
{
"rule": "BR-S-08",
"line": null,
"message": "The VAT breakdown for Standard rate must have a positive taxable amount and the correct rate. Check the tax breakdown."
}
]
}
}
Error Reference
Errors are returned as RFC 7807 ProblemDetails. The errorCode field indicates the error category.
| errorCode | Meaning | errors key |
|---|---|---|
| 4001 | XML validation — the generated XML violates EN 16931 Schematron rules. Includes user-facing messages in errors.friendly. |
errors.xml[] errors.friendly[] |
| 4002 | Model validation — one or more request fields are missing or invalid. | errors.{FieldName}[] |
| 4000 | General error — check detail for more information. |
— |
Frequently Asked Questions
What is the difference between /transform/to/ubl and /create/ubl?
The /transform/to/ubl endpoint transforms an existing PDF into a UBL 2.1 invoice using AI extraction. The /create/ubl endpoint generates a new UBL invoice from scratch using the structured form data you provide — no source PDF required.
Is the output Peppol BIS Billing 3.0 compliant?
Yes. Every generated UBL invoice is validated against EN 16931 Schematron business rules and Peppol BIS Billing 3.0 constraints before delivery. If validation fails (e.g. mismatched totals or missing mandatory fields), the API returns a 400 response with errorCode 4001 and the specific rule violations.
Which countries can receive the generated UBL invoice?
Any country connected to the global Peppol network — including Norway, Denmark, Sweden, Finland, Singapore, Australia, New Zealand, the Netherlands, Belgium, and Italy. The same UBL 2.1 document can be delivered to any Peppol-certified access point worldwide.
How does this differ from /create/xrechnung?
Both produce EN 16931 compliant XML. /create/ubl produces UBL 2.1 syntax for the Peppol network and is the right choice for international B2G invoicing. /create/xrechnung produces CII XML with additional German CIUS constraints (KoSIT) and is required for German federal portals (ZRE, OZG-RE).
Do I need to calculate totals myself?
No. Totals and tax breakdown are auto-calculated from your line items when omitted. You can still provide them explicitly if you prefer.
Can I include multiple VAT rates?
Yes. Each line item specifies its own TaxPercentage and TaxCategoryCode. The API automatically computes the tax breakdown by grouping lines with the same VAT rate and category, as required by EN 16931 and Peppol BIS Billing 3.0.