Skip to content

Peppol XML invoice example

A complete Peppol BIS Billing 3 invoice in UBL XML that passes validation, explained field by field, with a broken copy that shows what a totals error looks like and how it is fixed.

Download or validate the example

Result
Valid: XML, UBL schema, EN 16931 and Peppol layers all passed, with no warnings.
Checked
23 September 2026, with the free Ironfang Finance validator
Rules
Peppol BIS Billing 3.0, May 2026 release (2026.5, also known as 3.0.21); ruleset fwrs_bis3_billing_invoice_2026_5_r4, VESID eu.peppol.bis3:invoice:2026.5
Engine
phive 12.1.0 with phive-rules-peppol 4.5.6 and Saxon-HE 12.10
SHA-256
c9d1474941163526a1a518405de43c5a31d3f5261a72adf80877cc9389534ea9

Everything in it is fictional: example.test addresses, and GS1 location numbers under prefix 952, which GS1 reserves for demonstrations. The endpoint identifiers are not registered Peppol participants; never send a real document to them.

The whole invoice

This is the complete document, exactly as downloaded. The sections below take it apart. It is the same file the validator's Try a valid sample button sends.

<?xml version="1.0" encoding="UTF-8"?>
<!--
  A fictional Peppol BIS Billing 3.0 invoice published by Ironfang for the
  free validator at https://ironfang.uk/tools/peppol-validator. Every party,
  identifier, address and amount is invented: example.test names, GS1
  location numbers under prefix 952, which GS1 designates for demonstrations
  and examples, and an account reference that is not a bank account. Reuse it
  freely.
