Finding and storing your customers' Peppol IDs in Stripe
By evoicely · Last checked 20 October 2026
A Peppol participant ID is a scheme code plus an identifier, such as 0208:0765432146: scheme 0208 (the Belgian enterprise number) and the number itself.
For a Belgian company you rarely have to ask for it. The enterprise number is the company's VAT number without the BE, and Belgian Peppol providers must register their customers under it.
For anyone else you look the ID up in the Peppol Directory or with an SMP lookup, or you ask the customer.
Stripe has no field for it: keep the VAT number in the Customer's tax_ids and anything else in Customer metadata.
This page covers the format, the lookups, Belgium, Stripe, and the mistakes the official Peppol rules catch.
What a Peppol participant ID is
Every sender and receiver on Peppol is addressed by a participant identifier. It has two parts: an identifier scheme from the Peppol Electronic Address Scheme (EAS) code list, and the value that scheme issues (Peppol Policy for use of Identifiers 4.4.0, policies 3 and 4). You'll see it written three ways:
0208:0765432146: scheme and value, the form most access points and their APIs take.iso6523-actorid-upis::0208:0765432146: the full form, with Peppol's fixed "meta scheme" in front. The Peppol Directory's API and SMP lookups use it (policy 5).<cbc:EndpointID schemeID="0208">0765432146</cbc:EndpointID>: in the invoice itself, as the seller's (BT-34) and buyer's (BT-49) electronic address. The Peppol BIS rules require both (PEPPOL-EN16931-R020 and R010).
The value is case-insensitive (policy 2: 0088:abc is the same participant as 0088:ABc), but the scheme is not interchangeable: the same digits under another scheme are a different participant.
A company can be registered under more than one ID, for example its enterprise number and its VAT number.
Common schemes
The EAS list has well over a hundred entries. These are the ones a Stripe seller in Belgium or the Netherlands is most likely to meet. The names are from the Peppol EAS code list, the format checks from the Peppol BIS Billing 3.0 rules:
| Scheme | Identifier | Format the Peppol rules check |
|---|---|---|
0208 | Belgian enterprise number (KBO/BCE, "ondernemingsnummer") | 10 digits, no dots, no BE; the last two are a mod-97 check of the first eight (PEPPOL-COMMON-R043) |
9925 | Belgian VAT number | No format rule of its own in Peppol BIS |
0088 | Global Location Number (GLN) | A valid GS1 GLN (PEPPOL-COMMON-R040) |
0106 | Dutch Chamber of Commerce (KVK) number | 8 digits (PEPPOL-COMMON-R054, a warning) |
0190 | Dutch organisation identification number (OIN) | 20 digits (PEPPOL-COMMON-R055, a warning) |
9944 | Dutch VAT number | Like NL123456789B12 (PEPPOL-COMMON-R056-1, a warning) |
A scheme that isn't on the list fails rule PEPPOL-EN16931-CL008, and email (EM) isn't on it, so an email address can't be a Peppol endpoint.
Belgian customers: the ID is in the VAT number
Since 1 January 2026, Belgian enterprises liable to VAT have to exchange structured e-invoices with each other, sent over Peppol (einvoice.belgium.be, FPS Finance). Belgium's Peppol mandate for Stripe users covers who is in scope. Finding the buyer's ID is the easy part:
- Every Belgian business has a 10-digit enterprise number from the Crossroads Bank for Enterprises (KBO/BCE), and its VAT number is that same number preceded by
BE(business.belgium.be). SoBE0765.432.146gives the enterprise number0765432146. - Belgian Peppol registrations use it. FPS Finance says at least one registration of a Belgian company must be under its enterprise number (scheme
0208), that service providers are contractually obliged to do this, and that this avoids having to ask all your customers for their Peppol ID. You can always send to the enterprise number; other IDs (VAT number, GLN, DUNS and so on) are used only where both parties agree (FPS Finance: What is a Peppol ID?). - So don't ask. To "Should I ask my customers for their Peppol ID?" FPS Finance answers: "No, you should not." (B2B FAQ, question 15).
Getting it right
Most failed Belgian endpoints are formatting mistakes. We ran these through the Peppol BIS Billing 3.0 rules that our free validator uses, on an otherwise valid invoice:
Buyer cbc:EndpointID | Result |
|---|---|
schemeID="0208" 1111111145 | Valid |
schemeID="0208" 0111.111.124 | PEPPOL-COMMON-R043: the dots are part of how the number is written, not of the identifier |
schemeID="0208" BE1111111145 | PEPPOL-COMMON-R043: BE belongs to the VAT number, not the enterprise number |
schemeID="0208" 1111111146 | PEPPOL-COMMON-R043: check digits don't match |
schemeID="9925" BE1111111145 | Valid, but only reaches the buyer if they registered that ID too |
schemeID="BE:EN" 1111111145 | BR-CL-25 and PEPPOL-EN16931-CL008: not a scheme on the EAS list |
The enterprise numbers here are fictional; they only pass the check. The check itself is simple: the last two digits must equal 97 minus the first eight digits modulo 97, which is how the Peppol rule computes it.
Older documents write enterprise numbers with 9 digits (no leading 0); pad them to 10 before you use them. Don't use Stripe's format example BE0123456789 as test data for Peppol: its check digits don't add up.
In code, deriving the ID from a Belgian VAT number takes a few lines:
import re
def be_peppol_id(vat: str) -> str | None:
"""'BE 0765.432.146' -> '0208:0765432146', or None if it isn't a valid Belgian number."""
digits = re.sub(r"[\s.\-]", "", vat.upper()).removeprefix("BE")
if len(digits) == 9: # old 9-digit form
digits = "0" + digits
if not re.fullmatch(r"\d{10}", digits) or 97 - int(digits[:8]) % 97 != int(digits[8:]):
return None
return "0208:" + digits
A valid number doesn't mean the company is on Peppol yet. Check that before you send, as below.
How to look up a Peppol ID
The Peppol Directory
The Peppol Directory is OpenPeppol's search over the business cards that Peppol SMPs publish. You can search by name or ID, filter by country, or query it from code. Two limits matter (Peppol Directory: introduction):
- Listing is voluntary. A company that isn't in the Directory may still be on Peppol. A company that is listed is a Peppol participant.
- Only receivers are listed. The Directory shows who can receive documents, which is what you need to send them an invoice.
The REST API takes the full identifier, encoded, and allows at most 2 queries per second (REST API documentation):
curl "https://directory.peppol.eu/search/1.0/json?participant=iso6523-actorid-upis%3A%3A0208%3A0765432146"
An empty result list comes back with status 200, so check the number of matches rather than the status code. For finding an ID by company name, use the name parameter or the website's free-text search, then confirm the country and address before you store anything.
SML and SMP: the authoritative check
The Directory is for people. When an access point sends a document, it looks the recipient up in the Service Metadata Locator (SML), a DNS-based register, which points to the recipient's Service Metadata Publisher (SMP). The SMP says which document types the participant can receive and at which access point (Policy for use of Identifiers, section 2.1.2). So "is this customer on Peppol?" really means "does the SML know this ID, and does its SMP accept Peppol BIS invoices?". Unlike the Directory, this covers every registered receiver.
- By hand: OpenPeppol's SMP and business card lookup. FPS Finance points Belgian users to it: search for
0208:followed by the enterprise number. It shows who can receive, not who can send. - From code: most access-point APIs offer a "verify recipient" or "lookup" call that does the SML/SMP lookup for you. Call it right before sending, not once when you store the ID: registrations change.
Asking the customer
Outside Belgium there's often no rule that tells you which ID a company is registered under: a Dutch company could be on Peppol with its KVK number (0106), its VAT number (9944), or not at all.
If the Directory doesn't list them, ask their accounts-payable team for the full ID including the scheme, and look it up before the first invoice. In Belgium, ask only if the customer wants invoices at an ID other than their enterprise number.
Where to keep it in Stripe
Stripe has no Peppol ID field. Its e-invoicing docs say to put the customer's VAT number in tax_ids on the Customer, and Peppol participant IDs in Customer metadata under a consistent key, for example peppol_participant_id
(Stripe: e-invoicing).
Tax IDs for the VAT number
A Belgian or Dutch VAT number is a tax ID of type eu_vat. Stripe validates EU VAT numbers against VIES and reports the result as verification.status (pending, verified, unverified or unavailable), but it only checks that the number is valid, not that the name and address match
(Stripe: customer tax IDs).
curl https://api.stripe.com/v1/tax_ids \
-u "$STRIPE_SECRET_KEY:" \
-d type=eu_vat \
-d value=BE0765432146 \
-d "owner[type]=customer" \
-d "owner[customer]=cus_123"
Each invoice carries a copy in customer_tax_ids. It follows the Customer until the invoice is finalized and is frozen after that (Invoice object), so add the VAT number before the first invoice is finalized.
For a Belgian customer, that's all you need: the 0208 ID can be derived from it every time. Stripe has no tax ID type for a KVK number or a GLN, so those go in metadata.
Metadata for anything else
Store the ID on the Customer as one value in scheme:identifier form, so the scheme can't get separated from the number:
curl https://api.stripe.com/v1/customers/cus_123 \
-u "$STRIPE_SECRET_KEY:" \
-d "metadata[peppol_participant_id]=0106:12345678"
Normalise it when you save it: no spaces or dots, no iso6523-actorid-upis:: prefix, and look it up once so typos don't reach your first invoice.
Customer metadata isn't copied onto invoices; whatever converts an invoice has to fetch the Customer (or expand customer) to read it.
What ends up in the XML
A fictional Belgian seller invoices a fictional Belgian company. Both have Belgian VAT numbers, and both endpoints are scheme 0208 with the enterprise number derived from the VAT number.
evoicely's Peppol writer produced this file, and it passes the EN 16931 and Peppol BIS Billing 3.0 rules. Excerpt, the comments added afterwards:
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="0208">1000000120</cbc:EndpointID> <!-- BT-34 -->
...
<cac:PartyTaxScheme>
<cbc:CompanyID>BE1000000120</cbc:CompanyID> <!-- BT-31 -->
...
<cac:AccountingCustomerParty>
<cac:Party>
<cbc:EndpointID schemeID="0208">1111111145</cbc:EndpointID> <!-- BT-49 -->
...
<cac:PartyTaxScheme>
<cbc:CompanyID>BE1111111145</cbc:CompanyID> <!-- BT-48 -->
...
The VAT number keeps its BE prefix; the 0208 endpoint drops it. Our free validator shows each party's electronic address with its scheme, so you can check which ID an invoice is addressed to.
What evoicely does today
evoicely sends Peppol invoices for Belgian sellers who switch Peppol delivery on. It doesn't ask you for your customers' Peppol IDs:
- The buyer's ID is derived from the first
eu_vattax ID on the Stripe invoice, when the customer's billing address is in Belgium:0208plus the enterprise number, with the mod-97 check above (a 9-digit number is padded to 10). Dots and spaces in the VAT number are fine. - Before sending, evoicely asks its access point, Recommand, whether that ID is registered on Peppol. If it isn't, the document is emailed instead, if you've switched on email delivery; otherwise it's marked as not sent, with the reason.
- Your own ID is
0208plus the enterprise number from the Belgian VAT number in your settings. - Not read today: a Peppol ID in metadata (including
peppol_participant_id), and any scheme other than0208. Customers outside Belgium, or Belgian customers without a VAT number in Stripe, get only the XRechnung and ZUGFeRD files, with their email address as the electronic address. - Test mode documents go through Recommand's test environment, where sending is simulated and nothing reaches the buyer.
Checklist
- Put every business customer's VAT number in Stripe
tax_idsaseu_vatbefore their first invoice is finalized, and check that it verifies. - Belgian customers: derive
0208:plus the 10-digit enterprise number from the VAT number. No need to ask them. - Other customers: find the ID in the Peppol Directory or ask for it with its scheme, then store it in Customer metadata as
scheme:identifier. - Right before each send, let your access point confirm the ID is registered for Peppol BIS invoices. Have a fallback for customers who aren't.
- Validate the file. Our free validator runs the official Peppol rules, including the check digits of 0208 numbers.
Related guides
- Belgium's Peppol mandate for Stripe users: who has to send Peppol invoices since 2026.
- Common Peppol BIS validation errors: PEPPOL-COMMON-R043 and the rest.
Where evoicely fits
evoicely sends your Stripe invoices and credit notes over Peppol, addressing Belgian customers by the enterprise number in their VAT ID and checking they're on Peppol first. Each document is checked against the official Peppol rules before it goes out. Connect your Stripe account, free for 10 e-invoices a month.
This is general information, not legal or tax advice. Check what applies to your business with your tax advisor.