Back to API Overview
Real-time Webhooks
Receive instant notifications when email verifications complete. Push results directly to your systems without polling.
How Webhooks Work
When you enable webhooks, ValidMail will send an HTTP POST request to your specified URL immediately after each verification completes. This allows real-time integration without polling our API.
Setting Up Webhooks
- Go to Dashboard → Settings → Notifications
- Navigate to the "Webhook" tab
- Enable webhooks and enter your endpoint URL
- Optionally add a signing secret for request verification
- Enable "Real-time Verification Results" under Alert Types
- Save your settings
Webhook Payload
Each verification result webhook includes the following payload:
{
"event": "verification.completed",
"timestamp": "2024-01-15T10:30:00.000Z",
"data": {
"email": "user@example.com",
"status": "valid",
"score": 95,
"verdict": "Email verified with high confidence",
"isCatchAll": false,
"checks": {
"syntax": { "valid": true },
"dns": {
"valid": true,
"mxRecords": ["mx1.example.com"]
},
"smtp": {
"valid": true,
"catchAll": false
},
"disposable": false,
"roleBased": false,
"freeProvider": false
},
"typoSuggestion": {
"original": "user@gmial.com",
"suggested": "user@gmail.com",
"confidence": 95,
"reason": "Common domain typo"
},
"responseTimeMs": 234
},
"meta": {
"apiKeyId": "key_abc123",
"organizationId": "org_xyz789"
}
}Field Reference
| Field | Type | Description |
|---|---|---|
| event | string | Always "verification.completed" |
| timestamp | string | ISO 8601 timestamp |
| data.email | string | The verified email address |
| data.status | string | valid | invalid | risky | unknown |
| data.score | number | Deliverability score (0-100) |
| data.isCatchAll | boolean | null | Whether domain accepts all emails |
| data.checks | object | Detailed verification checks |
| meta.apiKeyId | string | ID of the API key used |
Verifying Webhook Signatures
When you configure a signing secret, we sign each webhook request using HMAC-SHA256. The signature is included in the X-ValidMail-Signature header.
Node.js Example
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// Express.js example
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-validmail-signature'];
const payload = req.body.toString();
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(payload);
if (event.event === 'verification.completed') {
console.log('Email verified:', event.data.email, event.data.status);
// Process the verification result
}
res.status(200).send('OK');
});Python Example
import hmac
import hashlib
def verify_webhook_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = 'sha256=' + hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
# Flask example
@app.route('/webhook', methods=['POST'])
def webhook():
signature = request.headers.get('X-ValidMail-Signature')
payload = request.get_data()
if not verify_webhook_signature(payload, signature, WEBHOOK_SECRET):
return 'Invalid signature', 401
event = request.get_json()
if event['event'] == 'verification.completed':
print(f"Email verified: {event['data']['email']} - {event['data']['status']}")
# Process the verification result
return 'OK', 200Delivery & Retry Policy
- Webhooks are delivered within milliseconds of verification completion
- We use a 5-second timeout for webhook delivery
- Failed webhooks are not retried to maintain real-time performance
- Your endpoint should return a 2xx status code to acknowledge receipt
- Webhook delivery does not block the API response
Best Practices
- Always verify signatures - Use the signing secret to validate that webhooks are from ValidMail
- Respond quickly - Return a 200 response immediately and process asynchronously if needed
- Handle duplicates - Use the email and timestamp to deduplicate if your endpoint receives the same event twice
- Use HTTPS - Always use HTTPS endpoints for webhook URLs
- Monitor failures - Set up logging to track webhook delivery issues
Request Headers
Each webhook request includes these headers:
| Header | Description |
|---|---|
| Content-Type | application/json |
| X-ValidMail-Event | verification.completed |
| X-ValidMail-Signature | HMAC-SHA256 signature (if secret configured) |