Error handling: HTTP codes, retries and robust integration

HTTP status codes, error responses and retry logic of the PSB API: how to build a robust integration.

Every API integration will encounter errors sooner or later. A network outage, an unreachable server, an incorrectly formatted document: it comes with the territory. The PSB API communicates errors through standard HTTP status codes and structured JSON responses. In addition, the PSB has a built-in retry mechanism that automatically handles temporary errors during document delivery.

In this article you will learn which status codes the PSB returns, how to interpret error responses, when you can safely retry and how the PSB's automatic retry mechanism works.

HTTP status codes

The PSB API uses standard HTTP status codes to indicate the result of a request. The status codes fall into two categories: client errors (4xx) that you need to fix yourself, and server errors (5xx) that you can retry.

Success response
CodeMeaningExplanation200OKThe request was processed successfully201CreatedNew object created (for example a hook, subscriber or document/resource)202AcceptedRequest accepted for asynchronous/queue processing; check the status later204No ContentRequest successful without a response body (for example on DELETE or an update without a body)
Client errors (4xx): do not retry

With a 4xx error the problem is in the request itself. Resending with the same data will produce the same result. Fix the cause before trying again.

CodeMeaningWhenAction400Bad RequestValidation error or syntax error in the documentCheck the request body. The JSON response contains details about what went wrong401UnauthorizedNo token sent, or the token has expired or is invalidRequest a new Bearer token from the Identity Server403ForbiddenThe token is valid, but the action is not allowed. Most common: you are using a partyId that your account does not have access to. Other causes: expired bearer token, invalid subscription key, or an endpoint that is not available for your authorisation levelCheck that you are using the correct partyId and that the user who obtained the bearer token has access to that partyId. If in doubt: obtain a new token via the Identity Server404Not FoundThe requested endpoint or resource does not exist (for example an unknown Document ID, hook or PartyID). When sending, this also occurs with the combination "No valid delivery options. PartyId '...' not found in Peppol" (among others with VerstuurInvoice): the offered PartyId is not (for this document type) on Peppol/SMPCheck the URL, the Document ID and the partyId. On "PartyId not found in Peppol": first do a lookup via queryRecipientParty or lookup.peppol.org on the offered ID, then optionally check related schemes (for example BE 0208 versus 9925/BE:VAT, same core number) -- only recommend an EndpointID change on a confirmed lookup hit. No hit on any candidate ID: the recipient is not reachable on those identifiers; the customer must ask the recipient for registration or another submission ID405Method Not AllowedThe HTTP method used is not supported on this endpointCheck the API documentation for the correct method (GET/POST/PUT/DELETE)409ConflictThe document has already been processed (idempotency)No action needed: the document was received successfully earlier. See idempotency413Content Too LargeThe file exceeds the maximum sizeReduce the document or attachments. IDR limit: 15 MB415Unsupported Media TypeThe Content-Type header is missing or incorrectUse the correct content type, for example application/json where required422Unprocessable EntityThe request is technically correct, but the content cannot be processed (for example invalid UBL, a Peppol validation error or a violated business rule)Check the document structure and business rules; the JSON response usually contains details400 (duplicate agencies)Duplicate identifier schemeTwo or more identifiers with the same scheme/agency code in a single queryRecipientParty call. Error message: EConnect.Psb.Models.EConnectException: 'Duplicate id agencies {code} requested.' (where {code} is the agency code without leading zero, e.g. scheme 0208208).Provide only one identifier per scheme per call. Multiple candidates within the same scheme: make separate calls.

API403 Access forbidden: the literal error message [API403] Access forbidden. Please check PartyId authorization and make sure the Subscription-Key is valid can occur among other things with a failed Peppol submission from Business Central ("delivery failed"), but the cause is generic to the PSB, not BC-specific. Diagnostic order:

  1. Check the PartyId authorization: are you using the correct partyId and does the account link have rights to that party?
  2. Refresh the Bearer token if it has expired or is invalid.
  3. Check the Subscription-Key only if that header is still required (legacy/Collabrr/API31) -- not as a first step by default.

Note: the mention of "Subscription-Key" in the error message does not automatically mean the key needs to be renewed. PartyId authorization and a platform-side linking issue are equally common causes. If delivery keeps failing after a valid token and partyId check, escalate to eConnect support instead of repeatedly rotating the Subscription-Key.

SBDH envelope validation (API400.USRMS1 / API400.USRMS2): these error codes indicate a mismatch between the Peppol envelope (SBDH) and the e-invoice document itself. With USRMS1 the sender or recipient in the envelope does not match the identifiers in the invoice XML. With USRMS2 the PSB cannot find a recognisable sender in the document. Check that the EndpointID and PartyIdentification in your UBL match the values provided when sending. The PSB rejects the document at the AS4 level and returns the error to the sending Access Point.

Rate limiting (429): retryable

An exception to the rule "only 5xx is retryable": 429 Too Many Requests indicates rate limiting and is retryable. Wait and respect the Retry-After header before resending the request.

CodeMeaningWhenAction429Too Many RequestsRate limiting: you are sending too many requests in a time windowWait and respect the Retry-After header, then retry
Server errors (5xx): retry

A 5xx error indicates a temporary problem on the server side. The request itself may be correct. Together with 429, these are the only status codes where retrying makes sense.

CodeMeaningWhenAction500Internal Server ErrorUnexpected server errorRetry with exponential backoff502Bad GatewayInvalid response from an upstream service; usually temporaryRetry with exponential backoff503Service UnavailableThe PSB is temporarily unavailable (maintenance, overload)Retry with exponential backoff504Gateway TimeoutAn upstream service does not respond in timeRetry with exponential backoff

