On the way in
Send theX-Idempotency-Key header with each event when inbound signing is off. hooksnode stores the first event with a key. When the same key comes again to the same project, hooksnode stores nothing and answers:
200 tells your sender not to retry. Delivery to destinations is still at least once, never exactly once.
- The key is stored on the project. When the event has a source, the stored key is prefixed with that source, so the same header on another source is a new event.
- A key longer than 255 characters is stored as
sha256:plus the hex SHA-256 of the full key. That stored form still dedupes. - Use an ID that your system already has, such as the provider’s event ID.
- A CloudEvents
idis a second dedupe key. Repeating that id is a duplicate even whenX-Idempotency-Keyis new.
X-Idempotency-Key. It drops an exact resend of a signed request (the same body and signature) within 10 minutes, and answers with the same body. Paystack can still deliver the same event more than once, so make each destination idempotent on data.reference. Flutterwave uses data.tx_ref. Stripe uses the event id.
hooksnode sets keys for you on other sources:
On the way out
hooksnode delivers at least once, never exactly once. Your endpoint can get the same event twice. Make your handler safe to run twice:- Find a stable ID in the event. For example, Paystack’s
data.reference, the email’smessage.id, or the bank event’semail.id. - Before you do the work, check if you already did it for that ID.
- Store the ID in the same database transaction as the work.