Event delivery and security
Envelope, idempotency, ordering, retries, dead-lettering, signatures and replay protection.
Envelope
Required: specversion (2.0), id, type (nutrab2b.<family>.<event>.v2), source, subject, time, sender, receiver, correlationid, idempotencykey, sequence, env, data.
correlationid is shared by every event of one business conversation; causationid points to the event that triggered this one.
At-least-once delivery and idempotency
Senders retry until they get an ACK, so receivers will see duplicates. The receiver processes each idempotencykey once and answers repeats with DUPLICATE plus the original result (NB-E005).
Recommended key: <sender GLN>:<business id>:<event>:<n>.
Ordering
sequence is monotonic per sender + subject starting at 1. If sequence n+2 arrives before n+1 the receiver parks it (NB-E006) and releases it when the gap fills. A lower sequence than already processed is rejected.
Gaps are detected through HEARTBEAT last_sequences; the sender then replays the missing event unchanged.
Retries and dead-lettering
Retry schedule: immediately, 30 s, 2 min, 10 min, 1 h, 6 h, 24 h. After 7 failed attempts the event goes to the dead-letter queue and an ERROR_NOTICE is raised.
Do not retry 4xx-type rejections (schema or rule errors) unchanged, fix and send with a new idempotency key and the same sequence only if the original was never accepted.
Webhook signatures
Header X-NB2B-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, t + '.' + raw body)>. Verify over the exact raw bytes, compare in constant time, and reject timestamps more than 300 s from your clock (NB-E008).
For non-repudiation, add envelope.signature with a detached JWS (ES256 or EdDSA) and publish your keys as JWKS.
signature = hex(hmac_sha256(secret, `${t}.${rawBody}`))
header = `t=${t},v1=${signature}`Attachments
Never inline PDFs. Put CoA PDFs, certificates and bills of lading in attachments[] with doc_type, an HTTPS URI and the SHA-256 of the file.
Limits
Single event ≤ 1 MB, batch ≤ 10 MB, 100 events/s per partner by default (NB-E012 with Retry-After when exceeded).
