Skip to main content

On the way in

Send the X-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:
The 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 id is a second dedupe key. Repeating that id is a duplicate even when X-Idempotency-Key is new.
With inbound signing on, hooksnode ignores 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:
  1. Find a stable ID in the event. For example, Paystack’s data.reference, the email’s message.id, or the bank event’s email.id.
  2. Before you do the work, check if you already did it for that ID.
  3. Store the ID in the same database transaction as the work.