Overview
The /api/validate/json endpoint is essential for development. It validates your invoice JSON and ensures it can be converted to valid UBL BIS Billing 3.0 format before you create any documents.
You cannot create documents with invalid JSON. The API will reject invoices that don’t meet UBL BIS Billing 3.0 standards. Always validate during development to catch errors early.
Why Validate?
No document creation : Validation doesn’t create any records - it’s risk-free testing
Fast feedback : Get instant validation results without creating documents
Detailed errors : Receive specific field-level error messages
UBL compliance : Ensures your JSON converts to valid UBL BIS Billing 3.0 XML
Save API calls : Fix errors before attempting to create documents
Basic Validation
Use POST /api/validate/json with your invoice data:
curl -X POST "https://api.e-invoice.be/api/validate/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"document_type": "INVOICE",
"invoice_id": "INV-2024-001",
"invoice_date": "2024-10-24",
"due_date": "2024-11-23",
"currency": "EUR",
"vendor_name": "Your Company BVBA",
"vendor_tax_id": "BE0123456789",
"vendor_address": "Main Street 123, 1000 Brussels, Belgium",
"customer_name": "Customer Company NV",
"customer_tax_id": "BE0987654321",
"customer_address": "Customer Lane 456, 2000 Antwerp, Belgium",
"items": [
{
"description": "Professional Services - Consulting services for October 2024",
"quantity": "10",
"unit_price": "100.00",
"unit_code": "C62",
"tax_rate": "21.00"
}
]
}'
The example above will fail validation! This is intentional - it demonstrates why validation is critical. See below for the errors and how to fix them.
Response Types
Error Response (Real Example)
When validation fails, you’ll receive detailed UBL compliance errors. Here’s what the example above returns:
{
"id" : "b55354b0-5c69-489b-a8f7-44be7d5bdd6b" ,
"file_name" : "b55354b0-5c69-489b-a8f7-44be7d5bdd6b.xml" ,
"is_valid" : false ,
"issues" : [
{
"message" : "Belgian enterprise number MUST be stated in the correct format." ,
"type" : "error" ,
"rule_id" : "PEPPOL-COMMON-R043" ,
"flag" : "fatal"
},
{
"message" : "[BR-S-08]-For each different value of VAT category rate (BT-119) where the VAT category code (BT-118) is \" Standard rated \" , the VAT category taxable amount (BT-116) in a VAT breakdown (BG-23) shall equal the sum of Invoice line net amounts (BT-131)..." ,
"type" : "error" ,
"rule_id" : "BR-S-08" ,
"flag" : "fatal"
},
{
"message" : "Invoice line net amount MUST equal (Invoiced quantity * (Item net price/item price base quantity) + Sum of invoice line charge amount - sum of invoice line allowance amount" ,
"type" : "error" ,
"rule_id" : "PEPPOL-EN16931-R120" ,
"flag" : "fatal"
}
]
}
This is exactly why the validation endpoint exists! These UBL BIS Billing 3.0 compliance errors would prevent your invoice from being sent. Let’s fix them.
Fixed Example
Here’s a corrected version that passes validation:
curl -X POST "https://api.e-invoice.be/api/validate/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"document_type": "INVOICE",
"invoice_id": "INV-2024-001",
"invoice_date": "2024-10-24",
"due_date": "2024-11-23",
"currency": "EUR",
"vendor_name": "Your Company BVBA",
"vendor_tax_id": "BE0897290877",
"vendor_address": "Main Street 123, 1000 Brussels, Belgium",
"customer_name": "Customer Company NV",
"customer_tax_id": "BE0817331995",
"customer_address": "Customer Lane 456, 2000 Antwerp, Belgium",
"items": [
{
"description": "Professional Services - Consulting services for October 2024",
"quantity": "10",
"unit_price": "100.00",
"unit_code": "C62",
"tax_rate": "21.00",
"amount": "1000.00"
}
]
}'
What changed:
Valid Belgian VAT numbers with correct mod97 checksums:
BE0897290877 (vendor) instead of BE0123456789
BE0817331995 (customer) instead of BE0987654321
Added amount field to line items: "1000.00" (quantity × unit_price)
Success Response
When your JSON is valid, you’ll receive confirmation along with the generated UBL XML:
{
"id" : "9eec0b03-4649-4ae4-9c4c-323ebb6d53e8" ,
"file_name" : "9eec0b03-4649-4ae4-9c4c-323ebb6d53e8.xml" ,
"is_valid" : true ,
"issues" : [],
"ubl_document" : "<?xml version= \" 1.0 \" encoding= \" UTF-8 \" ?> \n <Invoice xmlns= \" urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 \" ..."
}
Response fields:
id: Validation session identifier
file_name: Generated XML filename
is_valid: true when validation passes
issues: Empty array when no errors
ubl_document: The generated UBL BIS Billing 3.0 XML (truncated above for readability)
Success means:
Your JSON is valid and UBL-compliant
You can see the exact UBL XML that will be generated
You’re ready to create the document using POST /api/documents/ with the same JSON payload
The ubl_document field shows you exactly what XML will be sent via Peppol. This is useful for debugging or understanding how your JSON maps to UBL BIS Billing 3.0.
Validating the UBL XML (Optional)
While the API always returns valid UBL when your JSON passes validation, you can optionally verify the generated UBL XML using the /api/validate/ubl endpoint.
This is completely optional - the JSON validation already ensures UBL compliance. Use this if you want to double-check the XML or validate externally-generated UBL files.
How to Validate UBL XML
Save the ubl_document from the validation response to a file, then validate it:
# First, save the UBL XML to a file (from the validation response above)
cat > invoice.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" ...>
<!-- Your UBL XML content -->
</Invoice>
EOF
# Then validate the UBL file
curl -X POST "https://api.e-invoice.be/api/validate/ubl" \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "[email protected] "
UBL Validation Response
Success (valid UBL):
{
"id" : "a1b2c3d4-5678-90ab-cdef-1234567890ab" ,
"file_name" : "invoice.xml" ,
"is_valid" : true ,
"issues" : []
}
Validation errors (if any):
{
"id" : "a1b2c3d4-5678-90ab-cdef-1234567890ab" ,
"file_name" : "invoice.xml" ,
"is_valid" : false ,
"issues" : [
{
"message" : "Invoice total amount mismatch" ,
"type" : "error" ,
"rule_id" : "BR-CO-15" ,
"flag" : "fatal"
}
]
}
When to Use UBL Validation
Use POST /api/validate/ubl when you:
Have existing UBL XML files to verify before sending
Want to double-check the generated XML from JSON validation
Are migrating from another system with pre-generated UBL documents
Need to validate UBL files from external sources
If you’re creating invoices from JSON, stick with /api/validate/json - it’s simpler and handles the UBL generation for you automatically.
Common Validation Errors
{
"field" : "vendor_tax_id" ,
"message" : "Invalid Peppol ID format. Expected: scheme:identifier"
}
Fix : Use the correct format scheme:identifier
Belgian companies: 0208:0123456789 (CBE number - VAT without ‘BE’ prefix)
See Peppol schemes
Invalid Tax Rate
{
"field" : "items[0].tax_rate" ,
"message" : "Invalid tax rate format. Must be a percentage string"
}
Fix : Use string format for tax rates:
Standard rate: "21.00"
Reduced rate: "6.00"
Zero rated: "0.00"
Missing Required Fields
{
"field" : "vendor_address" ,
"message" : "Field is required for UBL compliance"
}
Fix : Ensure all required fields are present:
Vendor/customer name, tax ID, and address
Invoice ID, invoice date, currency
At least one item with description, quantity, unit price, and tax rate
{
"field" : "invoice_date" ,
"message" : "Invalid date format. Use ISO 8601: YYYY-MM-DD"
}
Fix : Use the format YYYY-MM-DD, e.g., 2024-10-24
Invalid Currency Code
{
"field" : "currency" ,
"message" : "Unsupported currency code"
}
Fix : Use supported ISO 4217 codes: EUR, USD, GBP, JPY, CHF, CAD, AUD, NZD, CNY, INR, SEK, NOK, DKK, SGD, HKD
Development Workflow
1. Build Your Invoice JSON
Start with a template or build your invoice object:
const invoice = {
document_type: 'INVOICE' ,
invoice_id: 'INV-2024-001' ,
invoice_date: '2024-10-24' ,
currency: 'EUR' ,
// ... rest of invoice data
};
2. Validate First
Always validate before attempting to create:
const validation = await api . post ( '/api/validate/json' , invoice );
if ( ! validation . data . valid ) {
console . error ( 'Validation errors:' , validation . data . errors );
// Fix errors and try again
return ;
}
3. Create Document
Only after validation passes, create the document:
const document = await api . post ( '/api/documents/' , invoice );
Complete Development 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 validateAndCreateInvoice ( invoiceData ) {
try {
// Step 1: Validate the JSON
console . log ( 'Validating invoice JSON...' );
const validation = await api . post ( '/api/validate/json' , invoiceData );
if ( ! validation . data . valid ) {
console . error ( '❌ Validation failed:' );
validation . data . errors . forEach ( error => {
console . error ( ` - ${ error . field } : ${ error . message } ` );
});
return null ;
}
console . log ( '✓ Invoice JSON is valid' );
// Step 2: Create the document
console . log ( 'Creating invoice...' );
const document = await api . post ( '/api/documents/' , invoiceData );
console . log ( '✓ Invoice created:' , document . data . id );
return document . data ;
} catch ( error ) {
console . error ( 'Error:' , error . response ?. data || error . message );
return null ;
}
}
// Example usage - using valid data
const invoiceData = {
document_type: 'INVOICE' ,
invoice_id: 'INV-2024-001' ,
invoice_date: '2024-10-24' ,
due_date: '2024-11-23' ,
currency: 'EUR' ,
vendor_name: 'Your Company BVBA' ,
vendor_tax_id: 'BE0897290877' , // Valid Belgian VAT with mod97 checksum
vendor_address: 'Main Street 123, 1000 Brussels, Belgium' ,
customer_name: 'Customer Company NV' ,
customer_tax_id: 'BE0817331995' , // Valid Belgian VAT with mod97 checksum
customer_address: 'Customer Lane 456, 2000 Antwerp, Belgium' ,
items: [
{
description: 'Professional Services - Consulting services for October 2024' ,
quantity: '10' ,
unit_price: '100.00' ,
unit_code: 'C62' ,
tax_rate: '21.00' ,
amount: '1000.00' // Required: quantity × unit_price
}
]
};
validateAndCreateInvoice ( invoiceData );
Testing Strategy
During Development
Use /api/validate/json liberally:
Test edge cases : Validate unusual scenarios (zero amounts, multiple currencies, etc.)
Test all document types : Validate invoices, credit notes, and debit notes
Iterate quickly : Fix errors and re-validate without creating documents
Build test suites : Create automated validation tests
Before Production
Validate representative samples of all invoice types
Test with real customer Peppol IDs
Verify all tax categories and currency codes you’ll use
Test complex scenarios (allowances, charges, multiple line items)
Validating UBL XML
If you have existing UBL XML files, validate them with POST /api/validate/ubl:
curl -X POST "https://api.e-invoice.be/api/validate/ubl" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/xml" \
--data-binary @invoice.xml
This validates that your UBL file meets Peppol BIS Billing 3.0 requirements.
Best Practices
Don’t wait until production. Validate during development to catch issues early:
Test each new invoice template
Validate after schema changes
Include validation in CI/CD pipelines
Handle Validation Errors Gracefully
if ( ! validation . data . valid ) {
// Log detailed errors
logger . error ( 'Invoice validation failed' , {
invoice_id: invoiceData . invoice_id ,
errors: validation . data . errors
});
// Notify developers/users
notifyError ( validation . data . errors );
// Don't attempt to create the document
return ;
}
If you’re generating invoices from templates, validate the template once and cache the result: const templateCache = new Map ();
function validateTemplate ( templateName , templateData ) {
if ( templateCache . has ( templateName )) {
return templateCache . get ( templateName );
}
const isValid = validateInvoiceJSON ( templateData );
templateCache . set ( templateName , isValid );
return isValid ;
}
Test validation extensively in the staging environment before moving to production:
Staging: https://api-dev.e-invoice.be
Production: https://api.e-invoice.be
Next Steps