Note: the send endpoint accepts a maximum of 24 MB per request, including HTTP overhead. Payloads exceeding this limit are rejected by the web server with an HTTP 500 instead of a 413, because the rejection occurs before the application layer performs its validation. Keep this in mind with base64-encoded attachments: they add approximately 33% to the file size.

API500UH during deployments: the error code API500UH (Unhandled error) can occur when the PSB performs an internal service update (Service Fabric deployment). In many cases the document has already been delivered successfully to the recipient, but the confirmation step fails due to the migration. The PSB's retry mechanism automatically attempts to complete the remaining steps. If you receive an API500UH, check via the status events whether the document was delivered before resending it.

Reading error responses

With a 4xx error the response contains a JSON body describing the problem. This information helps you identify the cause quickly.

{
  "error": "Validation failed",
  "message": "The supplied document is not valid UBL 2.1",
  "details": [
    "cbc:InvoiceTypeCode is missing"
  ]
}

With a 5xx error the response is not always structured. Base your retry logic on the HTTP status code, not on the content of the body.

Retry strategy for your integration

Not every error deserves a retry. The rule of thumb is simple: only 5xx status codes and network timeouts are worth retrying. With 4xx errors you need to modify the request before sending it again.

Exponential backoff

The recommended retry strategy is exponential backoff: start with a short wait time and double it with each subsequent attempt.

AttemptWait time11 second22 seconds34 seconds48 seconds516 seconds632 seconds7+60 seconds (maximum)

Tip: add a small random spread (jitter) to the wait time. If multiple clients retry simultaneously after an outage, jitter prevents them from all hitting the server at the same moment.

Safe retries with idempotency

Always combine your retry logic with the X-EConnect-DocumentId header. By including the same documentId with each attempt, the PSB guarantees that a document is never processed twice. If the PSB receives a documentId that has already been processed, it returns a 409 Conflict as confirmation.

See Idempotency: preventing duplicate submissions for the full explanation and code examples.

Decision tree
Automatic retry mechanism of the PSB

In addition to the retry logic you implement yourself, the PSB has its own retry mechanism for document delivery. If the PSB attempts to deliver an invoice or order to the recipient and that party returns a 5xx error, the PSB automatically resumes delivery.

Document delivery (invoices and orders)

The PSB makes up to 8 retry attempts spread over approximately 35 hours. With each attempt the PSB publishes an event so you can track progress:

EventMeaningInvoiceSentRetryA new delivery attempt for an invoice has startedInvoiceSentErrorAll 8 attempts have failed, the invoice could not be deliveredOrderSentRetryA new delivery attempt for an order has startedOrderSentErrorAll 8 attempts have failed, the order could not be delivered

If you have configured a webhook for these topics, you receive a notification with each attempt. After an InvoiceSentError or OrderSentError, manual action is required: contact the recipient or escalate via eConnect Support.

Tip: subscribe to the InvoiceSentRetry and InvoiceSentError topics via a webhook. This way you detect delivery issues immediately and can act proactively.

Webhook delivery

For webhooks the PSB uses a separate retry schedule. If your webhook endpoint is unreachable or does not return a 2xx status code, the PSB retries delivering the event.

ParameterValueMaximum number of attempts12Maximum retry duration~6 days (approximately 137 hours)StrategyExponential backoffTimeout per attempt100 secondsEvent per attemptHookSentRetryEvent on definitive failureHookSentError

The PSB expects a 2xx response from your endpoint within 100 seconds. Any other response (or a timeout) counts as a failed attempt. Therefore, process incoming webhooks as quickly as possible, confirm receipt with a 200 OK and perform heavy processing asynchronously in a background process.

Note: if your endpoint is unreachable for an extended period, the PSB stops retrying after approximately 6 days (137 hours). Missed events can still be retrieved via the batch endpoint. See Batch hooks for more information.

PSB hostnames for network whitelisting

For integrations that access the PSB from a restricted network (firewall, proxy, allowlist), both the primary and failover hostnames must be allowed. everbinding.nl is the legacy eConnect domain and is actively used for PSB failover.

EnvironmentPrimaryFailoverProductionpsb.econnect.euapi.everbinding.nlAcceptanceaccp-psb.econnect.eutestapi.everbinding.nl

Whitelist all four hostnames on port 443 (HTTPS). Without the failover hostnames, a valid PSB connection can become unreachable during a fail-event, while the PSB itself is still running.

Overview: retryable or not?
Status codeRetryableStrategy200 OKNot neededProcessed201 CreatedNot neededProcessed202 AcceptedNot neededCheck status later204 No ContentNot neededProcessed400 Bad RequestNoFix request401 UnauthorizedNoRequest new token403 ForbiddenNoCheck permissions404 Not FoundNoCheck URL/resource405 Method Not AllowedNoCheck HTTP method409 ConflictNoDocument was already processed413 Content Too LargeNoReduce file size415 Unsupported Media TypeNoFix Content-Type header422 Unprocessable EntityNoCheck document structure/business rules429 Too Many RequestsYesWait for Retry-After, exponential backoff500 Internal Server ErrorYesExponential backoff502 Bad GatewayYesExponential backoff503 Service UnavailableYesExponential backoff504 Gateway TimeoutYesExponential backoff

In short Client errors (4xx) require your attention: fix the problem in your request. Server errors (5xx) are temporary and can be safely retried with exponential backoff. Always use the X-EConnect-DocumentId header to prevent duplicate processing on retries. The PSB automatically retries document delivery up to 8 times over approximately 3 days (72 hours), and webhooks up to 12 times over approximately 6 days (137 hours).

View the full API documentation