Automation Blog Contact
EN FR DE
Back to Blog
API Feb 4, 2026 14 min read

UBL REST-API: The Complete Universal Business Language Invoice Toolkit

InvoiceXML provides a complete UBL API toolkit: convert any document to UBL, create UBL from structured data, validate against EN 16931 and Peppol BIS 3.0 rules, render UBL as a human-readable PDF, and convert between UBL and CII syntax. Everything is accessible via a single REST API.

If you are building anything that touches Peppol, you are building with UBL. Universal Business Language (UBL) 2.1 is the XML format underpinning the pan-European Peppol e-invoicing network — and increasingly, the global one. Belgium mandated Peppol-format B2B e-invoicing from January 2026. The Netherlands has required it for public sector since 2019. Norway, Sweden, Finland, Singapore, Australia, New Zealand, and Japan all use Peppol. The UK's 2029 mandate is built around a Peppol-like four-corner model. Wherever structured e-invoicing is required outside of Germany and France's hybrid formats, UBL is almost certainly the answer.

InvoiceXML provides a complete UBL API toolkit: convert any document to UBL, create UBL from structured data, validate against EN 16931 and Peppol BIS 3.0 rules, render UBL as a human-readable PDF, and convert between UBL and CII syntax. Everything is accessible via a single REST API, with no infrastructure to manage on your side.


What is UBL? Structure, namespaces, and why it matters

UBL (Universal Business Language) is an XML standard maintained by OASIS (Organization for the Advancement of Structured Information Standards). UBL 2.1, published in 2013, is the version adopted by EN 16931 as one of the two official syntax bindings for European e-invoicing alongside UN/CEFACT CII.

Where CII uses deeply nested, trade-agreement-oriented XML with verbose namespace prefixes like SpecifiedTradeSettlement and ApplicableHeaderTradeAgreement, UBL takes a flatter component-based approach. Invoice data is organised into reusable aggregate components (cac:) and basic components (cbc:), making the document more verbose in raw byte count but more straightforward for developers familiar with conventional data modelling.

Here is a minimal valid UBL 2.1 invoice:

<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
         xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
         xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">

  <cbc:CustomizationID>
    urn:cen.eu:en16931:2017
  </cbc:CustomizationID>
  <cbc:ID>INV-2025-001</cbc:ID>
  <cbc:IssueDate>2025-03-15</cbc:IssueDate>
  <cbc:DueDate>2025-04-15</cbc:DueDate>
  <cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
  <cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>

  <cac:AccountingSupplierParty>
    <cac:Party>
      <cac:PartyName>
        <cbc:Name>Acme BV</cbc:Name>
      </cac:PartyName>
      <cac:PostalAddress>
        <cbc:StreetName>Keizersgracht 1</cbc:StreetName>
        <cbc:CityName>Amsterdam</cbc:CityName>
        <cbc:PostalZone>1015 CN</cbc:PostalZone>
        <cac:Country>
          <cbc:IdentificationCode>NL</cbc:IdentificationCode>
        </cac:Country>
      </cac:PostalAddress>
      <cac:PartyTaxScheme>
        <cbc:CompanyID>NL123456789B01</cbc:CompanyID>
        <cac:TaxScheme>
          <cbc:ID>VAT</cbc:ID>
        </cac:TaxScheme>
      </cac:PartyTaxScheme>
    </cac:Party>
  </cac:AccountingSupplierParty>

  <cac:AccountingCustomerParty>
    <cac:Party>
      <cac:PartyName>
        <cbc:Name>Example SA</cbc:Name>
      </cac:PartyName>
      <cac:PostalAddress>
        <cbc:StreetName>Rue de la Loi 1</cbc:StreetName>
        <cbc:CityName>Brussels</cbc:CityName>
        <cbc:PostalZone>1000</cbc:PostalZone>
        <cac:Country>
          <cbc:IdentificationCode>BE</cbc:IdentificationCode>
        </cac:Country>
      </cac:PostalAddress>
    </cac:Party>
  </cac:AccountingCustomerParty>

  <cac:TaxTotal>
    <cbc:TaxAmount currencyID="EUR">210.00</cbc:TaxAmount>
    <cac:TaxSubtotal>
      <cbc:TaxableAmount currencyID="EUR">1000.00</cbc:TaxableAmount>
      <cbc:TaxAmount currencyID="EUR">210.00</cbc:TaxAmount>
      <cac:TaxCategory>
        <cbc:ID>S</cbc:ID>
        <cbc:Percent>21</cbc:Percent>
        <cac:TaxScheme>
          <cbc:ID>VAT</cbc:ID>
        </cac:TaxScheme>
      </cac:TaxCategory>
    </cac:TaxSubtotal>
  </cac:TaxTotal>

  <cac:LegalMonetaryTotal>
    <cbc:LineExtensionAmount currencyID="EUR">1000.00</cbc:LineExtensionAmount>
    <cbc:TaxExclusiveAmount currencyID="EUR">1000.00</cbc:TaxExclusiveAmount>
    <cbc:TaxInclusiveAmount currencyID="EUR">1210.00</cbc:TaxInclusiveAmount>
    <cbc:PayableAmount currencyID="EUR">1210.00</cbc:PayableAmount>
  </cac:LegalMonetaryTotal>

  <cac:InvoiceLine>
    <cbc:ID>1</cbc:ID>
    <cbc:InvoicedQuantity unitCode="HUR">10</cbc:InvoicedQuantity>
    <cbc:LineExtensionAmount currencyID="EUR">1000.00</cbc:LineExtensionAmount>
    <cac:Item>
      <cbc:Name>Software Development Services</cbc:Name>
      <cac:ClassifiedTaxCategory>
        <cbc:ID>S</cbc:ID>
        <cbc:Percent>21</cbc:Percent>
        <cac:TaxScheme>
          <cbc:ID>VAT</cbc:ID>
        </cac:TaxScheme>
      </cac:ClassifiedTaxCategory>
    </cac:Item>
    <cac:Price>
      <cbc:PriceAmount currencyID="EUR">100.00</cbc:PriceAmount>
    </cac:Price>
  </cac:InvoiceLine>

