Overview
Before sending an e-invoice via Peppol, you need to know your customer’s Peppol ID (also called Peppol participant identifier). The e-invoice.be API provides lookup services to find registered Peppol participants and verify their identifiers.
What is a Peppol ID?
A Peppol ID is a unique identifier for organizations registered on the Peppol network. It consists of:
Scheme : The identifier scheme (e.g., 0208 for Belgian companies)
Identifier : The actual ID
Format: scheme:identifier → 0208:0123456789
Belgian Peppol IDs use the CBE number (Crossroads Bank for Enterprises number), which is equivalent to the Belgian VAT number without the ‘BE’ prefix . For example, if the VAT number is BE0123456789, the Peppol ID is 0208:0123456789 (numbers only).
Organizations must be registered with a Peppol Access Point to receive e-invoices. If a customer is not registered, they cannot receive invoices via Peppol.
Lookup by Peppol ID
Verify if a specific Peppol ID is registered and can receive invoices:
Using /api/validate/peppol-id
curl -X GET "https://api.e-invoice.be/api/validate/peppol-id?peppol_id=0208:0123456789" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
Registered and active:
{
"valid" : true ,
"peppol_id" : "0208:0123456789" ,
"registered" : true ,
"participant_name" : "Example Company NV" ,
"capabilities" : [
"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" ,
"urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2"
]
}
Not registered:
{
"valid" : false ,
"peppol_id" : "0208:0123456789" ,
"registered" : false ,
"message" : "Participant not found in Peppol network"
}
Invalid format:
{
"valid" : false ,
"peppol_id" : "0123456789" ,
"message" : "Invalid Peppol ID format. Expected: scheme:identifier (e.g., 0208:0123456789)"
}
Search for Participants
Search the Peppol network for participants by name or identifier:
Using /api/lookup/participants
curl -X GET "https://api.e-invoice.be/api/lookup/participants?query=Example%20Company" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"results" : [
{
"peppol_id" : "0208:0123456789" ,
"name" : "Example Company NV" ,
"country_code" : "BE" ,
"registered" : true
},
{
"peppol_id" : "0208:0987654321" ,
"name" : "Example Company International BVBA" ,
"country_code" : "BE" ,
"registered" : true
}
],
"total" : 2
}
Query Parameters
Parameter Description Example querySearch term (name or ID) Example Companycountry_codeFilter by country (ISO 3166-1 alpha-2) BElimitMax results (default: 20, max: 100) 50
General Lookup
Get detailed information about any Peppol participant:
Using /api/lookup
curl -X GET "https://api.e-invoice.be/api/lookup?peppol_id=0208:0123456789" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"peppol_id" : "0208:0123456789" ,
"participant_name" : "Example Company NV" ,
"country_code" : "BE" ,
"registered" : true ,
"access_point" : "e-invoice.be Access Point" ,
"capabilities" : [
"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" ,
"urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2"
],
"registration_date" : "2024-01-15T10:00:00Z"
}
Common Peppol ID Schemes
Different countries use different identifier schemes:
Country Scheme Code Identifier Type Format Example Belgium 0208CBE number (VAT without ‘BE’) 0208:0123456789Netherlands 0106KVK number 0106:12345678Germany 0204VAT number 0204:DE123456789France 0009SIRET 0009:12345678901234UK 0088GLN 0088:1234567890123Norway 0192Organization number 0192:123456789Sweden 0007Organization number 0007:1234567890Denmark 0184CVR number 0184:12345678International 0088Global Location Number 0088:1234567890123
Integration Examples
Node.js Example
const axios = require ( 'axios' );
const api = axios . create ({
baseURL: 'https://api.e-invoice.be' ,
headers: {
'Authorization' : `Bearer ${ process . env . E_INVOICE_API_KEY } ` ,
'Content-Type' : 'application/json'
}
});
async function lookupCustomer ( cbeNumber ) {
try {
// Construct Peppol ID (Belgian example)
// Note: For Belgium, use CBE number without 'BE' prefix
// If you have VAT number BE0123456789, use just 0123456789
const peppolId = `0208: ${ cbeNumber } ` ;
// Validate the Peppol ID
const response = await api . get ( '/api/validate/peppol-id' , {
params: { peppol_id: peppolId }
});
if ( response . data . valid && response . data . registered ) {
console . log ( '✓ Customer can receive e-invoices via Peppol' );
console . log ( ' Name:' , response . data . participant_name );
console . log ( ' Peppol ID:' , response . data . peppol_id );
return response . data ;
} else {
console . log ( '✗ Customer is not registered on Peppol network' );
console . log ( ' They cannot receive e-invoices electronically' );
return null ;
}
} catch ( error ) {
console . error ( 'Error looking up customer:' , error . response ?. data || error . message );
return null ;
}
}
// Example usage
lookupCustomer ( '0123456789' ); // CBE number without 'BE' prefix
Search Example
async function searchCustomerByName ( companyName ) {
try {
const response = await api . get ( '/api/lookup/participants' , {
params: {
query: companyName ,
country_code: 'BE' ,
limit: 10
}
});
if ( response . data . results . length === 0 ) {
console . log ( 'No Peppol participants found for:' , companyName );
return [];
}
console . log ( `Found ${ response . data . total } participant(s):` );
response . data . results . forEach ( participant => {
console . log ( ` - ${ participant . name } ( ${ participant . peppol_id } )` );
});
return response . data . results ;
} catch ( error ) {
console . error ( 'Error searching:' , error . response ?. data || error . message );
return [];
}
}
// Example usage
searchCustomerByName ( 'Example Company' );
Pre-Flight Check Workflow
Before creating an invoice, validate the recipient:
async function createInvoiceWithValidation ( invoiceData ) {
try {
// 1. Validate recipient is on Peppol network
const customerPeppolId = invoiceData . customer . party_legal_entity . company_id ;
console . log ( 'Checking if customer can receive e-invoices...' );
const validation = await api . get ( '/api/validate/peppol-id' , {
params: { peppol_id: customerPeppolId }
});
if ( ! validation . data . valid || ! validation . data . registered ) {
console . error ( '❌ Customer cannot receive e-invoices via Peppol' );
console . error ( ' Peppol ID:' , customerPeppolId );
console . error ( ' Please use alternative delivery method (email, PDF)' );
return null ;
}
console . log ( '✓ Customer can receive e-invoices' );
// 2. Validate invoice JSON
console . log ( 'Validating invoice JSON...' );
const jsonValidation = await api . post ( '/api/validate/json' , invoiceData );
if ( ! jsonValidation . data . valid ) {
console . error ( '❌ Invoice validation failed' );
jsonValidation . data . errors . forEach ( error => {
console . error ( ` - ${ error . field } : ${ error . message } ` );
});
return null ;
}
console . log ( '✓ Invoice JSON is valid' );
// 3. Create the invoice
console . log ( 'Creating invoice...' );
const document = await api . post ( '/api/documents/' , invoiceData );
console . log ( '✓ Invoice created:' , document . data . id );
// 4. Send via Peppol
console . log ( 'Sending via Peppol...' );
const result = await api . post ( `/api/documents/ ${ document . data . id } /send` );
console . log ( '✓ Invoice sent:' , result . data . state );
return document . data ;
} catch ( error ) {
console . error ( 'Error:' , error . response ?. data || error . message );
return null ;
}
}
Handling Unregistered Customers
If a customer is not on the Peppol network:
Inform them : Let them know about Peppol e-invoicing benefits
Alternative delivery : Send PDF invoices via email
Register with e-invoice.be : Customers can sign up at e-invoice.be
Example: Fallback Logic
async function sendInvoiceToCustomer ( invoiceData ) {
const peppolId = invoiceData . customer . party_legal_entity . company_id ;
// Check if customer is on Peppol
const validation = await api . get ( '/api/validate/peppol-id' , {
params: { peppol_id: peppolId }
});
if ( validation . data . valid && validation . data . registered ) {
// Send via Peppol
return await sendViaPeppol ( invoiceData );
} else {
// Fallback to email with PDF
console . log ( 'Customer not on Peppol, sending PDF via email' );
return await sendPdfViaEmail ( invoiceData );
}
}
Best Practices
Always check if a recipient can receive e-invoices before creating documents: // ✓ Good: Check first
const isValid = await validatePeppolId ( customerId );
if ( isValid ) {
await createAndSendInvoice ( data );
}
// ✗ Bad: Create first, fail later
await createAndSendInvoice ( data ); // May fail
Cache participant lookups to reduce API calls: const participantCache = new Map ();
const CACHE_TTL = 24 * 60 * 60 * 1000 ; // 24 hours
async function lookupWithCache ( peppolId ) {
const cached = participantCache . get ( peppolId );
if ( cached && Date . now () - cached . timestamp < CACHE_TTL ) {
return cached . data ;
}
const data = await lookupParticipant ( peppolId );
participantCache . set ( peppolId , {
data ,
timestamp: Date . now ()
});
return data ;
}
Different countries use different schemes. Build a mapping: const PEPPOL_SCHEMES = {
'BE' : '0208' , // Belgian CBE (numbers only, no 'BE' prefix)
'NL' : '0106' , // Dutch KVK
'DE' : '0204' , // German VAT
'FR' : '0009' , // French SIRET
'UK' : '0088' , // UK GLN
};
function buildPeppolId ( countryCode , identifier ) {
const scheme = PEPPOL_SCHEMES [ countryCode ];
if ( ! scheme ) {
throw new Error ( `Unknown country: ${ countryCode } ` );
}
return ` ${ scheme } : ${ identifier } ` ;
}
When a customer isn’t found, guide them: if ( ! validation . data . registered ) {
console . log ( `
Customer is not registered on the Peppol network.
To receive e-invoices, they need to:
1. Sign up at https://app.e-invoice.be
2. Complete registration with their Peppol ID
3. Configure their account to receive invoices
Alternative: Send a PDF invoice via email instead.
` );
}
Next Steps