Webhooks
Receive real-time notifications when events occur in your inboxes. Webhooks push data to your server instead of polling the API.
Webhook Headers
Every webhook delivery includes these headers:
| Header | Description |
|---|---|
Content-Type | Always application/json |
User-Agent | destroy.network-Webhook/1.0 |
X-Webhook-ID | Your webhook configuration ID |
X-Webhook-Event | Event type (e.g., message.received) |
X-Delivery-ID | Unique ID for this delivery attempt |
X-Webhook-Signature | HMAC-SHA256 signature (if secret configured) |
Signature Verification
If you configure a secret when creating the webhook, every delivery includes an X-Webhook-Signature header:
X-Webhook-Signature: sha256=a1b2c3d4e5f6...The signature is computed as HMAC-SHA256(JSON.stringify(payload), secret) in hex format. Use constant-time comparison to prevent timing attacks.
Event Types
| Event | Description |
|---|---|
message.received | New email arrived in one of your inboxes |
inbox.created | New inbox was created via the API |
inbox.expired | Inbox expired and was cleaned up |
Webhooks are automatically disabled after 5 consecutive delivery failures. Re-enable via the update endpoint.
Webhook deliveries have a 10-second timeout. Ensure your endpoint responds quickly.
Maximum 10 webhooks per account. Secret must be 16-256 characters.
Response 200
[
{
"id": "wh_Kp9xMn2qLr4vTt7bYw3cZ",
"url": "https://yourapp.com/webhooks/destroy",
"events": ["message.received", "inbox.expired"],
"active": true,
"failureCount": 0,
"lastTriggeredAt": "2025-01-29T11:30:00.000Z",
"createdAt": "2025-01-29T12:00:00.000Z"
}
]Rate Limits
Code Examples
curl https://destroy.network/api/user-webhooks \
-H "Authorization: Bearer sk_live_your_api_key"/api/user-webhooksCreate Webhook
Register a new webhook endpoint to receive event notifications.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | HTTPS URL to receive webhook events (must be publicly accessible) |
events | string[] | Yes | Event types to subscribe to: message.received, inbox.created, inbox.expired |
secret | string | No | Secret for HMAC-SHA256 signature verification (16-256 characters) |
{
"url": "https://yourapp.com/webhooks/destroy",
"events": ["message.received", "inbox.created"],
"secret": "your-secret-min-16-chars"
}Response 201
{
"id": "wh_Kp9xMn2qLr4vTt7bYw3cZ",
"url": "https://yourapp.com/webhooks/destroy",
"events": ["message.received", "inbox.created"],
"active": true,
"createdAt": "2025-01-29T12:00:00.000Z"
}Errors
| Status | Message |
|---|---|
| 400 | Invalid URL (must be HTTPS) or events |
| 400 | INVALID_WEBHOOK_URL - URL points at loopback, private network, link-local, or other unsafe address |
| 400 | Webhook URL already registered |
| 400 | Maximum 10 webhooks allowed |
| 401 | Unauthorized |
| 403 | Webhooks require Pro or Business plan |
| 429 | RESOURCE_LIMIT_EXCEEDED - more than 10 webhooks created in the last hour |
Rate Limits
Code Examples
curl -X POST https://destroy.network/api/user-webhooks \
-H "Authorization: Bearer sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/webhooks/destroy",
"events": ["message.received", "inbox.created"],
"secret": "your-secret-min-16-chars"
}'Webhooks require Pro or Business plan.
URL must use HTTPS and be publicly accessible.
URLs that point at loopback, private networks, link-local cloud metadata, or local IPv6 ranges are rejected.
Webhook deliveries do not follow redirects, so a 302 response cannot be used to reach an internal target.
Webhook deliveries are dispatched with a per-trigger concurrency cap of 3, so a slow endpoint can't tie up the platform.
Maximum 10 webhooks per account, with a per-account creation cap of 10 per hour.
Secret must be 16-256 characters if provided.
/api/user-webhooks/{id}Get Webhook
Get details for a specific webhook including failure information.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Webhook ID |
Response 200
{
"id": "wh_Kp9xMn2qLr4vTt7bYw3cZ",
"url": "https://yourapp.com/webhooks/destroy",
"events": ["message.received", "inbox.created"],
"active": true,
"failureCount": 0,
"lastTriggeredAt": "2025-01-29T11:30:00.000Z",
"lastFailureAt": null,
"lastFailureReason": null,
"createdAt": "2025-01-29T12:00:00.000Z"
}Errors
| Status | Message |
|---|---|
| 404 | Webhook not found |
Rate Limits
Code Examples
curl https://destroy.network/api/user-webhooks/wh_Kp9xMn2qLr4vTt7bYw3cZ \
-H "Authorization: Bearer sk_live_your_api_key"/api/user-webhooks/{id}Update Webhook
Update a webhook's URL, events, secret, or active status. Re-enabling a webhook resets its failure counter.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Webhook ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
url | string | No | New HTTPS URL |
events | string[] | No | New event subscriptions |
secret | string | null | No | New secret (or null to remove) |
active | boolean | No | Enable or disable the webhook |
{
"active": true,
"events": ["message.received", "inbox.created", "inbox.expired"]
}Response 200
{
"success": true
}Errors
| Status | Message |
|---|---|
| 404 | Webhook not found |
Rate Limits
Code Examples
curl -X PATCH https://destroy.network/api/user-webhooks/wh_Kp9xMn2qLr4vTt7bYw3cZ \
-H "Authorization: Bearer sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"active": true}'Setting active: true resets the failure counter to 0.
Set secret to null to remove signature verification.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Webhook ID |
Response 200
{
"success": true
}Errors
| Status | Message |
|---|---|
| 404 | Webhook not found |
Rate Limits
Code Examples
curl -X DELETE https://destroy.network/api/user-webhooks/wh_Kp9xMn2qLr4vTt7bYw3cZ \
-H "Authorization: Bearer sk_live_your_api_key"/api/user-webhooks/{id}/testTest Webhook
Send a test event to verify your webhook endpoint is working correctly.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Webhook ID |
Response 200
{
"success": true,
"responseStatus": 200,
"responseBody": "OK",
"durationMs": 245
}Errors
| Status | Message |
|---|---|
| 404 | Webhook not found |
Rate Limits
Code Examples
curl -X POST https://destroy.network/api/user-webhooks/wh_Kp9xMn2qLr4vTt7bYw3cZ/test \
-H "Authorization: Bearer sk_live_your_api_key"Sends a test event with event type 'test'.
Does not affect failure count or trigger status.
Response body is truncated to 500 characters.
/your-server/webhookVerify Webhook Signature
When you configure a secret, verify the X-Webhook-Signature header to ensure the request came from destroy.network.The signature is computed as: sha256=HMAC-SHA256(payload, secret)Important: Always use constant-time comparison to prevent timing attacks.
Response 200
OKCode Examples
# Test payload example sent to your server:
# Headers:
# X-Webhook-Signature: sha256=5d41402abc4b2a76b9719d911017c592
# X-Webhook-Event: message.received
# X-Webhook-ID: wh_Kp9xMn2qLr4vTt7bYw3cZ
# X-Delivery-ID: del_unique123Use crypto.timingSafeEqual() or equivalent for comparison.
The payload is the raw JSON body as a string.
Reject requests with invalid or missing signatures.
