Business Gateway
Reference

Error codes

The stable code values, what causes them, and what to do.

Failures come back as:

{ "error": { "code": "VALIDATION_FAILED", "message": "…" } }

code is stable and is what your software should branch on. message is written for people and its wording may change.

The document itself

CodeHTTPCause
PEPPOL_VALIDATION_FAILED400The document does not satisfy the Peppol rules for its type
VALIDATION_FAILED400The request was malformed: a bad field, an unknown JSON key, a cursor that does not parse
VALIDATION_UNAVAILABLE400 / 503The document could not be checked. Retry later; it is not a verdict
PEPPOL_DOCUMENT_NOT_SUPPORTED400No capability covers this document type in this direction
PEPPOL_RECIPIENT_NOT_FOUND400The receiving address is not known to us
PEPPOL_DISCOVERY_FAILED400 / 503The recipient could not be looked up on the network
PAYLOAD_TOO_LARGE413Over the size limit for the body or the document

A validation failure is yours to fix — resending the same bytes fails again. A discovery failure is often the recipient's address being wrong, or their registration not covering the document type.

Credentials and access

CodeHTTPCause
UNAUTHORIZED401Missing, malformed or revoked credential
FORBIDDEN403The credential is valid but not allowed here
PERMISSION_DENIED403The API key lacks the permission this route needs
PASSWORD_CHANGE_REQUIRED403The user must set a new password first
NOT_FOUND404Missing, out of your scope, or not a valid id

NOT_FOUND is deliberately returned for things that exist but are outside your scope. A credential confined to one company cannot tell the difference between another company's document and one that was never created — that is the point.

State and conflicts

CodeHTTPCause
CONFLICT409It already exists
INVALID_STATE409The action does not apply in the current lifecycle state
IDEMPOTENCY_CONFLICT409The same Idempotency-Key with a different body
IDENTIFIER_TAKEN409That company or participant identifier is in use
EMAIL_CONFLICT409That email already belongs to a user
COMPANY_REQUIRED400Your credential reaches several companies and the request did not name one
ACCOUNT_CLOSED / COMPANY_CLOSED409Closed, and not accepting changes
LAST_OWNER / LAST_API_KEY409Removing it would leave no way in

Rate limiting and availability

CodeHTTPCause
429 (no code needed)429Too many requests. Wait for Retry-After
PEPPOL_UNAVAILABLE503A dependency is down. Retry with backoff
PEPPOL_INTERNAL_ERROR500Our fault. Retrying an identical request rarely helps

What to retry

Retry 429 after Retry-After, and 503 with exponential backoff. Both are temporary by definition.

Do not retry a 4xx unchanged — the answer will not differ. The exception is VALIDATION_UNAVAILABLE, which says the check could not be run rather than that it failed.

Always carry an Idempotency-Key on sends, so that a retry after a timeout — where you never learned whether the first attempt landed — cannot produce a second document.

On this page