Peppol BIS 3.0
Peppol BIS Billing 3.0 is the recommended format for invoice exchange through Maventa. It implements the European standard EN16931-1:2017 using UBL 2.1 XML syntax, and is mandatory for cross-border invoicing over the Peppol network. Some countries also accept national formats for domestic Peppol traffic.
This page covers the XML format itself. For Peppol network registration and participant lookup, see the Peppol network page. For sending and receiving documents via the API, see the document exchange page.
The Peppol BIS 3.0 specification is updated regularly. Required and conditional fields may change between releases. Always check the latest implementation guidelines for current rules.
Document identifiers
Every Peppol BIS 3.0 invoice must include CustomizationID and ProfileID elements that identify the document specification and business process.
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>These values are the same for both invoices and credit notes. The document type is determined by the root element (Invoice or CreditNote) and the InvoiceTypeCode / CreditNoteTypeCode element.
For the full document identifier strings used in Peppol registration, see the document types section on the invoicing formats page.
Invoice structure overview
A Peppol BIS 3.0 invoice uses the UBL 2.1 Invoice root element. The following table lists the required and commonly used top-level elements.
| Element | Required | Description |
|---|---|---|
cbc:CustomizationID |
Yes | Specification identifier (see above) |
cbc:ProfileID |
Yes | Business process identifier (see above) |
cbc:ID |
Yes | Invoice number |
cbc:IssueDate |
Yes | Invoice date (YYYY-MM-DD) |
cbc:DueDate |
Conditional | Payment due date. Either DueDate or PaymentTerms must be provided. |
cbc:InvoiceTypeCode |
Yes |
380 for commercial invoice, 384 for corrected invoice, 389 for self-billing invoice, 751 for invoice information for accounting purposes |
cbc:DocumentCurrencyCode |
Yes | ISO 4217 currency code (e.g., EUR) |
cbc:BuyerReference |
Yes | Buyer’s reference or order number. Required by Peppol even if the buyer has not provided one — use N/A as fallback. |
cac:AccountingSupplierParty |
Yes | Seller details |
cac:AccountingCustomerParty |
Yes | Buyer details |
cac:TaxTotal |
Yes | Tax breakdown |
cac:LegalMonetaryTotal |
Yes | Invoice totals |
cac:InvoiceLine |
Yes | At least one invoice line |
Minimal invoice skeleton
The following shows the high-level structure of a Peppol BIS 3.0 invoice. Each section is covered in detail below.
<?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#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
<cbc:ID>INV-2024-001</cbc:ID>
<cbc:IssueDate>2024-01-15</cbc:IssueDate>
<cbc:DueDate>2024-02-15</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
<cbc:BuyerReference>PO-12345</cbc:BuyerReference>
<cac:AccountingSupplierParty><!-- ... --></cac:AccountingSupplierParty>
<cac:AccountingCustomerParty><!-- ... --></cac:AccountingCustomerParty>
<cac:TaxTotal><!-- ... --></cac:TaxTotal>
<cac:LegalMonetaryTotal><!-- ... --></cac:LegalMonetaryTotal>
<cac:InvoiceLine><!-- ... --></cac:InvoiceLine>
</Invoice>Parties (supplier and buyer)
Both AccountingSupplierParty and AccountingCustomerParty follow the same structure. The key required elements are:
| Element | Required | Description |
|---|---|---|
cbc:EndpointID |
Yes | Electronic address with schemeID attribute (e.g., 0216 for Finnish OVT code) |
cac:PartyIdentification/cbc:ID |
No | Additional party identifier |
cac:PartyName/cbc:Name |
No | Trading name |
cac:PostalAddress |
Yes | Street, city, postal code, country |
cac:PartyTaxScheme |
No | VAT number (cbc:CompanyID) with tax scheme VAT. Not all companies have a VAT identifier. |
cac:PartyLegalEntity/cbc:RegistrationName |
Yes | Legal registration name |
cac:PartyLegalEntity/cbc:CompanyID |
No | Company registration number |
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="0216">003712345678</cbc:EndpointID>
<cac:PartyName>
<cbc:Name>Supplier Oy</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Esimerkkikatu 1</cbc:StreetName>
<cbc:CityName>Helsinki</cbc:CityName>
<cbc:PostalZone>00100</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>FI</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>FI12345678</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Supplier Oy</cbc:RegistrationName>
<cbc:CompanyID>1234567-8</cbc:CompanyID>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingSupplierParty>The EndpointID schemeID value identifies the type of electronic address. Common scheme IDs and endpoint ID formats include:
| Scheme ID | Country | Endpoint ID format |
|---|---|---|
0216 |
Finland | OVT code (e.g., 003712345678) |
0007 |
Sweden | Organization number (e.g., 5567891234) |
0088 |
International | GLN (Global Location Number) |
0184 |
Denmark | CVR number (e.g., 12345678) |
0192 |
Norway | Organization number (e.g., 987654321) |
0106 |
Netherlands | KvK number (e.g., 12345678) |
For a full list, see the EAS code list in the Peppol documentation. For endpoint ID formats and details for each country Maventa supports, see the Services & Reach country pages.
Tax and totals
TaxTotal
The TaxTotal element provides a total tax amount and a breakdown by tax category. Each TaxSubtotal groups all line amounts with the same tax rate and category.
<cac:TaxTotal>
<cbc:TaxAmount currencyID="EUR">240.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">1000.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">240.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>24.00</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>Common tax category codes:
| Code | Description |
|---|---|
S |
Standard rate |
Z |
Zero rated |
E |
Exempt from tax |
AE |
Reverse charge (VAT paid by buyer) |
K |
Intra-community supply |
O |
Not subject to VAT |
Tax categories with a zero percent rate (E, AE, K, O) require a TaxExemptionReasonCode or TaxExemptionReason (free text) inside the TaxCategory element to explain why VAT is not charged.
<cac:TaxCategory>
<cbc:ID>E</cbc:ID>
<cbc:Percent>0.00</cbc:Percent>
<cbc:TaxExemptionReasonCode>vatex-eu-132</cbc:TaxExemptionReasonCode>
<cbc:TaxExemptionReason>Exempt based on article 132 of Council Directive 2006/112/EC</cbc:TaxExemptionReason>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>LegalMonetaryTotal
The LegalMonetaryTotal element summarizes the invoice amounts. All amounts must use 2 decimal places.
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="EUR">1000.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="EUR">1000.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="EUR">1240.00</cbc:TaxInclusiveAmount>
<cbc:PayableAmount currencyID="EUR">1240.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>| Element | Required | Description |
|---|---|---|
LineExtensionAmount |
Yes | Sum of all invoice line net amounts |
TaxExclusiveAmount |
Yes | Total amount without VAT (line extension + document-level charges - document-level allowances) |
TaxInclusiveAmount |
Yes | Total amount with VAT |
AllowanceTotalAmount |
No | Sum of document-level allowances |
ChargeTotalAmount |
No | Sum of document-level charges |
PayableRoundingAmount |
No | Rounding amount to reach PayableAmount
|
PayableAmount |
Yes | Amount to be paid |
Invoice lines
Each InvoiceLine represents a line item on the invoice.
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="EA">10</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">1000.00</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Name>Product name</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>24.00</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>| Element | Required | Description |
|---|---|---|
cbc:ID |
Yes | Line identifier (unique within the invoice) |
cbc:InvoicedQuantity |
Yes | Quantity with unitCode attribute (UN/ECE Rec 20 codes, e.g., EA for each, HUR for hour, KGM for kilogram) |
cbc:LineExtensionAmount |
Yes | Net amount for the line (quantity x price, adjusted for line-level allowances/charges) |
cac:Item/cbc:Name |
Yes | Item name or description |
cac:Item/cac:ClassifiedTaxCategory |
Yes | Tax category and rate for the line |
cac:Price/cbc:PriceAmount |
Yes | Unit price excluding VAT |
For item identification, you can optionally include:
-
cac:Item/cac:SellersItemIdentification/cbc:ID— seller’s article number -
cac:Item/cac:StandardItemIdentification/cbc:ID— standard identifier (e.g., GTIN) withschemeIDattribute -
cac:Item/cac:CommodityClassification/cbc:ItemClassificationCode— classification code (e.g., UNSPSC)
For unit codes, see the UN/ECE Recommendation 20 and 21 reference.
Line-level allowances and charges
Line-level allowances and charges appear inside InvoiceLine and affect the LineExtensionAmount of that line. They do not include a TaxCategory (the line’s tax category applies).
Provide either AllowanceChargeReasonCode (from the UNCL7161 code list) or AllowanceChargeReason (free text), or both.
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="EA">10</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">900.00</cbc:LineExtensionAmount>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:AllowanceChargeReasonCode>95</cbc:AllowanceChargeReasonCode>
<cbc:AllowanceChargeReason>Discount</cbc:AllowanceChargeReason>
<cbc:Amount currencyID="EUR">100.00</cbc:Amount>
</cac:AllowanceCharge>
<cac:Item>
<cbc:Name>Product name</cbc:Name>
<!-- ... -->
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="EUR">100.00</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>In this example, 10 units at 100.00 EUR = 1000.00, minus a 100.00 EUR discount, gives a LineExtensionAmount of 900.00 EUR.
Allowances and charges
Allowances (discounts) and charges can also be applied at the document level. Both use the same AllowanceCharge structure, distinguished by the ChargeIndicator element. Provide either AllowanceChargeReasonCode (from the UNCL7161 code list) or AllowanceChargeReason (free text), or both.
Document-level allowances and charges
Document-level allowances and charges appear directly under the Invoice root element and affect the invoice totals.
<!-- Document-level allowance (discount) -->
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:AllowanceChargeReasonCode>95</cbc:AllowanceChargeReasonCode>
<cbc:AllowanceChargeReason>Discount</cbc:AllowanceChargeReason>
<cbc:Amount currencyID="EUR">50.00</cbc:Amount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>24.00</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:AllowanceCharge>
<!-- Document-level charge (e.g., shipping) -->
<cac:AllowanceCharge>
<cbc:ChargeIndicator>true</cbc:ChargeIndicator>
<cbc:AllowanceChargeReasonCode>FC</cbc:AllowanceChargeReasonCode>
<cbc:AllowanceChargeReason>Freight charge</cbc:AllowanceChargeReason>
<cbc:Amount currencyID="EUR">15.00</cbc:Amount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>24.00</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:AllowanceCharge>-
ChargeIndicator=falsefor allowances (discounts),truefor charges - Document-level allowances and charges must include a
TaxCategory
Credit notes
Credit notes use a separate root element CreditNote instead of Invoice. The XML namespaces and structure are otherwise the same, with a few key differences:
| Aspect | Invoice | Credit note |
|---|---|---|
| Root element | Invoice |
CreditNote |
| Type code element | InvoiceTypeCode |
CreditNoteTypeCode |
| Type code value |
380 (standard) |
381 (credit note) |
| Quantity element | InvoicedQuantity |
CreditedQuantity |
| Line element | InvoiceLine |
CreditNoteLine |
Amounts in a credit note are positive — the credit note document type itself indicates that the amounts are to be subtracted.
Referencing the original invoice
Use BillingReference to link the credit note to the original invoice:
<CreditNote xmlns="urn:oasis:names:specification:ubl:schema:xsd:CreditNote-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#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
<cbc:ID>CN-2024-001</cbc:ID>
<cbc:IssueDate>2024-02-01</cbc:IssueDate>
<cbc:CreditNoteTypeCode>381</cbc:CreditNoteTypeCode>
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
<cbc:BuyerReference>PO-12345</cbc:BuyerReference>
<cac:BillingReference>
<cac:InvoiceDocumentReference>
<cbc:ID>INV-2024-001</cbc:ID>
<cbc:IssueDate>2024-01-15</cbc:IssueDate>
</cac:InvoiceDocumentReference>
</cac:BillingReference>
<!-- Remaining structure follows the same pattern as Invoice -->
</CreditNote>Attachments
Peppol BIS 3.0 supports embedding attachments in the invoice XML using the AdditionalDocumentReference element.
Supported MIME types
| MIME type | Description |
|---|---|
application/pdf |
PDF document |
image/png |
PNG image |
image/jpeg |
JPEG image |
text/csv |
CSV file |
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
Excel spreadsheet (.xlsx) |
application/vnd.oasis.opendocument.spreadsheet |
OpenDocument spreadsheet (.ods) |
Embedding an attachment
<cac:AdditionalDocumentReference>
<cbc:ID>ATT-001</cbc:ID>
<cbc:DocumentDescription>Timesheet for January 2024</cbc:DocumentDescription>
<cac:Attachment>
<cbc:EmbeddedDocumentBinaryObject mimeCode="application/pdf"
filename="timesheet-2024-01.pdf">
<!-- Base64 encoded content -->
JVBERi0xLjQKMSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZw...
</cbc:EmbeddedDocumentBinaryObject>
</cac:Attachment>
</cac:AdditionalDocumentReference>You can also reference an external document by URL instead of embedding:
<cac:AdditionalDocumentReference>
<cbc:ID>ATT-002</cbc:ID>
<cac:Attachment>
<cac:ExternalReference>
<cbc:URI>https://example.com/documents/timesheet.pdf</cbc:URI>
</cac:ExternalReference>
</cac:Attachment>
</cac:AdditionalDocumentReference>Validation
Peppol BIS 3.0 invoices are validated at three levels:
- UBL 2.1 XSD schema validation — Checks that the XML structure conforms to the UBL 2.1 schema (correct elements, data types, and structure).
- EN16931 schematron rules — European standard business rules that check calculation correctness, required fields, and cross-field consistency.
-
Peppol business rules — Additional rules specific to the Peppol network (e.g.,
EndpointIDmust be present,CustomizationIDmust match the Peppol BIS 3.0 identifier).
Maventa automatically validates outgoing Peppol invoices against all three rule sets. If validation fails, the invoice is rejected with an error describing which rule was violated.
For more details on validation and how to pre-validate your invoices, see the /integration-guide/invoicing-formats/validation/ page and the Validator API.
Key code lists
| Code list | Usage | Reference |
|---|---|---|
| EAS |
EndpointID scheme IDs |
Peppol EAS list |
| ICD (ISO 6523) |
PartyIdentification/ID and PartyLegalEntity/CompanyID scheme IDs |
Peppol ICD list |
| ISO 4217 | Currency codes (DocumentCurrencyCode, amounts) |
Peppol currency list |
| UNCL5305 (subset) | Tax category codes (S, Z, E, AE, etc.) |
Peppol tax category list |
| UNCL7161 | Allowance/charge reason codes | Peppol UNCL7161 list |
| UNCL1001 (subset) | Invoice type codes (380, 381, 384, etc.) |
Peppol invoice type list |
| UN/ECE Rec 20 + 21 | Unit of measure codes (EA, HUR, KGM, etc.) |
Peppol unit codes |
| MIME types | Attachment content types | Peppol MIME list |
External resources
- Peppol BIS Billing 3.0 specification — official documentation with syntax bindings, rules, and code lists
- Peppol BIS Billing 3.0 latest release (2025-Q4) — most recent published version
- Peppol Post-Award technical documentation — latest releases and announcements from Peppol
- UBL 2.1 schema files — OASIS UBL XML schema definitions
- Example Peppol BIS 3.0 invoice XML — Maventa example file
- All example XML files — example invoices in all supported formats