Webhooks
Receive real-time notifications when email events occur. Grosend retries failed deliveries up to 5 times with exponential backoff.
Create a webhook
curl -X POST https://api.grosend.com/api/v1/webhooks \
-H "Authorization: Bearer sv_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhook",
"events": ["email.delivered", "email.bounced", "email.opened", "email.clicked"]
}'
Response
{
"id": "webhook-uuid",
"url": "https://your-server.com/webhook",
"events": ["email.delivered", "email.bounced", "email.opened", "email.clicked"],
"secret": "uuid-generated-secret",
"status": "active",
"createdAt": "2025-01-15T10:30:00Z"
}
Store the secret securely — it is used to verify webhook signatures via HMAC-SHA256.
Event types
email.deliveredEmail was delivered to the recipient inbox
email.openedRecipient opened the email (tracking pixel)
email.clickedRecipient clicked a link (click tracking)
email.bouncedEmail bounced (hard or soft)
email.complaintRecipient marked as spam
Webhook payload
{
"id": "evt_1234567890",
"type": "email.delivered",
"created_at": "2025-01-15T10:35:00Z",
"data": {
"email_id": "email-uuid",
"from": "hello@yourdomain.com",
"to": "user@example.com",
"subject": "Welcome to Grosend"
}
}
Click events include additional fields:
{
"type": "email.clicked",
"data": {
"email_id": "email-uuid",
"to": "user@example.com",
"link": "https://yourdomain.com/pricing",
"user_agent": "Mozilla/5.0...",
"ip_address": "192.168.1.1"
}
}
Verifying signatures
Each webhook delivery includes an X-Grosend-Signatureheader with an HMAC-SHA256 signature of the request body using your webhook's signing secret.
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return signature === `sha256=${expected}`;
}
Retry schedule
If your endpoint returns a non-2xx status code, Grosend retries with exponential backoff:
1st retry1 minute
2nd retry5 minutes
3rd retry30 minutes
4th retry2 hours
5th retry8 hours
After 5 failed attempts, the webhook is marked as "failed" and will not receive further events. You must recreate it.
Manage webhooks
# List webhooks
curl https://api.grosend.com/api/v1/webhooks \
-H "Authorization: Bearer sv_live_..."
# Update a webhook
curl -X PUT https://api.grosend.com/api/v1/webhooks/{webhook-id} \
-H "Authorization: Bearer sv_live_..." \
-H "Content-Type: application/json" \
-d '{"events": ["email.delivered", "email.bounced"]}'
# Delete a webhook
curl -X DELETE https://api.grosend.com/api/v1/webhooks/{webhook-id} \
-H "Authorization: Bearer sv_live_..."