Webhook Events
Webhook Payload Format
{
"id": "evt_123",
"object": "event",
"type": "order.succeeded",
"created": 1705312200,
"livemode": true,
"data": {
"object": {
"id": "6ba7b811-9dad-11d1-80b4-00c04fd430d0",
"object": "order",
"status": "succeeded"
}
}
}
Signature Verification
Webhooks are signed using HMAC-SHA256. The signature is sent in the EPD-Signature header:
EPD-Signature: t=1705312200,v1=abc123def456...
Verification steps:
- Extract timestamp (
t) and signature (v1) from header - Construct signed payload:
{timestamp}.{raw_body} - Compute HMAC-SHA256 with your signing secret
- Compare using timing-safe comparison
- Reject if timestamp is >5 minutes old
Supported Event Types
| Event | Description |
|---|---|
order.created |
Order created |
order.succeeded |
Payment succeeded |
order.failed |
Payment failed |
order.refunded |
Fully refunded |
order.partially_refunded |
Partially refunded |
order.refund_failed |
Refund failed |
order.voided |
Order voided |
subscription.created |
Subscription created |
subscription.charged |
Billing cycle charged |
subscription.canceled |
Subscription canceled |
subscription.billing.updated |
Billing updated |
customer.created |
Customer created |
customer.updated |
Customer updated |
customer.payment_method.updated |
Payment method changed |
coupon.created |
Coupon created |
coupon.updated |
Coupon updated |
coupon.archived |
Coupon soft-archived (also fired by DELETE /coupons/{id}) |
coupon.unarchived |
Archived coupon restored |
coupon.code.redeemed |
A code was redeemed on an order or subscription |
Retry Policy
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
| 6 | 8 hours |
| 7 | 24 hours |
| Dead Letter | After all retries exhausted |
Timeout: 30 seconds per delivery attempt. Respond with a 2xx status code to acknowledge receipt.