-->
<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>EX-2026-0001</cbc:ID>
    <cbc:IssueDate>2026-06-15</cbc:IssueDate>
    <cbc:DueDate>2026-07-15</cbc:DueDate>
    <cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
    <cbc:Note>Fictional sample invoice for the Ironfang Peppol validator.</cbc:Note>
    <cbc:DocumentCurrencyCode>GBP</cbc:DocumentCurrencyCode>
    <cbc:BuyerReference>PO-EXAMPLE-0001</cbc:BuyerReference>
    <cac:AccountingSupplierParty>
        <cac:Party>
            <cbc:EndpointID schemeID="0088">9520000000011</cbc:EndpointID>
            <cac:PartyIdentification>
                <cbc:ID schemeID="0088">9520000000011</cbc:ID>
            </cac:PartyIdentification>
            <cac:PartyName>
                <cbc:Name>Example Supplier Ltd</cbc:Name>
            </cac:PartyName>
            <cac:PostalAddress>
                <cbc:StreetName>1 Example Street</cbc:StreetName>
                <cbc:CityName>Exampleton</cbc:CityName>
                <cbc:PostalZone>EX1 1EX</cbc:PostalZone>
                <cac:Country>
                    <cbc:IdentificationCode>GB</cbc:IdentificationCode>
                </cac:Country>
            </cac:PostalAddress>
            <cac:PartyTaxScheme>
                <cbc:CompanyID>GB000000000</cbc:CompanyID>
                <cac:TaxScheme>
                    <cbc:ID>VAT</cbc:ID>
                </cac:TaxScheme>
            </cac:PartyTaxScheme>
            <cac:PartyLegalEntity>
                <cbc:RegistrationName>Example Supplier Ltd</cbc:RegistrationName>
            </cac:PartyLegalEntity>
            <cac:Contact>
                <cbc:Name>Accounts</cbc:Name>
                <cbc:ElectronicMail>accounts@supplier.example.test</cbc:ElectronicMail>
            </cac:Contact>
        </cac:Party>
    </cac:AccountingSupplierParty>
    <cac:AccountingCustomerParty>
        <cac:Party>
            <cbc:EndpointID schemeID="0088">9520000000028</cbc:EndpointID>
            <cac:PartyIdentification>
                <cbc:ID schemeID="0088">9520000000028</cbc:ID>
            </cac:PartyIdentification>
            <cac:PartyName>
                <cbc:Name>Example Buyer Ltd</cbc:Name>
            </cac:PartyName>
            <cac:PostalAddress>
                <cbc:StreetName>2 Sample Road</cbc:StreetName>
                <cbc:CityName>Sampleford</cbc:CityName>
                <cbc:PostalZone>EX2 2EX</cbc:PostalZone>
                <cac:Country>
                    <cbc:IdentificationCode>GB</cbc:IdentificationCode>
                </cac:Country>
            </cac:PostalAddress>
            <cac:PartyLegalEntity>
                <cbc:RegistrationName>Example Buyer Ltd</cbc:RegistrationName>
            </cac:PartyLegalEntity>
            <cac:Contact>
                <cbc:Name>Purchasing</cbc:Name>
                <cbc:ElectronicMail>purchasing@buyer.example.test</cbc:ElectronicMail>
            </cac:Contact>
        </cac:Party>
    </cac:AccountingCustomerParty>
    <cac:Delivery>
        <cbc:ActualDeliveryDate>2026-06-10</cbc:ActualDeliveryDate>
    </cac:Delivery>
    <cac:PaymentMeans>
        <cbc:PaymentMeansCode name="Credit transfer">30</cbc:PaymentMeansCode>
        <cbc:PaymentID>EX-2026-0001</cbc:PaymentID>
        <cac:PayeeFinancialAccount>
            <cbc:ID>EXAMPLE-ACCOUNT-0001</cbc:ID>
            <cbc:Name>Example Supplier Ltd</cbc:Name>
        </cac:PayeeFinancialAccount>
    </cac:PaymentMeans>
    <cac:PaymentTerms>
        <cbc:Note>Payment within 30 days of the invoice date.</cbc:Note>
    </cac:PaymentTerms>
    <cac:TaxTotal>
        <cbc:TaxAmount currencyID="GBP">148.00</cbc:TaxAmount>
        <cac:TaxSubtotal>
            <cbc:TaxableAmount currencyID="GBP">740.00</cbc:TaxableAmount>
            <cbc:TaxAmount currencyID="GBP">148.00</cbc:TaxAmount>
            <cac:TaxCategory>
                <cbc:ID>S</cbc:ID>
                <cbc:Percent>20</cbc:Percent>
                <cac:TaxScheme>
                    <cbc:ID>VAT</cbc:ID>
                </cac:TaxScheme>
            </cac:TaxCategory>
        </cac:TaxSubtotal>
    </cac:TaxTotal>
    <cac:LegalMonetaryTotal>
        <cbc:LineExtensionAmount currencyID="GBP">740.00</cbc:LineExtensionAmount>
        <cbc:TaxExclusiveAmount currencyID="GBP">740.00</cbc:TaxExclusiveAmount>
        <cbc:TaxInclusiveAmount currencyID="GBP">888.00</cbc:TaxInclusiveAmount>
        <cbc:PayableAmount currencyID="GBP">888.00</cbc:PayableAmount>
    </cac:LegalMonetaryTotal>
    <cac:InvoiceLine>
        <cbc:ID>1</cbc:ID>
        <cbc:InvoicedQuantity unitCode="C62">10</cbc:InvoicedQuantity>
        <cbc:LineExtensionAmount currencyID="GBP">500.00</cbc:LineExtensionAmount>
        <cac:Item>
            <cbc:Description>Example widget, standard finish</cbc:Description>
            <cbc:Name>Example widget</cbc:Name>
            <cac:SellersItemIdentification>
                <cbc:ID>EX-WIDGET-01</cbc:ID>
            </cac:SellersItemIdentification>
            <cac:ClassifiedTaxCategory>
                <cbc:ID>S</cbc:ID>
                <cbc:Percent>20</cbc:Percent>
                <cac:TaxScheme>
                    <cbc:ID>VAT</cbc:ID>
                </cac:TaxScheme>
            </cac:ClassifiedTaxCategory>
        </cac:Item>
        <cac:Price>
            <cbc:PriceAmount currencyID="GBP">50.00</cbc:PriceAmount>
        </cac:Price>
    </cac:InvoiceLine>
    <cac:InvoiceLine>
        <cbc:ID>2</cbc:ID>
        <cbc:InvoicedQuantity unitCode="HUR">2</cbc:InvoicedQuantity>
        <cbc:LineExtensionAmount currencyID="GBP">240.00</cbc:LineExtensionAmount>
        <cac:Item>
            <cbc:Description>Installation of example widgets, per hour</cbc:Description>
            <cbc:Name>Installation service</cbc:Name>
            <cac:SellersItemIdentification>
                <cbc:ID>EX-INSTALL-01</cbc:ID>
            </cac:SellersItemIdentification>
            <cac:ClassifiedTaxCategory>
                <cbc:ID>S</cbc:ID>
                <cbc:Percent>20</cbc:Percent>
                <cac:TaxScheme>
                    <cbc:ID>VAT</cbc:ID>
                </cac:TaxScheme>
            </cac:ClassifiedTaxCategory>
        </cac:Item>
        <cac:Price>
            <cbc:PriceAmount currencyID="GBP">120.00</cbc:PriceAmount>
        </cac:Price>
    </cac:InvoiceLine>
