On this page
The short answer
PEPPOL-EN16931-CL007 fails when the currencyID of an amount is not exactly one of the codes on the Peppol currency list. Nothing is trimmed or upper-cased before the comparison, so the attribute must hold the bare three-letter code, such as GBP, and nothing else.
In the recorded example the amount due for payment is labelled GBP followed by a space. EN 16931 trims the value before its own check, BR-CL-03, and accepts it. Peppol does not, and PEPPOL-EN16931-R051 reports the attribute as well, because it no longer equals the document currency.
What the rule checks
The rule reads the same thirteen amount elements as BR-CL-03: cbc:Amount, cbc:BaseAmount, cbc:PriceAmount, cbc:TaxAmount, cbc:TaxableAmount, cbc:LineExtensionAmount and the totals in cac:LegalMonetaryTotal. Each amount with a bad attribute is a finding of its own.
Which rule a value trips depends on how it is wrong. A value on neither list, such as UKP or gbp, is reported by this rule and by BR-CL-03, and by PEPPOL-EN16931-R051 too when it differs from the document currency code. A valid code with a space before or after it passes BR-CL-03 and fails only on the Peppol layer: when tried, a leading space and a trailing space were each reported by this rule and PEPPOL-EN16931-R051.
The two lists differ by one currency. The Peppol list has STN, the current code for the Sao Tome and Principe dobra, and lacks the withdrawn STD; the EN 16931 list has it the other way round. When tried, an invoice entirely in STD passed EN 16931 and drew this rule on every amount, while one entirely in STN passed the Peppol layer and failed BR-CL-03 and BR-CL-04.
The VAT total in the VAT accounting currency is covered, although PEPPOL-EN16931-R051 leaves it out. When tried with EUR as the accounting currency, EUR followed by a space on that total was reported by this rule and by BR-53 and PEPPOL-EN16931-R055, which find that total by its currency code.
| Term | Meaning | UBL element |
|---|---|---|
| - | Currency of an amount (the currencyID attribute) | currencyID on each amount element, for example cac:LegalMonetaryTotal/cbc:PayableAmount/@currencyID |
| BT-5 | Invoice currency code | cbc:DocumentCurrencyCode |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- The currency comes from a fixed-width field or a
CHARdatabase column and keeps its padding. - A template writes the attribute as
currencyID="{currency} ", or joins strings with a separator, leaving a space in the value. - Codes are taken from an old reference table that still lists withdrawn currencies such as
STD. - Each amount is filled from its own source, and only one of them, such as the payment total, carries the untrimmed value.
How to fix it
- Use the finding location to find the amount, and the place in your mapping that fills its
currencyID. - Trim the currency code once, where it enters your system, and fill every
currencyIDandcbc:DocumentCurrencyCodefrom that one value. - Check the code against the current ISO 4217 list. A code valid on both layers, such as
GBPorEUR, clears this rule andBR-CL-03together. - For the Sao Tome and Principe dobra there is no code both layers accept in the pinned release:
STNfails EN 16931 andSTDfails Peppol, so an invoice in that currency cannot pass until the lists agree.
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: the amount due is labelled GBP with a trailing space
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="GBP">25.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="GBP">25.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="GBP">30.00</cbc:TaxInclusiveAmount>
<!-- allowance, charge, prepaid and rounding totals omitted from this fragment -->
<cbc:PayableAmount currencyID="GBP ">30.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>Fragment of the corrected invoice: every amount carries the bare code GBP
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="GBP">25.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="GBP">25.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="GBP">30.00</cbc:TaxInclusiveAmount>
<!-- allowance, charge, prepaid and rounding totals omitted from this fragment -->
<cbc:PayableAmount currencyID="GBP">30.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>Only the currencyID of cbc:PayableAmount differs: GBP with a trailing space in the failing invoice, plain GBP in the corrected one. Two Peppol findings share that location: this rule, because the padded value is not on the list, and PEPPOL-EN16931-R051, because it does not equal the document currency. The EN 16931 layer passes, since BR-CL-03 trims the value first.
What the validator reported
- The failing invoice reports PEPPOL-EN16931-CL007 and PEPPOL-EN16931-R051. The corrected document passes every layer with no findings.Download the failing XMLDownload the corrected XML
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
InvoiceandCreditNote. When tried, a credit note with the same padded amount due reported the same two rules. - Reported on the Peppol layer. Apart from
STD,STNand white space around a code, this rule andBR-CL-03accept and reject the same values in the pinned release. - It never reads
cbc:DocumentCurrencyCodeorcbc:TaxCurrencyCode;BR-CL-04andBR-CL-05check those. When tried withSTDas the VAT accounting currency,BR-CL-05accepted the code element and this rule reported only the VAT total that carriedSTD.
Related rules
- BR-CL-03 checks the same attributes on the EN 16931 layer, after trimming them
- PEPPOL-EN16931-R051 reports an amount whose currencyID differs from the document currency code
- PEPPOL-EN16931-CL006 is the Peppol code list check for the VAT point date code
- PEPPOL-EN16931-P0112 is another Peppol check that refuses a code the EN 16931 layer accepts, there the invoice type code
- Browse every rule in the reference
- Background: How Peppol invoice validation actually works
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-28.1: source checked 2026-09-28, explanation last updated 2026-09-28.
The official definition of PEPPOL-EN16931-CL007 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.