</Invoice>

A production UBL invoice with purchase order references, delivery addresses, multiple VAT categories, allowances, charges, and payment instruction details will be considerably longer. More importantly, UBL is highly customisable through CustomizationID — the value in this field determines which set of business rules applies. Peppol BIS Billing 3.0, XRechnung UBL, NLCIUS (Netherlands), EHF (Norway), and PINT (international) all use different customisation identifiers and carry additional validation rules on top of the base EN 16931 Schematron.

This is why UBL validation is harder than it looks. It is not enough to validate against the EN 16931 Schematron alone — you must also validate against the specific Peppol or national CIUS Schematron that the CustomizationID declares. Miss this and your invoices will pass your internal tests but fail at the Peppol access point or government portal.


The InvoiceXML UBL API toolkit

InvoiceXML handles the full UBL lifecycle via REST API. Every endpoint automatically detects the CustomizationID and applies the correct validation rules — you do not need to specify which Peppol profile or national CIUS to use. The API figures it out from the document itself.

Base URL: https://api.invoicexml.com
Authentication: Authorization: Bearer YOUR_API_KEY
Content-Type: multipart/form-data

Tool 1: Convert any invoice to UBL

What it does: Accepts any invoice document — PDF (native or scanned), DOCX, XLSX, JPEG, PNG, TIFF, HEIC — and returns a validated UBL 2.1 XML document. The AI pipeline reads the source document, extracts every required EN 16931 field, maps the data to the UBL component model, and validates the output against EN 16931 and Peppol BIS 3.0 Schematron rules before returning it.

When to use it: You operate a Peppol access point and need to accept PDF invoices from suppliers not yet capable of generating UBL natively. You are building an AP automation tool that needs to normalise incoming invoices into a single structured format regardless of how suppliers send them. You are an accountant or bookkeeper whose clients send PDF invoices but whose client's ERP expects UBL input.

curl -X POST https://api.invoicexml.com/v1/transform/to/ubl \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "[email protected]" \
  -F "profile=en16931"

The profile parameter accepts minimum, basicwl, basic, en16931, and extended. When targeting Peppol specifically, use en16931 — Peppol BIS 3.0 is built on the EN 16931 CIUS and all required fields will be present in the output.

The endpoint also accepts scanned documents — OCR is applied automatically, with no preprocessing or template configuration required on your side.


Tool 2: Create UBL from structured data

What it does: Accepts structured invoice data as form fields and returns a validated UBL 2.1 XML document. You supply seller details, buyer details, line items, tax breakdown, and payment information — the API handles the XML generation, namespace management, and Schematron validation.

When to use it: You are building an invoicing feature in a SaaS product, ERP system, or accounting platform. You already have invoice data in your database or application and need to produce Peppol-ready UBL output. You want to add e-invoicing to your product without implementing the UBL schema, Peppol BIS rules, or Saxon-HE Schematron execution yourself.

