Webhooks API
Configure webhooks to receive real-time notifications when emails arrive.
How Webhooks Work
When an email is received, Mailhooks will send a POST request to your configured webhook URL with the email data. This allows you to process emails in real-time without polling the API.
Email arrives at your domain
POST request sent to your URL
Your app handles the data
Create Webhook
Create a new webhook endpoint.
POST undefined/api/v1/webhooksRequest Body
{
"url": "https://your-app.com/webhook/mailhooks",
"events": ["email.received"],
"description": "Production webhook for email processing"
}Example Request
curl -X POST undefined/api/v1/webhooks \
-H "x-api-key: mh_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhook/mailhooks",
"events": ["email.received"]
}'Webhook Endpoints
List Webhooks
Get all configured webhooks for your account.
GET undefined/api/v1/webhooksUpdate Webhook
Update an existing webhook configuration.
PUT undefined/api/v1/webhooks/:idDelete Webhook
Remove a webhook endpoint.
DELETE undefined/api/v1/webhooks/:idWebhook Payload
When an email is received, Mailhooks sends the following payload to your webhook. If you use custom storage (BYOB), additional fields like storagePath are included so you can fetch the email and attachments from your bucket.
{
"id": "em_1234567890",
"from": "[email protected]",
"to": ["[email protected]"],
"subject": "Hello from Mailhooks",
"body": "Plain text content of the email...",
"html": "HTML content...storagePath fields on both the payload and attachments are only present when usesCustomStorage is true. Use these paths to fetch the raw EML file and attachments from your bucket.Payload Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique email ID |
from | string | Sender email address |
to | string[] | Recipient email addresses |
subject | string | Email subject line |
body | string | Plain text content |
html | string? | HTML content (if available) |
receivedAt | string | ISO 8601 timestamp when email was received |
headers | object | All email headers as key-value pairs |
attachments | array | List of attachments with id, filename, contentType, size, and storagePath (for custom storage) |
spfResult | string? | SPF authentication result |
dkimResult | string? | DKIM authentication result |
dmarcResult | string? | DMARC authentication result |
authSummary | string? | Summary of all authentication results |
usesCustomStorage | boolean | Whether email is stored in your custom S3 bucket (BYOB) |
storagePath | string? | Storage path for the EML file (only present when usesCustomStorage is true) |
storageConfig | object? | Storage provider details with provider (S3, AZURE_BLOB, GCS) and bucket name (only present when usesCustomStorage is true) |
HTTP Headers
Mailhooks includes the following headers with each webhook request:
| Header | Description |
|---|---|
Content-Type | application/json |
X-Webhook-Signature | HMAC-SHA256 signature of the payload |
X-Email-ID | The email ID for reference |
Webhook Security
Mailhooks signs all webhook requests to verify they're coming from us. The signature is included in the X-Webhook-Signature header.
Verifying Webhook Signatures
// Node.js example
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const hash = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return hash === signature;
}
// In your webhook handler
app.post('/webhook/mailhooks', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const isValid = verifyWebhookSignature(
req.body,
signature,
process.env.MAILHOOKS_WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Process the webhook...
});Retry Policy
If your webhook endpoint doesn't respond with a 2xx status code, Mailhooks will retry the delivery with exponential backoff:
5 seconds
30 seconds
2 minutes
10 minutes
30 minutes
Webhook Logs
View logs for a specific webhook to debug delivery issues. Each log entry includes the emailId for correlation with the original email.
Use the email ID to track the complete email lifecycle including SMTP reception and spam checks. See the Email Tracking documentation for details.
GET undefined/api/v1/webhooks/:id/logsQuery Parameters
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number (default: 1) |
perPage | integer | Items per page (default: 20) |
status | string | Filter by status: success, failed |
Best Practices
Respond Quickly
Process webhooks asynchronously and return 200 OK immediately
Verify Signatures
Always validate webhook signatures before processing
Handle Duplicates
Use email IDs to prevent processing the same email twice
Monitor Health
Check webhook logs regularly for failed deliveries