Skip to main content
The signature covers the full webhook payload: id, delivered_at, event. Two signature algorithms are supported depending on the keyType:
  1. Create a payload object: id, delivered_at, event
  2. JSON.stringify(payload)
  3. Encode the JSON string to Base64
  4. Sign using ED25519 (ed25519.signAsync)
  5. Encode the signature to Base64

Legacy (Deprecated)

  1. Create a payload object: id, delivered_at, event
  2. JSON.stringify(payload)
  3. Encode the JSON string to Base64
  4. SHA256 hash (privateKey + data)
  5. Encode the hash to Base64

Security Details:

  • The signature covers all fields, including id and delivered_at
  • A unique id prevents replay attacks
  • Timestamp validation prevents accepting outdated webhooks (16-minute window)
  • The 16-minute window accounts for retries (immediate + 5 min + 10 min) + network buffer
  • ED25519 provides cryptographic authenticity

Retry Logic

  1. First attempt: Immediately
  2. Second attempt: delay of 300 seconds (5 minutes)
  3. Third attempt: delay of 600 seconds (10 minutes)
  4. Error: task is removed from the queue and logged

IMPORTANT: Always verify webhooks to prevent forgery and replay attacks.

Full Verification Algorithm


ED25519 Verification Steps

  1. Replay protection - check webhook.id that it has not been seen before
  2. Timestamp validation - validate delivery_at within 16 minutes (maximum delivery time + buffer)
  3. Payload reconstruction - id, delivery_at, event
  4. Signature verification - ed25519.verifyAsync (signature, payload, publicKey)
  5. Store the webhook ID - store it to prevent replay in the future”