Idempotencia, limity požiadavky a odpoveď pri odoslaní dokumentu.Idempotency, request constraints and the response when sending a document.
7 min čítania7 min read
#idempotencia
#idempotency-key
#202 accepted
#json obálka
#sapi
#idempotency
#idempotency-key
#202 accepted
#json envelope
#sapi
Jedno volanie, okamžitá odpoveď, asynchrónne doručenie.
Idempotencia
Hlavička Idempotency-Key je povinná a chráni vás pred duplicitnou faktúrou,
keď sa spojenie preruší a vy odoslanie zopakujete. Zapamätáme si kľúč aj odtlačok
tela na 24 hodín a správame sa takto:
Rovnaký kľúč, rovnaké telo — vrátime pôvodnú odpoveď, dokument sa neodošle druhýkrát.
Rovnaký kľúč, iné telo — 409 s kódom SAPI-VAL-009. Kľúč sa nesmie recyklovať.
Nový kľúč — rozhodne obchodný kľúč nižšie.
Obchodný kľúč: pätica polí podľa ID-BDID-01
Nad hlavičkou beží ešte druhá vrstva, ktorá nezávisí od toho, aký Idempotency-Key
pošlete. Dokument identifikujeme päticou polí podľa slovenskej Peppol architektúry
(pravidlo ID-BDID-01): schéma a identifikátor dodávateľa, typ dokladu, číslo faktúry
a dátum vystavenia. Presné umiestnenie v UBL nájdete v tabuľke nižšie.
Z toho plynú dva dôsledky: faktúra a dobropis s rovnakým číslom sú dva rôzne doklady
(líšia sa v BT-03), a rovnako sú dva rôzne doklady dve faktúry s rovnakým číslom, ale
iným dátumom vystavenia.
Rozhodujú dve otázky naraz: odišiel predošlý doklad do siete? a posielate ten istý
doklad, alebo opravený?
Predošlý doklad do siete neodišiel — podanie prejde, či už posielate ten istý
doklad alebo opravený. Číslo faktúry ostáva vaše. Vznikne nový doklad s novýmproviderDocumentId, pôvodný ostáva vo výpise so svojím stavom.
Predošlý doklad sme prevzali do úschovy alebo ho protistrana prevzala a posielate ho
nezmenený — vrátime 202 s pôvodnýmproviderDocumentId. Druhá faktúra
nevznikne, kredit sa nespotrebuje a doklad sa neposiela znova. Kým prevzatie ešte
prebieha, odpoveď je iná — viď „Doklad, ktorý sa práve spracúva” nižšie.
Protistrana doklad odmietla (prišlo MLS NOK) — opravený doklad prejde pod tým
istým číslom; nezmenená kópia dostane 409.
Vo zvyšných prípadoch — 409 s kódom SAPI-PERM-002. V details je identifikátor
existujúceho dokumentu. Číslo faktúry je obsadené; pošlite doklad pod novým číslom
alebo použite dobropis.
Ako sa to meria. Nie podľa stavu — ten istý stav totiž vie vzniknúť pred odoslaním aj
po ňom. Rozhodujú dve veci naraz: či dokument opustil náš Access Point, a či posielate
ten istý doklad, alebo opravený.
Ako doklad skončil
Ten istý doklad
Opravený doklad
zamietnutý našou validáciou
prejde
prejde
príjemca sa nenašiel v Peppole (UNDELIVERABLE)
prejde
prejde
zrušený pred odoslaním
prejde
prejde
zamietnutý protistranou (prišlo MLS NOK)
409
prejde
prenos sme začali a zlyhal
409
409
odoslaný, odpoveď zatiaľ nedorazila
202 (prehratie)
409
bez odpovede protistrany (TIMEOUT)
202 (prehratie)
409
doručený
202 (prehratie)
409 — riešte dobropisom
Tri riadky si zaslúžia vysvetlenie.
Zamietnutý protistranou. Toto je jediný prípad, keď opravený doklad prejde pod tým
istým číslom: vieme s istotou, že protistrana pôvodný doklad neprijala, takže opravená
verzia u nej nemôže pribudnúť ako druhá. Predpisuje to aj architektúra e-faktúry Finančnej
správy — pre tento výsledok výslovne uvádza, že pôvodca môže poslať opravené údaje faktúry.
Poslať doklad znova nezmenený naopak nemá zmysel: má rovnaký technický identifikátor,
protistrana ho zahodí ako duplicitu a vy by ste od nás dostali potvrdenie o niečom, čo
príjemca zahodil. Preto vtedy odpovieme 409.
Kým je výsledok neistý, opravu pod tým istým číslom neprijmeme. Keď sa prenos rozbehol
a nevieme, ako dopadol — zlyhal, alebo odpoveď zatiaľ nedorazila, prípadne nedorazila
v lehote — mohol doklad u protistrany skončiť. Opravená verzia by mu tam pribudla ako
druhý doklad s tým istým číslom; technický identifikátor má iný, takže by ju jej systém
ako duplicitu nezachytil. Pre tento prípad tá istá architektúra nepredpisuje odoslanie
ďalšieho dokladu, ale nápravu na strane poskytovateľov. Číslo sa uvoľní, len čo sa
výsledok vyjasní — keď dorazí zamietnutie, platí prvý riadok tabuľky. Ak nechcete čakať,
použite nové číslo faktúry alebo dobropis.
Pri nezmenenom doklade sa tie tri riadky líšia. Ak sme ho už odovzdali protistrane
(riadky „odoslaný, odpoveď zatiaľ nedorazila” a TIMEOUT), opakovanie dostane 202
s pôvodným providerDocumentId a doklad sa zámerne neposiela znova — pravidlá Peppolu
to zakazujú, lebo potvrdenie o prevzatí sme dostali. Ak prenos zlyhal ešte u nás, dostanete
409; zopakovanie takého prenosu nie je nové podanie — napíšte nám a prenos zopakujeme
z našej strany.
Doručený. Tu je číslo faktúry definitívne použité. Opravu takého dokladu urobte
dobropisom alebo opravnou faktúrou, nie novým podaním pod tým istým číslom.
Doklady mimo Peppolu. Keď posielate na substitútneho príjemcu 0245:9970300001 (faktúra
ide k odberateľovi mimo siete a do Peppolu odchádza len daňový doklad pre Finančnú správu),
platí tá istá tabuľka — len rolu „protistrany” hrá Finančná správa. Doklad, ktorý FS SR
odmietla, teda pošlete opravený pod tým istým číslom; doklad, ktorý FS SR prijala, sa
opravuje dobropisom.
Prakticky to znamená, že po zlyhaní doklad neprečíslovávate. Keď zamietneme validáciu
a vy chybu opravíte, alebo sa príjemca dodatočne zaregistruje v Peppole po
UNDELIVERABLE, pošlete tú istú faktúru pod tým istým číslom. Zodpovedá to aj tomu, čo
predpisuje architektúra e-faktúry Finančnej správy pre neúspešné doručenie, aj tomu, že
faktúra má poradové číslo podľa zákona o DPH — nedoručená faktúra sa nevystavuje nanovo.
To isté platí pri zlyhaní na našej strane pred prevzatím do úschovy: dostanete 502
s kódom SAPI-PROC-003 a retryable: true a doklad zopakujte pod tým istým číslom.
Doklad, ktorý sa práve spracúva. Ak predošlé podanie toho istého čísla ešte beží,
dostanete 502 s kódom SAPI-PROC-003 a retryable: true — počkajte a zopakujte.
Táto odpoveď platí najviac 15 minút; potom považujeme prevzatie za nedokončené a nové
podanie prejde. Výnimkou je doklad, ktorý sa medzitým už dostal na drôt — vtedy platí
tabuľka vyššie bez ohľadu na to, ako dlho je v spracovaní.
Ak dokument ktorékoľvek z tých piatich polí neobsahuje, kľúč sa vyčítať nedá
a podanie touto kontrolou neprechádza.
Kontrola duplicity: tie isté polia na oboch rozhraniach
Tá istá kontrola obchodnej duplicity beží aj pri POST /api/v1/invoices. Kľúč je
spoločný pre obe rozhrania — líši sa len kód chyby (ERR-400 tu, SAPI-PERM-002 na
SAPI) a to, čo sa stane s číslom po zlyhaní: na Enterprise API ho doklad drží ďalej,
na SAPI ceste ho uvoľní doklad, ktorý do siete neodišiel (tabuľka vyššie).
Nezáleží pri nej na bajtoch dokumentu — porovnáva sa päť polí faktúry podľa slovenskej
Peppol architektúry (pravidlo ID-BDID-01):
Pole
Kde v UBL
BT-34-1
atribút schemeID na cbc:EndpointID dodávateľa
BT-34
hodnota toho istého cbc:EndpointID
BT-03
cbc:InvoiceTypeCode (cbc:CreditNoteTypeCode pri dobropise)
BT-01
číslo faktúry, koreňové cbc:ID
BT-02
dátum vystavenia, cbc:IssueDate
Z nich vzniká invoice_uuid v odpovedi. Druhý dokument s rovnakou päticou dostane
409 s kódom ERR-400 a s invoice_id už existujúcej faktúry.
Čo z toho vyplýva pre ERP:
Iný dátum vystavenia = iný doklad. Faktúra s rovnakým číslom, ale iným
cbc:IssueDate, duplicita nie je a prejde.
Dobropis smie použiť číslo z faktúry — líši sa v BT-03 (381 vs 380).
Ak príjemca implementuje ID-BDID-01, spočíta pre ten istý doklad tú istú
hodnotu — vtedy je invoice_uuid použiteľný ako spoločná referencia naprieč
sieťou. Norma to od oboch strán vyžaduje, ale vynútiť sa to nedá: voči príjemcovi,
ktorý pravidlo neimplementuje, je invoice_uuid len naša hodnota. Spoľahlivá
spoločná referencia je preto naďalej číslo faktúry (BT-01).
Keď dokument ktorékoľvek z piatich polí neobsahuje, kontrola sa preskočí
a invoice_uuid je náhodné. Všetkých päť je v EN16931 povinných, takže sa to
týka len dokumentov, ktoré aj tak neprejdú validáciou.
Faktúry podané pred zavedením ID-BDID-01 kontrola duplicity nezachytí. Ich
uložený invoice_uuid vznikol podľa staršieho pravidla a neprepočítava sa —
prepočet by menil identifikátor, ktorý ERP už dostalo v odpovedi 202. Podanie
toho istého dokladu pod novým Idempotency-Key preto 409 nedostane a založí
sa druhýkrát. Podanie s nezmeneným telom a bez nového kľúča zachytí ešte pred
kontrolou duplicity idempotencia a vráti pôvodnú faktúru. Je to jednorazové okno:
podania od zavedenia pravidla kryté sú — pokiaľ sa z dokumentu dá vyčítať
všetkých päť polí.
Obmedzenia požiadavky
Vlastnosť
Hodnota
Content-Type
application/json
Maximálna veľkosť
10 MB
Odpoveď pri úspechu
202 Accepted
Kontrola pri príjme
Platná JSON obálka a správne utvorené XML v poli payload. Hlbšia validácia beží až potom.
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 newproviderDocumentId; 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 originalproviderDocumentId. 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 ended
Same document
Corrected document
rejected by our validation
goes through
goes through
recipient not found in Peppol (UNDELIVERABLE)
goes through
goes through
cancelled before dispatch
goes through
goes through
rejected by the other side (an MLS NOK arrived)
409
goes through
transmission started and failed
409
409
transmitted, no delivery status yet
202 (replay)
409
no answer from the other side (TIMEOUT)
202 (replay)
409
delivered
202 (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):
Field
Where in UBL
BT-34-1
the schemeID attribute on the supplier’s cbc:EndpointID
BT-34
the value of that same cbc:EndpointID
BT-03
cbc:InvoiceTypeCode (cbc:CreditNoteTypeCode on a credit note)
BT-01
invoice number, the root cbc:ID
BT-02
issue 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
Property
Value
Content-Type
application/json
Maximum size
10 MB
Success response
202 Accepted
Check on intake
A valid JSON envelope and well-formed XML in the payload. Deeper validation runs afterwards.