Skip to content

PEPPOL-EN16931-R051: Use the invoice currency code in every amount currencyID

An amount has a currencyID other than cbc:DocumentCurrencyCode. All amounts must be in the invoice currency, bar the VAT total in an accounting currency.

Peppol BIS BillingFatal: the document is invalidCore fields

The short answer

PEPPOL-EN16931-R051 fails for each amount whose currencyID is not exactly the value of cbc:DocumentCurrencyCode. The finding location is the amount; change its currencyID to the invoice currency, and make sure the figure really is in that currency.

There is one exception. When cbc:TaxCurrencyCode names a VAT accounting currency, the VAT total in that currency goes in a second cac:TaxTotal with no breakdown, and that amount keeps its own currency.

What the rule checks

The rule visits every amount element of the kinds used in an invoice, including cbc:PriceAmount and the amounts of allowances and charges at every level, and compares its currencyID with the text of cbc:DocumentCurrencyCode under the root. The comparison is exact, so case and spaces matter.

The cbc:TaxAmount of a cac:TaxTotal that has no cac:TaxSubtotal is skipped; that is where the accounting-currency VAT total belongs. When tried, a GBP invoice with a cbc:TaxCurrencyCode of EUR and a second tax total of 13.46 EUR validated cleanly.

The exception follows the shape of the tax total, not the declared currency. When tried, a second tax total in EUR that repeated the VAT breakdown was reported by this rule on all three of its amounts, together with PEPPOL-EN16931-R053 and several VAT breakdown rules.

When cbc:DocumentCurrencyCode is missing or empty there is nothing to match, and every amount in the document is reported. The missing code itself is BR-05.

A code that is not on the ISO 4217 list fails this rule too, since it cannot equal a valid document currency; the code list rules BR-CL-03 and PEPPOL-EN16931-CL007 then appear with it.

TermMeaningUBL element
BT-5Invoice currency codecbc:DocumentCurrencyCode
-Currency of an amount (the currencyID attribute)currencyID on each amount element, for example cac:InvoiceLine/cac:Price/cbc:PriceAmount/@currencyID
BT-6VAT accounting currency codecbc:TaxCurrencyCode
BT-111Invoice total VAT amount in accounting currency (exempt)cac:TaxTotal/cbc:TaxAmount, in the cac:TaxTotal that has no cac:TaxSubtotal

How an integration ends up here

Possible causes, from the shape of the rule rather than from measured usage:

  • Prices come from a price list in a different currency from the invoice, and the price element takes the list currency while the totals use the invoice currency.
  • The invoice is converted for the buyer, and some amounts are converted and relabelled while others are not.
  • The document currency is set per customer on the header, while the currencyID attributes are hard-coded in the template.
  • VAT in a local currency is sent as a full copy of the breakdown instead of a single accounting-currency amount.

How to fix it

  1. Decide the invoice currency and write it to cbc:DocumentCurrencyCode.
  2. Express every amount in that currency. If a price comes from a list in another currency, convert it before the line is built; changing only the attribute would leave the wrong figure.
  3. Fill every currencyID from the document currency in one place in your mapping.
  4. If VAT must also be stated in a local accounting currency, add cbc:TaxCurrencyCode and a second cac:TaxTotal holding only a cbc:TaxAmount in that currency, with no cac:TaxSubtotal.

Validate your corrected invoice

Before and after

These are fragments, not complete documents. The complete synthetic documents they come from are linked below.

Fragment of the failing invoice: a GBP invoice with its item price in EUR

<cbc:DocumentCurrencyCode>GBP</cbc:DocumentCurrencyCode>
<!-- parties, tax total and monetary totals omitted from this fragment -->

<cac:InvoiceLine>
  <cbc:ID>1</cbc:ID>
  <cbc:InvoicedQuantity unitCode="C62">2</cbc:InvoicedQuantity>
  <cbc:LineExtensionAmount currencyID="GBP">25.00</cbc:LineExtensionAmount>
  <!-- item omitted from this fragment -->
  <cac:Price>
    <cbc:PriceAmount currencyID="EUR">12.5</cbc:PriceAmount>
    <cbc:BaseQuantity unitCode="C62">1</cbc:BaseQuantity>
  </cac:Price>
</cac:InvoiceLine>

Fragment of the corrected invoice: the item price is in GBP, the invoice currency

<cac:Price>
  <cbc:PriceAmount currencyID="GBP">12.5</cbc:PriceAmount>
  <cbc:BaseQuantity unitCode="C62">1</cbc:BaseQuantity>
</cac:Price>

The only difference is the currencyID on the item price: EUR in the failing invoice and GBP in the corrected one, on an invoice whose currency code is GBP. EUR is a valid ISO 4217 code, so the code list rules stay quiet and the EN 16931 layer passes, leaving this Peppol rule as the only finding. In the recorded example a relabel is the right fix because the price of 12.5 was always meant in pounds. A price that really was in euros would need converting as well.

What the validator reported

Recorded on phive 12.1.0 / phive-rules-peppol 4.5.6 / Saxon-HE 12.10, the engine behind the free validator, using synthetic data. A recorded result is regression evidence for these documents; it is not a certification.

Where it applies

  • Applies to UBL Invoice and CreditNote alike. When tried, a credit note with an EUR price on a GBP document reported this rule alone.
  • It is reported by the Peppol layer. In the recorded example the EN 16931 layer passes, because none of its rules compares the currency of an item price with the document currency.
  • A wrong currency on the VAT total with the breakdown matters to EN 16931 too. When tried, EUR there also brought BR-CO-15, which then finds no VAT total in the document currency.
  • A second tax total in another currency, sent without cbc:TaxCurrencyCode, is not reported here: when tried, PEPPOL-EN16931-R054 reported it instead.

Scope and source

Written for Peppol BIS Billing 3.0.21 (May 2026), EN 16931 1.3.16, as applied to UBL 2.1 Invoice and CreditNote documents. Other profiles, syntaxes and releases can define this identifier differently. Guidance version 2026-09-24.1: source checked 2026-09-24, explanation last updated 2026-09-24.

The official definition of PEPPOL-EN16931-R051 carries the normative wording and test. This page is our explanation of it, not a copy.

Guidance does not change the engine verdict. Fixing this finding does not mean the document passes every layer, and validation does not certify legal or tax compliance or transmit a document over Peppol.