Idempotency in the eConnect PSB API: how to prevent duplicate submissions with the X-EConnect-DocumentId header.
When sending invoices and other documents through an API there is always a risk of duplicate submissions. A network timeout, a restart of your application or an unexpected error can leave you unsure whether a document was actually processed. Without protection you could end up sending the same document again, resulting in duplicate invoices.
The PSB API offers a built-in idempotency mechanism that solves this problem. By including a unique documentId with every upload, the PSB recognises duplicate attempts and prevents the same document from being processed twice.
The idempotency mechanism revolves around the HTTP header X-EConnect-DocumentId. When sending a document you add this header with a unique value that identifies the document.
POST /api/v1/{partyId}/salesInvoice/send HTTP/1.1
Host: psb.econnect.eu
Authorization: Bearer {token}
Content-Type: application/xml
X-EConnect-DocumentId: 550e8400-e29b-41d4-a716-446655440000
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
...
</Invoice>
The PSB processes the document and stores the documentId. If you send the same request again (for example as a retry after a timeout), the PSB recognises that the documentId already exists and returns a 409 Conflict response instead of processing the document a second time.
HTTP/1.1 409 Conflict
That 409 is not an error in the traditional sense. It is a confirmation that the document was already processed successfully. Your application can safely mark the request as completed.
The documentId you include in the X-EConnect-DocumentId header must meet a few requirements:
@ and _ are not allowedImportant: never use the invoice number as documentId. An invoice number can be reused for a credit note or a corrected invoice, leading to conflicts. Use a UUID/GUID instead, generated once per document and reused on retry.
A UUID is the recommended choice. It is guaranteed to be unique and widely supported in all programming languages.
Good: 550e8400-e29b-41d4-a716-446655440000 (UUID)
Good: DOC2026030800142 (custom sequence, as long as it is unique)
Bad: INV-2026-001 (invoice number, do not use)
Bad: ab@cd (special characters)
Bad: abc (too short)
Idempotency becomes most valuable in combination with retry logic. If an API call fails due to a network error or a 5xx server error, you want to retry the request without the risk of duplicate processing.
The recommended approach works as follows:
X-EConnect-DocumentId header.200 OK: the document has been processed, done.409 Conflict: the document was already processed in a previous attempt, done.5xx error or a timeout: wait and retry the request with the same documentId.4xx error (other than 409): there is a problem with the request itself. Retrying is pointless; the error needs to be fixed.Send document with X-EConnect-DocumentId
Response?
Processed
Already processed, safe to complete
Wait (exponential backoff)
Fix error, do not retry
Tip: use exponential backoff for retries. Start with a short wait time (for example 1 second) and double it with each subsequent attempt, up to a maximum of, say, 60 seconds.
For document delivery the PSB uses a retry policy of up to 8 attempts over about 72 hours (about 3 days). That is separate from HTTP 5xx retries on your own API calls or webhooks: whether a delivery failure is retried depends on the delivery channel.
The X-EConnect-DocumentId header is supported on all endpoints that upload documents to the PSB. The most important ones are:
POST /api/v1/{partyId}/salesInvoice/sendPOST /api/v1/{partyId}/generic/sendPOST /api/v1/{partyId}/purchaseOrder/sendFor receive endpoints (downloading documents) idempotency does not apply: retrieving a document is inherently idempotent, as it does not modify any data. Note that inbound Peppol traffic does not use X-EConnect-DocumentId for duplicate detection.
Idempotency via X-EConnect-DocumentId applies to outbound upload endpoints. It does not function as a duplicate mechanism for Validate/Transform endpoints or inbound Peppol reception.
In addition, different routes have different document and attachment limits:
POST /salesInvoice/send requestEmbedded attachments are supported as inline base64 only (no separate attachment upload endpoint).
Idempotency is a small mechanism with a big impact. By consistently including an X-EConnect-DocumentId with every document upload, you protect yourself against duplicate submissions. Combined with retry logic and exponential backoff, you build a robust integration that withstands network issues and temporary server errors.
In short
Include the X-EConnect-DocumentId header with a unique UUID for every document upload. On a retry the PSB returns 409 Conflict if the document has already been processed. Never use the invoice number as documentId.
An invoice number can reappear on a credit note or a corrected invoice. Use a UUID (v4) per document and reuse it on retry, so the 409 check is tied to the document and not to the invoice number.
The PSB then generates a documentId itself. The downside is that after a network error you cannot tell whether the document was already processed. By sending your own documentId you can retry safely: a duplicate upload returns a 409 Conflict.
Idempotency applies to all write endpoints that upload documents, such as sending invoices, orders and generic documents. It does not apply to download endpoints (retrieving documents), because retrieval does not change data.
View the full API documentation