curl -X POST https://api.invoicexml.com/v1/create/ubl \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "InvoiceNumber=INV-2025-042" \
  -F "IssueDate=2025-03-15" \
  -F "PaymentDueDate=2025-04-15" \
  -F "SellerName=Acme BV" \
  -F "SellerTaxId=NL123456789B01" \
  -F "SellerStreet=Keizersgracht 1" \
  -F "SellerPostcode=1015 CN" \
  -F "SellerCity=Amsterdam" \
  -F "SellerCountry=NL" \
  -F "BuyerName=Example SA" \
  -F "BuyerStreet=Rue de la Loi 1" \
  -F "BuyerPostcode=1000" \
  -F "BuyerCity=Brussels" \
  -F "BuyerCountry=BE" \
  -F "Currency=EUR" \
  -F "TaxBasisTotal=1000.00" \
  -F "TaxTotalAmount=210.00" \
  -F "GrandTotalAmount=1210.00" \
  -F "PaymentMeansCode=30" \
  -F "IBAN=NL91ABNA0417164300" \
  -F "Lines[0][description]=Software Development Services" \
  -F "Lines[0][quantity]=10" \
  -F "Lines[0][unitPrice]=100.00" \
  -F "Lines[0][lineTotal]=1000.00" \
  -F "Lines[0][unitCode]=HUR" \
  -F "Lines[0][taxPercentage]=21" \
  -F "Lines[0][taxCategoryCode]=S"

The PaymentMeansCode field uses UN/CEFACT code list 4461 — 30 for credit transfer, 58 for SEPA credit transfer, 49 for direct debit. IBAN and BIC are optional but required for Peppol BIS 3.0 when PaymentMeansCode is 30 or 58.

UBL credit notes are also supported. Pass document_type=credit_note to generate a <CreditNote> document rather than an <Invoice>.


Tool 3: Validate UBL

What it does: Accepts a UBL 2.1 invoice or credit note and validates it through a multi-layer pipeline: UBL 2.1 XSD schema validation, EN 16931 Schematron business rules, and — where applicable — the CIUS-specific Schematron rules declared by the document's CustomizationID. Peppol BIS Billing 3.0, NLCIUS, EHF, and PINT profiles are all detected and validated automatically.

When to use it: Before submitting to a Peppol access point. During development when testing your UBL generation logic. When receiving incoming UBL invoices from suppliers and wanting to verify they are genuinely compliant before ingesting into your ERP — a common issue, as many businesses generate UBL that passes superficial checks but fails Peppol network validation.

curl -X POST https://api.invoicexml.com/v1/validate/ubl \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "[email protected]"

The response distinguishes between errors (blocking — the document is non-compliant) and warnings (non-blocking — the document is valid but contains an advisory):

{
  "valid": true,
  "errorCount": 0,
  "warningCount": 1,
  "errors": [],
  "warnings": [
    {
      "rule": "PEPPOL-EN16931-R004",
      "message": "Invoice type code should be 380 for a standard invoice.",
      "source": "schematron",
      "layer": "peppol-bis"
    }
  ]
}

Note the layer field — it tells you whether a violation came from the base EN 16931 rules or from the Peppol BIS overlay. This matters when debugging: an EN 16931 violation means your document is non-compliant with the European standard; a Peppol BIS violation means it is EN 16931-compliant but will be rejected by the Peppol network specifically.

Pass strict=true to treat warnings as errors — useful when you need hard guarantees before network submission.


Tool 4: Preview UBL as PDF

What it does: Accepts a UBL 2.1 invoice or credit note and renders it as a human-readable PDF. The output is a clean, professionally formatted invoice document generated directly from the UBL structured data, with all fields labelled in plain language rather than XML namespace notation.

When to use it: Your Peppol access point delivers UBL XML to your accounts payable inbox. Your team needs to review, approve, or dispute individual invoices before processing — but they cannot read XML. This endpoint gives them a readable version without requiring any desktop software installation or specialist e-invoicing viewer.

Also invaluable during testing: when your UBL generation pipeline produces output that passes validation but something looks wrong with the amounts or line items, rendering it as a PDF is the fastest way to spot the problem visually.

curl -X POST https://api.invoicexml.com/v1/render/ubl/to/pdf \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "[email protected]" \
  --output preview.pdf

UBL credit notes are detected automatically from the root element and rendered with appropriate labelling — negative amounts, credit note type codes, and reason codes are all clearly surfaced in the output.

