ePostman docs
Console

Sending documents

Idempotency, request constraints and the response when sending a document.

8 min read
  • #idempotency
  • #idempotency-key
  • #202 accepted
  • #json envelope
  • #sapi

One call, an immediate response, asynchronous delivery.

Idempotency

The Idempotency-Key header is mandatory and protects you from a duplicate invoice when a connection drops and you retry. We remember the key and a fingerprint of the body for 24 hours, and behave as follows:

  • Same key, same body — we return the original response; nothing is sent twice.
  • Same key, different body — 409 with SAPI-VAL-009. Keys must not be recycled.
  • New key — decided by the business key below.

The business key: five fields per ID-BDID-01

A second layer runs above the header and does not depend on which Idempotency-Key you send. A document is identified by five fields defined by the Slovak Peppol architecture (rule ID-BDID-01): the supplier’s scheme and identifier, the document type, the invoice number and the issue date. Where each one sits in UBL is in the table below.

Two consequences follow: an invoice and a credit note carrying the same number are two different documents (they differ in BT-03), and so are two invoices with the same number but a different issue date.

Two questions decide it together: did the earlier document leave for the network? and are you sending the same document, or a corrected one?

  • The earlier document never left — the submission goes through, whether you send the same document or a corrected one. The invoice number stays yours. A new document is created with a new providerDocumentId; the earlier one stays in your list with its own status.
  • We accepted the earlier document into custody, or the other side took it, and you send it unchanged — we return 202 with the original providerDocumentId. No second invoice is created, no credit is spent, and the document is not sent again. While that acceptance is still in progress the answer is different — see “A document that is still being processed” below.
  • The other side rejected it (an MLS NOK arrived) — a corrected document goes through under the same number; an unchanged copy gets 409.
  • In every other case — 409 with SAPI-PERM-002. The identifier of the existing document is in details. The invoice number is taken; send the document under a new one or use a credit note.

How this is measured. Not by status — the same status can arise both before and after dispatch. Two things decide together: whether the document left our Access Point, and whether you are sending the same document or a corrected one.

How the document endedSame documentCorrected document
rejected by our validationgoes throughgoes through
recipient not found in Peppol (UNDELIVERABLE)goes throughgoes through
cancelled before dispatchgoes throughgoes through
rejected by the other side (an MLS NOK arrived)409goes through
transmission started and failed409409
transmitted, no delivery status yet202 (replay)409
no answer from the other side (TIMEOUT)202 (replay)409
delivered202 (replay)409 — use a credit note

Three rows deserve an explanation.

Rejected by the other side. This is the only case where a corrected document goes through under the same number: we know for certain that the other side did not accept the original, so the corrected version cannot end up beside it. The Slovak Financial Administration’s e-invoice architecture prescribes exactly that for this outcome — it explicitly states that the originator may send updated invoice data. Sending the document again unchanged, on the other hand, achieves nothing: it carries the same technical identifier, they discard it as a duplicate, and you would get a confirmation from us for something the recipient dropped. That is why we answer 409 there.

While the outcome is uncertain, we do not accept a correction under the same number. Once the transmission began and we do not know how it ended — it failed, no delivery status has arrived yet, or none arrived within the window — the document may have landed at the other side. A corrected version would then appear there as a second document with the same invoice number; its technical identifier differs, so their system would not catch it as a duplicate. For this case the same architecture prescribes corrective action between the service providers, not another document from the originator. The number is released as soon as the outcome becomes clear — when a rejection arrives, the first row of the table applies. If you do not want to wait, use a new invoice number or a credit note.

For an unchanged document those three rows differ. If we already handed it to the other side (the rows “transmitted, no delivery status yet” and TIMEOUT), a repeat gets 202 with the original providerDocumentId and the document is deliberately not sent again — Peppol rules forbid it, because we did receive the acknowledgement of receipt. If the transmission failed on our side, you get 409; repeating such a transmission is not a new submission — contact us and we will repeat it from our side.

Delivered. Here the invoice number is definitively used. Correct such a document with a credit note or a corrective invoice, not with a new submission under the same number.

Documents outside Peppol. When you send to the substitute receiver 0245:9970300001 (the invoice reaches the buyer outside the network and only the tax document goes to the Financial Administration over Peppol), the same table applies — the role of “the other side” is played by the Financial Administration. A document it rejected can therefore be sent again corrected, under the same number; a document it accepted is corrected with a credit note.

In practice this means you do not renumber after a failure. When we reject validation and you fix the error, or the recipient registers in Peppol after an UNDELIVERABLE, you send the same invoice under the same number. That matches both what the Slovak Financial Administration’s e-invoice architecture prescribes for a failed delivery and the fact that an invoice carries a sequential number under the VAT act — an undelivered invoice is not re-issued.

The same holds for a failure on our side before custody: you get a 502 with SAPI-PROC-003 and retryable: true, and you resend under the same number.

A document that is still being processed. If an earlier submission of the same number is still running, you get a 502 with SAPI-PROC-003 and retryable: true — wait and retry. That answer holds for at most 15 minutes; after that we treat the custody attempt as unfinished and a new submission goes through. The exception is a document that has meanwhile reached the wire — the table above then applies, no matter how long it has been in progress.

If the document is missing any one of those five fields the key cannot be read and the submission does not pass through this check.

Duplicate control: the same fields on both interfaces

The same business-duplicate check runs on POST /api/v1/invoices. The key is shared by both interfaces — what differs is the error code (ERR-400 here, SAPI-PERM-002 on SAPI) and what happens to the number after a failure: on the Enterprise API the document keeps holding it, on the SAPI path a document that never left our network releases it (the table above).

It ignores the document bytes and compares five invoice fields defined by the Slovak Peppol architecture (rule ID-BDID-01):

FieldWhere in UBL
BT-34-1the schemeID attribute on the supplier’s cbc:EndpointID
BT-34the value of that same cbc:EndpointID
BT-03cbc:InvoiceTypeCode (cbc:CreditNoteTypeCode on a credit note)
BT-01invoice number, the root cbc:ID
BT-02issue date, cbc:IssueDate

They produce the invoice_uuid in the response. A second document with the same five values gets 409 with ERR-400 and the invoice_id of the existing invoice.

What this means for an ERP:

  • A different issue date means a different document. An invoice reusing a number with a different cbc:IssueDate is not a duplicate and goes through.
  • A credit note may reuse an invoice number — BT-03 differs (381 vs 380).
  • If the receiver implements ID-BDID-01, it computes the same value for the same document, and invoice_uuid then works as a shared reference across the network. The rule requires this of both sides, but it cannot be enforced: against a receiver that does not implement it, invoice_uuid is only our value. The dependable shared reference remains the invoice number (BT-01).
  • If the document is missing any of the five fields, the check is skipped and invoice_uuid is random. All five are mandatory in EN16931, so this only affects documents that would fail validation anyway.
  • Invoices submitted before ID-BDID-01 was introduced are not covered by the duplicate check. Their stored invoice_uuid came from an earlier derivation and is not recomputed — recomputing it would change an identifier the ERP already received in a 202 response. Resubmitting such a document under a new Idempotency-Key therefore does not get a 409 and creates a second invoice. A resubmission with an unchanged body and no new key is caught by idempotency before the duplicate check and returns the original invoice. This is a one-off window: submissions made since the rule was introduced are covered — as long as all five fields can be read from the document.

Request constraints

PropertyValue
Content-Typeapplication/json
Maximum size10 MB
Success response202 Accepted
Check on intakeA valid JSON envelope and well-formed XML in the payload. Deeper validation runs afterwards.