Overview
TheDocument schema defines the structure of invoices, credit notes and debit notes in the e-invoice.be API. You send this schema when you call POST /api/documents/ or POST /api/validate/json.
Only the
items array is required, with a minimum of one line. All other fields are optional, but a document needs most of them to pass the Peppol BIS Billing 3.0 rules.Validation is not a separate mandatory call.
POST /api/documents/ rejects a payload that does not pass the same rules. Use POST /api/validate/json while you develop, because it returns all rule failures and the generated UBL.Document metadata
enum
default:"INVOICE"
Type of document to create.
INVOICE- Standard invoiceCREDIT_NOTE- Credit note (refund or correction)DEBIT_NOTE- Debit noteSELFBILLING_INVOICE- Self-billed invoiceSELFBILLING_CREDIT_NOTE- Self-billed credit note
enum
default:"DRAFT"
Document state. See Document states.
enum
default:"OUTBOUND"
Document direction.
OUTBOUND- Document that you send to a customerINBOUND- Document that you receive from a supplier
Document states
You can send a document only when it is in the
DRAFT or FAILED state. For the transitions, the retry behaviour and the webhook events of each state, see Document lifecycle and delivery tracking.
See Document lifecycle and delivery tracking for the state diagrams, the transitions, the retries and the related webhook events.
Vendor (supplier) information
string
Legal name of the vendor.Example:
"E-INVOICE BV"string
VAT number of the vendor, with the country prefix. The API changes the value to uppercase and removes all characters other than A-Z and 0-9. See Normalisation and rounding.Example:
"BE1018265814"The API derives the Peppol participant ID of the sender from this value when it sends the document. See Look up Peppol participants for Peppol routing.string
Address of the vendor as one string. See Addresses for the format that the API can split correctly.Example:
"Brusselsesteenweg 119/A, 1980 Zemst, BE"string
Department or person at the vendor address. The API writes this value as the contact name only when
vendor_email is present.Example: "Accounts Department"string
Contact email address of the vendor.Example:
"billing@e-invoice.be"Customer (buyer) information
string
Legal name of the customer.Example:
"OpenPeppol VZW"string
VAT number of the customer, with the country prefix. The API changes the value to uppercase and removes all characters other than A-Z and 0-9.Example:
"BE0848934496"string
Peppol participant ID of the customer, in the format
scheme:identifier. When you send this field, the API uses it as the receiver of the document and does not derive the receiver from customer_tax_id.Example: "0208:0848934496"The API does not store this field with the document. The value is kept only as the receiver of the generated UBL. See Look up Peppol participants to find and check a Peppol ID before you send.string
Your internal reference for the customer. The API writes it as the party identification of the customer. It is also the fallback value of
BuyerReference when purchase_order is absent.Example: "CUST-12345"string
Address of the customer as one string. See Addresses.Example:
"Rond-point Schuman 6, 1040 Brussels, BE"string
Department or person at the customer address. The API writes this value as the contact name only when
customer_email is present.Example: "Accounts Payable"string
Contact email address of the customer.Example:
"ap@openpeppol.example"Invoice details
string
Unique invoice number.Example:
"INV-2026-001"string
Issue date in ISO 8601 format (
YYYY-MM-DD).Example: "2026-10-01"string
Payment due date in ISO 8601 format (
YYYY-MM-DD). The API does not write this field to the UBL of a credit note.Example: "2026-10-31"string
Purchase order reference of the customer. For credit notes, use this to reference the original invoice.Example:
"PO-12345" or "INV-2026-001" (for credit notes)string
Free-text note.Example:
"Full refund - goods returned"string
Description of the payment terms.Example:
"Payment due within 30 days"Financial fields
The API calculatessubtotal, total_discount, total_tax, invoice_total and amount_due when they are absent. When you send them, the API compares them with its own calculation. See Invoice totals and calculations for the formulas.
enum
default:"EUR"
Currency code (ISO 4217).The
currency field accepts these ISO 4217 codes:EUR, USD, GBP, JPY, CHF, CAD, AUD, NZD, CNY, INR, SEK, NOK, DKK, SGD, HKDThe default is EUR.Example: "EUR"number
Taxable base amount (after document-level allowances and charges, before tax).Corresponds to UBL
cac:LegalMonetaryTotal/cbc:TaxExclusiveAmountExample: 1000.00number
Total of the document-level allowances (discounts only, not charges).Corresponds to UBL
cac:LegalMonetaryTotal/cbc:AllowanceTotalAmountExample: 50.00number
Total VAT amount.Corresponds to UBL
cac:TaxTotal/cbc:TaxAmountExample: 210.00number
Total amount with tax (
subtotal + total_tax).Corresponds to UBL cac:LegalMonetaryTotal/cbc:TaxInclusiveAmountExample: 1210.00number
Amount due for payment after prepayments.Corresponds to UBL
cac:LegalMonetaryTotal/cbc:PayableAmountExample: 1210.00number
Previous outstanding balance. This is an internal field: the API does not write it to the generated UBL.Example:
100.00Tax information
enum
default:"S"
Tax category code (UNCL5305).
S- Standard rate (most common)Z- Zero ratedE- Exempt from taxAE- VAT reverse chargeK,G,O,L,M,B- Other special cases
tax_code is K (intra-community supply), each line item must have a tax_rate of 0.00.enum
VAT exemption reason code (when
tax_code is E, AE, K, G, O, L, M or B).Example: "VATEX-EU-IC" for an intra-community supplystring
Text that explains the VAT exemption.Example:
"Reverse charge applies - Art. 196 EU VAT Directive"Service period
string
Start date of the service period (ISO 8601:
YYYY-MM-DD).Example: "2026-09-01"string
End date of the service period (ISO 8601:
YYYY-MM-DD).Example: "2026-09-30"Additional addresses
Of these fields, the API writes only
shipping_address and shipping_address_recipient to the generated UBL (as cac:Delivery). The billing, service and remittance fields are kept with the document, but the receiver does not get them in the UBL.string
Billing address (if different from the customer address).Example:
"Rond-point Schuman 6, 1040 Brussels, BE"string
Recipient at the billing address.Example:
"Accounts Payable Department"string
Delivery address. The API writes it to
cac:Delivery/cac:DeliveryLocation/cac:Address with the same split rule as the party addresses.Example: "Industrieweg 5, 3000 Leuven, BE"string
Recipient at the delivery address. The API writes it as the name of the delivery party.Example:
"Warehouse Manager"string
Address of the service location.Example:
"Industrieweg 5, 3000 Leuven, BE"string
Recipient at the service address.
string
Remittance (payment) address.Example:
"Brusselsesteenweg 119/A, 1980 Zemst, BE"string
Recipient at the remittance address.
Line items
array
required
Payment details
array
Array of payment instructions. The API writes one
cac:PaymentMeans element for each entry, always with payment means code 30 (credit transfer).Example:Allowances and charges
array
Document-level allowances (discounts).Example of a 10% allowance:
array
Document-level charges (fees).Example:
Tax details
array
Tax breakdown for each category and rate.The API calculates the breakdown when it is absent.
Attachments
array
Files in this array are embedded in the UBL. See Attachments and PDF for the permitted file types and for the
construct_pdf option.Example:How fields map to UBL
The API converts the JSON document to UBL BIS Billing 3.0. The table shows the conversions that are not self-evident. The response ofPOST /api/validate/json contains the generated UBL, thus you can examine the result for your own payload.
The MIME type of an attachment in the UBL is
file_type when it is one of application/pdf, image/png, image/jpeg, text/csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet (xlsx) or application/vnd.oasis.opendocument.spreadsheet (ods). For a different file_type, the API uses the extension of file_name (.pdf, .png, .jpg, .jpeg, .csv, .xlsx, .ods) to find the MIME type.
Addresses
vendor_address, customer_address and shipping_address are single strings. The API splits each string into the parts of a UBL address with these rules:
- The API splits the string on new lines. If there is only one line, it splits the string on a comma followed by a space (
", "). - Part 1 is the street (
cbc:StreetName). - Part 2 is the postal code and the city. When the part has the form “postal code, space, city”, the API writes
cbc:PostalZoneandcbc:CityName. If not, the full part is the city. - The last part is the country (
cac:Country/cbc:IdentificationCode) only if it has 2 or 3 letters and no other characters. The API changes it to uppercase. - For the vendor and the customer, if the last part is not a country code, the API uses the first two characters of the tax ID of that party. If there is no tax ID, the country is
BE. Forshipping_address, the API does not use the tax ID: the country isBEwhen the string has no country code.
Unknown Street and Unknown City.
Normalisation and rounding
The API changes some values before it stores the document and generates the UBL.
Rounding of monetary amounts is half-up to 2 decimals (
0.005 becomes 0.01). The API rounds in this sequence:
- Each line
amountis rounded. - For each tax group, the API adds the rounded line amounts, subtracts the document-level allowances and adds the document-level charges. A tax group is one combination of tax category and tax rate.
- The tax of each group is
taxable amount × rate / 100, rounded. total_taxis the sum of the group taxes.
total_tax can be different by some cents. See Invoice totals and calculations.
Example
Complete invoice:Invoice
peppol_ids of your company.
Next Steps
LineItem
Look up the fields of an invoice line.
Create e-invoices
Create and send an invoice with this schema.
Invoice totals and calculations
Calculate the totals that the API checks.
Validation during development
Validate a payload and examine the generated UBL.