The CustomizationID is read and the profile identity (Peppol BIS 3.0, NLCIUS, EHF, etc.) is shown in the document header of the rendered PDF, so reviewers immediately know which network profile the invoice was generated for.

Important: The rendered PDF is for visual review only. It is not a PDF/A-3 container, it has no legal standing, and it does not carry embedded XML. The original UBL XML remains the authoritative compliance document.


Tool 5: Convert between UBL and CII

What it does: Performs lossless bidirectional conversion between UBL 2.1 and CII D16B syntax. Both syntaxes express the same EN 16931 semantic data model — the conversion maps every Business Term (BT) from one XML grammar to the other without data loss. The output is validated against EN 16931 Schematron before delivery.

Why this matters — the cross-network interoperability problem:

European e-invoicing is split along a syntax fault line. Germany and France built their hybrid formats (ZUGFeRD and Factur-X) on CII. Peppol, Belgium, the Netherlands, and the Nordics built on UBL. A German supplier sending invoices to both German business customers (ZUGFeRD/CII) and Belgian customers via Peppol (UBL) needs to produce both syntaxes from the same invoice data. Maintaining two separate generation pipelines doubles your compliance surface — updates to EN 16931 need to be applied in both. The better architecture is to generate in one syntax and convert on demand.

Similarly, a French company receiving Factur-X invoices (CII embedded in PDF) and needing to submit them to a Dutch Peppol access point needs CII-to-UBL conversion as infrastructure.

When to use it:

  • Your ERP generates CII natively (ZUGFeRD output) and you need Peppol UBL for cross-border submissions
  • You receive Peppol UBL invoices and want to archive them as CII embedded in PDF/A-3 (Factur-X format)
  • You are building a multi-market invoicing tool and want a single canonical format with on-demand syntax conversion
  • You are a Peppol access point operator normalising incoming documents from multiple network types
# UBL → CII (for ZUGFeRD/Factur-X embedding)
curl -X POST https://api.invoicexml.com/v1/convert/ubl/to/cii \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "[email protected]" \
  --output invoice-cii.xml

# CII → UBL (for Peppol submission)
curl -X POST https://api.invoicexml.com/v1/convert/cii/to/ubl \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "[email protected]" \
  --output invoice-ubl.xml

Both endpoints preserve all EN 16931 Business Terms. Fields that exist in one syntax but have no direct equivalent in the other (syntax-specific extensions) are mapped to the closest semantic equivalent or included as additional document references where the standard allows.


UBL across Peppol markets: what you actually need to know

The UBL specification itself is relatively stable — OASIS published UBL 2.1 in 2013 and it has not been superseded for e-invoicing purposes. What changes constantly are the CIUS profiles layered on top of it.

Peppol BIS Billing 3.0 is the dominant profile for cross-border European invoicing. OpenPeppol maintains it and releases updates quarterly — minor clarifications, code list updates, and occasionally new mandatory fields. Each update is reflected in a new version of the Peppol BIS Schematron, which must be deployed before the deprecation deadline or your validation will accept invoices that the network rejects.

National profiles add further rules:

  • NLCIUS (Netherlands) adds Dutch-specific constraints around GLN identifiers and municipal buyer references
  • EHF (Norway) has its own version history and Norwegian-specific business rules
  • PINT (Peppol International) is a newer specification designed for cross-regional Peppol (EU ↔ APAC) with additional fields for non-EU tax systems
  • Belgium mandates Peppol BIS 3.0 directly but with specific requirements around the Peppol participant identifier (0208 scheme)

Managing all of this — tracking release schedules, updating Schematron files, testing against each profile's test suite, deploying before deprecation deadlines — is a continuous operational commitment. InvoiceXML maintains all of these profiles and deploys updates ahead of their effective dates. Your integration does not change when a new Peppol BIS version ships; only the validation engine behind the API updates.


Why the InvoiceXML UBL API rather than an open-source library?

UBL has strong open-source library support in most languages. The OASIS UBL XSDs are freely available. The Peppol BIS Schematrons are published on GitHub. You can absolutely build a UBL pipeline yourself. Here is what that actually involves:

Profile management is a full-time job. Peppol BIS releases update several times per year. Each release involves downloading new Schematron XSLT files, testing them against your existing invoice samples, checking for breaking changes in business rule semantics, and deploying before the old version is deprecated. Miss a release and your customers' invoices start failing at the access point with cryptic PEPPOL-EN16931-R... error codes at 11pm on a Friday.

