ubl-peppol

Belgium Implementation (EN 16931)

This guide covers the specific requirements for generating UBL invoices that comply with the Belgian EN 16931 standard.

Belgian Specifications

PEPPOL BIS Billing 3.0 + EN 16931

Belgium uses the standard PEPPOL BIS Billing 3.0 with additional national requirements according to EN 16931.

Important Belgian Rules

ubl-BE-01: Second AdditionalDocumentReference

// Required: PEPPOL reference
$ubl->addAdditionalDocumentReference('PEPPOL', 'PEPPOLInvoice');

ubl-BE-10: Tax Category Names

Use correct BTCC values:

// Standard rate (21%)
'tax_category_name' => 'Taux standard'

// Zero rate (0%)
'tax_category_name' => 'Taux zéro'

ubl-BE-14: TaxTotal in InvoiceLine

For Belgian compliance, TaxTotal is omitted at InvoiceLine level.

Complete Belgian Invoice

use Darvis\UblPeppol\UblBeBis3Service;

$ubl = new UblBeBis3Service();
$ubl->createDocument();

// 1. Invoice header
$ubl->addInvoiceHeader('BE-INV-2024-001', '2024-01-15', '2024-02-14');

// 2. Required references
$ubl->addBuyerReference('CLIENT-001');
$ubl->addOrderReference('ORDER-2024-001');

// 3. PEPPOL reference (ubl-BE-01)
$ubl->addAdditionalDocumentReference('PEPPOL', 'PEPPOLInvoice');

// 4. Supplier (Belgian company)
$ubl->addAccountingSupplierParty(
    '0123456789',             // VAT number WITHOUT "BE" prefix as endpoint
    '0208',                   // Belgian VAT scheme (0208)
    'BE0123456789',           // Party ID
    'My Belgian Company BV',
    'Grote Markt 1',
    '1000',
    'Brussel',
    'BE',
    'BE0123456789'            // VAT number (with prefix)
);

// 5. Customer
$ubl->addAccountingCustomerParty(
    '0987654321',             // VAT number WITHOUT "BE" prefix as endpoint
    '0208',                   // Belgian VAT scheme (0208)
    'BE0987654321',           // Party ID
    'Customer Company NV',
    'Kerkstraat 123',
    '2000',
    'Antwerpen',
    'BE'
);

// 6. Invoice lines
$ubl->addInvoiceLine([
    'id' => '1',
    'quantity' => 2,
    'unit_code' => 'C62',
    'price_amount' => 100.00,
    'line_extension_amount' => 200.00, // Optional; defaults to quantity * price when omitted
    'currency' => 'EUR',
    'name' => 'Consultancy services',
    'description' => 'IT consultancy - 2 days',
    'tax_category_id' => 'S',
    'tax_percent' => 21.0,
    'tax_scheme_id' => 'VAT'
]);

// 7. Taxes (ubl-BE-10 compliance)
$ubl->addTaxTotal([
    [
        'taxable_amount' => '200.00',
        'tax_amount' => '42.00',
        'currency' => 'EUR',
        'tax_category_id' => 'S',
        'tax_category_name' => 'Taux standard', // Belgian BTCC value
        'tax_percent' => 21.0,
        'tax_scheme_id' => 'VAT'
    ]
]);

// 8. Totals
$ubl->addLegalMonetaryTotal([
    'line_extension_amount' => 200.00,
    'tax_exclusive_amount' => 200.00,
    'tax_inclusive_amount' => 242.00,
    'charge_total_amount' => 0.00,
    'payable_amount' => 242.00
], 'EUR');

// 9. Payment information
$ubl->addPaymentMeans(
    '30',                     // Credit transfer
    'Credit transfer',
    'BE-PAY-2024-001',
    'BE12 3456 7890 1234',   // Belgian IBAN
    'My Belgian Company BV',
    'BBRUBEBB',              // BIC code
    null,                    // Channel code not used in Belgium
    null                     // Due date handled at invoice level
);

$ubl->addPaymentTerms('Payment within 30 days', null, null, null);

// 10. Generate XML
$xml = $ubl->generateXml();

Belgian VAT Rates

Rate Percentage Tax Category ID BTCC Name
Standard 21% S Taux standard
Reduced 6% S Taux réduit
Zero 0% Z Taux zéro
Exempt 0% E Exonéré

Belgian VAT Numbers

Format: BE0123456789 (BE + 10 digits)

// Validation
if (!preg_match('/^BE[0-9]{10}$/', $vatNumber)) {
    throw new InvalidArgumentException('Invalid Belgian VAT number');
}

Belgian EndpointID

Important: For Belgium, the EndpointID should be the VAT number WITHOUT the “BE” prefix, not the KBO number.

Format: 10 digits (VAT number without country code)

// Example VAT number: BE0999000228
// EndpointID should be: 0999000228 (without "BE")
// Scheme ID: 0208 (Belgian VAT)

// Extract EndpointID from VAT number
$vatNumber = 'BE0999000228';
$endpointId = preg_replace('/^BE/i', '', $vatNumber); // Result: 0999000228
$endpointId = preg_replace('/[^0-9]/', '', $endpointId); // Remove non-numeric

// Validation
if (strlen($endpointId) !== 10 || !ctype_digit($endpointId)) {
    throw new InvalidArgumentException('Invalid Belgian VAT number for EndpointID');
}

KBO Number Validation (for reference)

KBO numbers use mod97 checksum validation. The last 2 digits are: 97 - (first 8 digits mod 97)

// Example: 0681845662
// Basis: 06818456
// Checksum: 97 - (6818456 % 97) = 97 - 35 = 62 ✓

function isValidKboNumber(string $kbo): bool {
    if (strlen($kbo) !== 10 || !ctype_digit($kbo)) {
        return false;
    }
    $basis = (int) substr($kbo, 0, 8);
    $checksum = (int) substr($kbo, 8, 2);
    return $checksum === (97 - ($basis % 97));
}

AllowanceCharge for Minimum Order Surcharges

For minimum order amounts, use AllowanceCharge instead of invoice lines:

// Minimum order surcharge as AllowanceCharge
$ubl->addAllowanceCharge(
    true,                           // isCharge (true = surcharge)
    74.63,                          // amount
    'Minimum order surcharge',      // reason
    'S',                            // taxCategoryId
    21.0,                           // taxPercent
    'EUR'                           // currency
);

// Totals must reflect the charge
$ubl->addLegalMonetaryTotal([
    'line_extension_amount' => 0.37,    // Sum of invoice lines only
    'tax_exclusive_amount' => 75.00,    // Lines + charges
    'tax_inclusive_amount' => 90.75,
    'charge_total_amount' => 74.63,     // Sum of charges
    'payable_amount' => 90.75
], 'EUR');

Formula: TaxExclusiveAmount = LineExtensionAmount + ChargeTotalAmount

Validation

Belgian PEPPOL Validator

Test your invoices at: https://ecosio.com/en/peppol-and-xml-document-validator/

Common Errors

  1. ubl-BE-01: Missing PEPPOL AdditionalDocumentReference
  2. ubl-BE-10: Wrong tax category names (use BTCC values)
  3. ubl-BE-14: TaxTotal in wrong position in InvoiceLine

Endpoint Scheme IDs for Belgium

Example Validation Response

Successful:

✓ ubl-BE-01: PEPPOL reference present
✓ ubl-BE-10: Correct BTCC values used
✓ ubl-BE-14: TaxTotal correctly positioned
✓ XSD validation passed

Error:

✗ ubl-BE-10: Tax category name "Standard rate" not allowed
  Use: "Taux standard"