</Invoice>
<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>EX-2026-0001</cbc:ID>
<cbc:IssueDate>2026-06-15</cbc:IssueDate>
<cbc:DueDate>2026-07-15</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:Note>Fictional sample invoice for the Ironfang Peppol validator.</cbc:Note>
<cbc:DocumentCurrencyCode>GBP</cbc:DocumentCurrencyCode>
<cbc:BuyerReference>PO-EXAMPLE-0001</cbc:BuyerReference>

Seller, buyer and electronic addresses

<cac:AccountingSupplierParty>
    <cac:Party>
        <cbc:EndpointID schemeID="0088">9520000000011</cbc:EndpointID>
        <cac:PartyIdentification>
            <cbc:ID schemeID="0088">9520000000011</cbc:ID>
        </cac:PartyIdentification>
        <cac:PartyName>
            <cbc:Name>Example Supplier Ltd</cbc:Name>
        </cac:PartyName>
        <cac:PostalAddress>
            <cbc:StreetName>1 Example Street</cbc:StreetName>
            <cbc:CityName>Exampleton</cbc:CityName>
            <cbc:PostalZone>EX1 1EX</cbc:PostalZone>
            <cac:Country>
                <cbc:IdentificationCode>GB</cbc:IdentificationCode>
            </cac:Country>
        </cac:PostalAddress>
        <cac:PartyTaxScheme>
            <cbc:CompanyID>GB000000000</cbc:CompanyID>
            <cac:TaxScheme>
                <cbc:ID>VAT</cbc:ID>
            </cac:TaxScheme>
        </cac:PartyTaxScheme>
        <cac:PartyLegalEntity>
            <cbc:RegistrationName>Example Supplier Ltd</cbc:RegistrationName>
        </cac:PartyLegalEntity>
        <cac:Contact>
            <cbc:Name>Accounts</cbc:Name>
            <cbc:ElectronicMail>accounts@supplier.example.test</cbc:ElectronicMail>
        </cac:Contact>
    </cac:Party>
</cac:AccountingSupplierParty>

The buyer is built the same way, with its own address:

<cbc:EndpointID schemeID="0088">9520000000028</cbc:EndpointID>

Invoice lines

<cac:InvoiceLine>
    <cbc:ID>1</cbc:ID>
    <cbc:InvoicedQuantity unitCode="C62">10</cbc:InvoicedQuantity>
    <cbc:LineExtensionAmount currencyID="GBP">500.00</cbc:LineExtensionAmount>
    <cac:Item>
        <cbc:Description>Example widget, standard finish</cbc:Description>
        <cbc:Name>Example widget</cbc:Name>
        <cac:SellersItemIdentification>
            <cbc:ID>EX-WIDGET-01</cbc:ID>
        </cac:SellersItemIdentification>
        <cac:ClassifiedTaxCategory>
            <cbc:ID>S</cbc:ID>
            <cbc:Percent>20</cbc:Percent>
            <cac:TaxScheme>
                <cbc:ID>VAT</cbc:ID>
            </cac:TaxScheme>
        </cac:ClassifiedTaxCategory>
    </cac:Item>
    <cac:Price>
        <cbc:PriceAmount currencyID="GBP">50.00</cbc:PriceAmount>
    </cac:Price>
</cac:InvoiceLine>

Each line has a quantity with a unit from UN/ECE Recommendation 20 (C62 means one unit, HUR an hour), a net amount, the item and its VAT category, and the unit price. Category S is the standard rate, here 20 percent. The line net amount is quantity times price, with no allowances or charges on these lines.

Invoice line calculations
LineItemQuantityPriceNet amount
1Example widget10 one (unit) (C62)50.0010 x 50.00 = 500.00
2Installation service2 hour (HUR)120.002 x 120.00 = 240.00

Tax breakdown and document totals

