Skip to main content

Register a webhook

The response includes a signingSecret — save it immediately, it is returned once only.

Available events


Event payload shape

Torpedo sends a POST with a JSON body. Every event uses the same envelope:
The request also carries these headers:

data by event

Email SMS
  • stat and providerStatus are the operator’s delivery status, for example UNDELIV, EXPIRED or REJECTD.
  • providerErrorCode is the operator’s error code, or null when it didn’t send one.
  • failureCategory is one of undeliverable, expired, rejected, deleted or unknown for sms.undelivered, and submission_error for sms.failed.
A permanent failure (undeliverable or rejected) also adds the number to your suppression list. Example sms.undelivered:
Verify (WhatsApp OTP) Every verification.* event includes verificationId, to and clientRef (your reference from the start request, or null). Some events add more fields:
  • channel is whatsapp or sms.
  • errorCode is the WhatsApp error code, for example 131026 when the number isn’t on WhatsApp.
  • For WhatsApp, errorCategory is one of recipient_unreachable, throttled, transient, invalid_request, expired or platform. For SMS it uses the same categories as sms.undelivered.
  • In verification.fallback, reason is the WhatsApp errorCategory that triggered the fallback.
Example verification.fallback:
Domains Use the ID in data to fetch the full record, for example GET /api/v1/sms/{smsId}, GET /api/v1/emails/{emailId} or GET /api/v1/verify/{verificationId}.

Verifying the signature

Every request from Torpedo includes an X-Signature header:
Verify it to confirm the request is genuine:
Always verify the signature before processing webhook payloads. Use timing-safe comparison (timingSafeEqual, hmac.Equal, CryptographicOperations.FixedTimeEquals) to prevent timing attacks — never use plain string equality.

Delivery retries

Torpedo retries failed webhook deliveries up to 7 times over about 27 hours: after 5 seconds, 5 minutes, 30 minutes, 2 hours, 5 hours, 10 hours and 10 hours. Your endpoint should:
  • Return 2xx within 5 seconds
  • Be idempotent. The same event may be delivered more than once, always with the same id
Status codes that change retry behaviour: View delivery history via GET /api/v1/webhooks/{id}/deliveries.