Overview
This page is the reference for error handling. It shows the error body formats, the status codes of each endpoint, the frequent validation rules and the correct retry behaviour.Error body formats
The API uses three formats. Read the HTTP status code first, then parse the body.Error with a text message
Most errors return a JSON object with one field,detail, that contains a string.
404 Not Found
Request validation error (422)
When a request does not match the schema of the endpoint (a missing field, a wrong type, a wrong date format),detail is an array. Each item identifies one field.
422 Unprocessable Entity
array
The path to the field. The first item is the part of the request (
body, query or path).string
The description of the problem.
string
The machine-readable error type, for example
missing.Some endpoints also return
422 with a text message in detail, for example "Invalid file type". Your code must accept a string and an array in detail.Validation result
The validation endpoints (POST /api/validate/json, POST /api/validate/ubl and POST /api/documents/{document_id}/validate) return a success status when the document breaks a rule: 201 Created for the two /api/validate/ endpoints and 200 OK for the validation of a stored document. The result is in the body: is_valid is false and issues contains the rule failures.
201 Created
string
required
The text of the rule that failed.
string
required
The issue type, for example
error.string
The identifier of the rule, for example
BR-CO-15 or PEPPOL-EN16931-R120. A failure of the XML schema has the value xsd-validation.string
The severity. An issue with the value
fatal makes the document invalid.string
The position in the generated UBL where the rule failed.
string
The test expression of the rule.
string
required
The rule set that found the issue.
HTTP status codes
The same status code can have different causes on different endpoints. A failure to derive the Peppol IDs gives
406 when you create a document and 400 when you send it. A Peppol ID that is not owned by your company gives 406 when you create a document and 409 when you send it.Create document errors (406)
POST /api/documents/ returns 406 Not Acceptable for four causes. No document is created.
The Peppol sender or receiver cannot be derived
The Peppol sender or receiver cannot be derived
vendor_tax_id and customer_tax_id (or the company IDs) are present and correct.The sender is not a Peppol ID of your company
The sender is not a Peppol ID of your company
GET /api/me/ to see the Peppol IDs of your company.For a self-billing document, the API examines the receiver, and the message starts with Derived receiver. See Ownership rule.The totals in the JSON are not correct
The totals in the JSON are not correct
Total tax mismatch, Total discount mismatch, Invoice total mismatch or Amount due. See Invoice totals and calculations.The generated UBL is not valid for Peppol BIS Billing 3.0
The generated UBL is not valid for Peppol BIS Billing 3.0
detail contains the messages of the rules that failed, without the rule identifiers. Send the same payload to POST /api/validate/json to get the full list of issues with rule_id. Then see Frequent validation 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.Send errors
POST /api/documents/{document_id}/send does these checks in sequence.
Peppol ID routing
When you send a document, the API finds the sender and receiver Peppol IDs in this order:- The query parameters of the send request.
- The Peppol IDs that the API stored with the UBL of the document.
- The identifiers in the document:
vendor_tax_idorvendor_company_idfor the sender, andcustomer_peppol_id,customer_tax_idorcustomer_company_idfor the receiver.
0208 and the enterprise number: the tax ID BE1018265814 gives the Peppol ID 0208:1018265814. For other countries, the derived scheme can be different from the scheme that the receiver registered. Thus the best practice is to give all four query parameters:
cURL
string
Scheme of the sender Peppol ID. Example:
0208.string
Identifier of the sender, without the scheme. Example:
1018265814.string
Scheme of the receiver Peppol ID. Example:
0208.string
Identifier of the receiver, without the scheme. Example:
0848934496.400 if it cannot find a complete sender and receiver Peppol ID. It returns 409 if the sender Peppol ID is not one of the peppol_ids of your company.
Frequent validation rules
For the full procedure, see Validation during development.
A document is in state FAILED
After an accepted send call, the document is in state TRANSIT. The transmission occurs in the background. If all transmission attempts fail, the state becomes FAILED and the document.sent.failed webhook event is sent. See Retry behaviour for the number of attempts.
1
Read the timeline
GET /api/documents/{document_id}/timeline returns the events of the document. Each transmission attempt that failed is an event with event_type send_failed. The details object shows the sender and receiver Peppol IDs that the API used.cURL
200 OK
2
Examine the receiver
Make sure that the receiver Peppol ID in
details is correct. Then call GET /api/validate/peppol-id?peppol_id=0208:0848934496 to see if the receiver is registered on the Peppol network. See Look up Peppol participants.3
Send again
Call
POST /api/documents/{document_id}/send again. The API accepts a send call for a document in state FAILED. If the Peppol IDs were wrong, give the correct IDs as query parameters. See Send a failed document again.The timeline does not contain the technical reason of a failed transmission. If the receiver is registered and the document fails again, contact support@e-invoice.be with the document ID.
Retries and idempotency
Which errors to retry
Rate limits
The rate limit applies to each API key and only to these endpoints:POST /api/documents/POST /api/documents/ublPOST /api/validate/jsonPOST /api/validate/ubl
429 with a Retry-After header that contains a number of seconds.
429 Too Many Requests
Retry-After and wait.
No idempotency key
The API has no idempotency key. If you repeatPOST /api/documents/, the API creates a second draft with the same invoice_id. A send call is different: a second send call for a document in state TRANSIT or SENT returns 405 and does not transmit the document again.
If a create call ends without a response (a timeout or a network error), find out if the document exists before you create it again. Search the drafts for your invoice number. This list contains documents in the states DRAFT, TRANSIT and FAILED. For documents that are sent, use GET /api/outbox/ with the same search parameter. Find duplicates before a retry gives the full procedure.
200 OK
search parameter finds a part of the invoice number, the vendor name, the customer name or the note, thus compare invoice_id for an exact match.
Troubleshooting
422 with "Field required" and loc ["body", "file"]
422 with "Field required" and loc ["body", "file"]
The endpoint expects a
multipart/form-data upload with a part that has the name file. You sent the XML or the PDF as the raw request body. With cURL, use -F "file=@invoice.xml" and do not set the Content-Type header manually. See Send UBL documents and Create documents from PDF.401 on each request
401 on each request
Authentication required means that the request has no Authorization: Bearer header. Invalid authentication means that the API key is not known or is deleted. Make sure that the header has the format Authorization: Bearer <key> and that the key is the key of the company that you want to use. See Authentication.429 during a bulk import
429 during a bulk import
The create and validate endpoints have a rate limit for each API key. Read the
Retry-After header, wait, then continue. Send the requests in sequence, not in parallel.The customer did not receive the document
The customer did not receive the document
Read the state with
GET /api/documents/{document_id}.DRAFT: the document was not sent. Call the send endpoint.TRANSIT: the transmission is in progress.FAILED: see A document is in stateFAILED.SENT: the access point of the receiver accepted the document. Ask the customer to look in the software that is connected to their Peppol ID. Read the timeline to see which receiver Peppol ID was used.
The test email did not arrive
The test email did not arrive
A sandbox company sends each document as an email with the UBL file to the contact email address of your company, not to the customer. Make sure that the contact email address is set, and look in the spam folder. If the company has no contact email address, the send call returns
400 with Tenant is in test mode but no company email is set. See Test mode and sandbox companies.The webhook signature does not match
The webhook signature does not match
The signature is calculated on the full event as JSON with sorted keys, not on the
data field only. Make sure that you use the secret of the correct webhook and that you serialise the payload as the Webhooks guide shows.The sandbox inbox is empty
The sandbox inbox is empty
A sandbox company does not receive documents from the Peppol network, and a document that you send to your own company does not go into the inbox. Use Simulate inbound to put a document into the inbox. See Receive documents.
Next Steps
Validation during development
Find all rule failures of a payload before you create a document.
Document lifecycle and delivery tracking
Learn the states of a document and the transitions between them.
Webhooks
Receive an event when a document is sent or fails.
Invoice totals and calculations
Calculate totals that pass the validation rules.