<cac:TaxTotal>
    <cbc:TaxAmount currencyID="GBP">148.00</cbc:TaxAmount>
    <cac:TaxSubtotal>
        <cbc:TaxableAmount currencyID="GBP">740.00</cbc:TaxableAmount>
        <cbc:TaxAmount currencyID="GBP">148.00</cbc:TaxAmount>
        <cac:TaxCategory>
            <cbc:ID>S</cbc:ID>
            <cbc:Percent>20</cbc:Percent>
            <cac:TaxScheme>
                <cbc:ID>VAT</cbc:ID>
            </cac:TaxScheme>
        </cac:TaxCategory>
    </cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
    <cbc:LineExtensionAmount currencyID="GBP">740.00</cbc:LineExtensionAmount>
    <cbc:TaxExclusiveAmount currencyID="GBP">740.00</cbc:TaxExclusiveAmount>
    <cbc:TaxInclusiveAmount currencyID="GBP">888.00</cbc:TaxInclusiveAmount>
    <cbc:PayableAmount currencyID="GBP">888.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>

Every total can be worked out from the lines, and the EN 16931 rules check each step:

How the totals reconcile
FieldCalculationGBPRule
LineExtensionAmount500.00 + 240.00740.00BR-CO-10
TaxExclusiveAmountLine total, less document allowances, plus charges (none here)740.00BR-CO-13
TaxableAmount (S, 20%)Net of the lines in category S740.00BR-S-08
TaxAmount (S, 20%)740.00 x 20%, rounded to two decimals148.00BR-S-09
TaxTotal/TaxAmountSum of the breakdown tax amounts148.00BR-CO-14
TaxInclusiveAmount740.00 + 148.00888.00BR-CO-15
PayableAmountTotal with VAT, less prepaid, plus rounding (neither here)888.00BR-CO-16

Calculate these with decimal arithmetic, not floating point, and round each amount to two decimals where the rules say so. A total built by adding binary floating-point numbers can come out a penny off, which is enough to fail. The Understanding EN 16931 validation errors article explains the calculation rules in more depth.

Payment details

<cac:PaymentMeans>
    <cbc:PaymentMeansCode name="Credit transfer">30</cbc:PaymentMeansCode>
    <cbc:PaymentID>EX-2026-0001</cbc:PaymentID>
    <cac:PayeeFinancialAccount>
        <cbc:ID>EXAMPLE-ACCOUNT-0001</cbc:ID>
        <cbc:Name>Example Supplier Ltd</cbc:Name>
    </cac:PayeeFinancialAccount>
</cac:PaymentMeans>
<cac:PaymentTerms>
    <cbc:Note>Payment within 30 days of the invoice date.</cbc:Note>
</cac:PaymentTerms>

Payment means code 30 is a credit transfer. PaymentID is the reference the buyer should quote when paying, and PayeeFinancialAccount/ID the account to pay into: an IBAN, or the account identifier your banking arrangement uses. This sample's account is a placeholder, not a bank account.

A broken copy, and the fix

The second sample is the same invoice with one number changed: the document's line total says 750.00 where the two lines add up to 740.00.

<cac:LegalMonetaryTotal>
    <cbc:LineExtensionAmount currencyID="GBP">750.00</cbc:LineExtensionAmount>
    <cbc:TaxExclusiveAmount currencyID="GBP">740.00</cbc:TaxExclusiveAmount>
    <cbc:TaxInclusiveAmount currencyID="GBP">888.00</cbc:TaxInclusiveAmount>
    <cbc:PayableAmount currencyID="GBP">888.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>

Validated on the same day with the same ruleset, it is invalid with exactly two findings, both fatal and both in the EN 16931 layer:

One wrong field produces two findings, because a second rule depends on the same value. The totals with VAT and payable still agree with each other, so no other rule fires. The fix is to put the true sum, 740.00, back into LegalMonetaryTotal/LineExtensionAmount: that is the valid sample above.

Adapting it to a real invoice

A valid result means the document passed the UBL schema, EN 16931 and Peppol BIS Billing rules for the stated release. It does not send the invoice, register anybody on the Peppol network, prove a recipient will accept it, or certify it for tax purposes. Delivery happens through a Peppol access point. The How Peppol invoice validation actually works article explains the layers a document passes through.

Validating from code

The validator on the site is free without an account. To check documents from your own system, send the same bytes to the validation API with an Ironfang API key that has the finance:einvoices:write scope:

curl --fail-with-body https://api.ironfang.uk/finance/v1/einvoices/validate \
  -H "Authorization: Bearer $IRONFANG_API_KEY" \
  -H 'Content-Type: application/xml' \
  --data-binary @peppol-bis-billing-3-invoice.xml

The response is JSON with the outcome, the ruleset, a status for each layer and every finding with its rule identifier. The Finance API guide covers scopes, limits and stored results, the rule reference explains findings one rule at a time, and generation from JSON builds documents like this one for you, validated before they are returned; the invoice JSON playground lets you try it without an account.