Multi-profile validation requires conditional logic. A UBL document bound to Peppol BIS 3.0 needs different validation than one bound to NLCIUS. You need to read the CustomizationID, look up the corresponding Schematron, and run the right validation stack. The logic is not complex but it needs to be implemented, tested, and maintained for every profile you support.

XSLT 2.0 execution is a non-trivial dependency. The Peppol BIS Schematrons require an XSLT 2.0 processor. In Java, Saxon-HE is the standard choice. In .NET, there is no official free native option — the best available approach is IKVM-based Saxon-HE cross-compilation, which is a community package rather than an officially supported product. In Python and Node.js, options are even more limited. Depending on your stack, adding XSLT 2.0 support is a meaningful infrastructure change.

Credit note support doubles your test matrix. UBL defines <Invoice> and <CreditNote> as separate document types with slightly different element constraints. Both need separate validation, separate generation logic, and separate rendering. Many library implementations handle one better than the other.

Security is a first-order concern, not an afterthought. UBL invoices contain sensitive financial data: company names, VAT registration numbers, bank account details (IBAN, BIC), payment amounts, and business relationships. A self-hosted processing service that logs requests, retains uploaded files, or sends data to a third-party AI provider without disclosure is a GDPR liability. InvoiceXML processes all documents in memory only. Nothing is written to disk. Nothing is retained after the API response is delivered. No invoice data is used for model training. Our infrastructure is GDPR-compliant and HIPAA-certified — independently audited, not self-reported.

Our security team monitors the API infrastructure around the clock. Anomalous access patterns, unexpected traffic spikes, and potential injection attempts are detected and responded to in real time. Regular penetration tests and dependency audits are part of our standard operating procedure. You get enterprise-grade security for a compliance feature that is not your core product — without needing to staff or fund the security function yourself.

99.95% uptime backed by a contract, not a blog post. Invoice processing is often synchronous in financial workflows — your system cannot queue an invoice indefinitely waiting for the compliance layer. We operate redundant infrastructure across multiple availability zones with automatic failover. Our live status page shows the full uptime history since launch. Every plan above Free includes an uptime SLA.


Complete UBL API endpoint reference

Operation Endpoint Input Output
PDF/document to UBL (AI) POST /v1/transform/to/ubl PDF, image, DOCX, XLSX UBL 2.1 XML
Create UBL POST /v1/create/ubl JSON UBL 2.1 XML
Validate UBL POST /v1/validate/ubl UBL 2.1 XML Validation result JSON
Preview UBL as PDF POST /v1/render/ubl/to/pdf UBL 2.1 XML PDF
UBL to CII POST /v1/convert/ubl/to/cii UBL 2.1 XML CII XML
CII to UBL POST /v1/convert/cii/to/ubl CII XML UBL 2.1 XML

All endpoints are available at https://api.invoicexml.com. Authentication uses a Bearer token in the Authorization header. All error responses follow RFC 7807 ProblemDetails with structured errorCode fields. Human-readable error messages are available via the ?errors=friendly query parameter — useful for surfacing validation failures in no-code workflows and user-facing applications.

The full OpenAPI 3.1 schema is available at api.invoicexml.com/openapi, importable directly into Postman, Insomnia, or any OpenAPI-compatible client generator.


Supported UBL profiles and customisations

Profile / CIUS CustomizationID Used by Auto-detected
EN 16931 plain urn:cen.eu:en16931:2017 Generic EU e-invoicing
Peppol BIS Billing 3.0 urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0 Pan-European Peppol
NLCIUS urn:cen.eu:en16931:2017#compliant#urn:fdc:nen.nl:nlcius:v1.0 Netherlands public sector
EHF Billing 3.0 urn:cen.eu:en16931:2017#compliant#urn:fdc:anskaffelser.no:2019:ehf:spec:3.0 Norway
PINT (international) urn:peppol:pint:billing-1 Cross-regional Peppol
XRechnung UBL (CIUS-REC-DE) urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_3.0 German public sector
UBL CreditNote Root element <CreditNote> Credit notes / corrections

Get started

The fastest way to evaluate the UBL API is to upload a UBL XML file or a PDF invoice at invoicexml.com/pdf-to-ubl — no account or API key required.

To integrate via API, start your free 30-day trial. A permanent free tier of 100 credits per month is available after the trial expires — enough to keep your integration alive throughout development and into low-volume production.

Related resources:


InvoiceXML is the compliance layer for modern European e-invoicing. It covers UBL, CII, ZUGFeRD, Factur-X, XRechnung, and EN 16931 via a single REST API — with no data retained, no Peppol profile tracking required, and no Schematron maintenance on your side.