Webhooks
Webhooks are the core of Notifs. They allow you to send notifications to multiple channels with a single API call. This guide covers everything you need to know about creating, configuring, and using webhooks.
What are Webhooks?
A webhook in Notifs is a notification endpoint that you can trigger via our API or SDK. When you send data to a webhook, Notifs automatically delivers it to all configured channels (Email, Slack, SMS, Discord, etc.).
Key Concepts
- Webhook ID: Unique identifier for your webhook (e.g.,
webhook_abc123) - Channels: Delivery destinations (Email, Slack, SMS, etc.)
- Payload: The data you send with each webhook request
- Template: Optional message template for formatting notifications
Creating a Webhook
Via Dashboard
-
Navigate to Webhooks in your dashboard
-
Click Create Webhook
-
Configure your webhook:
- Name: Descriptive name (e.g., "Payment Success")
- Channels: Select delivery channels
- Template: Optional message template
- Secret: Auto-generated signing secret
-
Save and copy the Webhook ID
Via API
import { Notifs } from '@notifs/sdk'
const notifs = new Notifs({
apiKey: process.env.NOTIFS_API_KEY
})
const webhook = await notifs.webhooks.create({
name: 'Payment Success',
channels: ['email', 'slack'],
template: {
email: {
subject: 'Payment Received - {{amount}}',
body: 'Thank you {{user}}! Your payment of {{amount}} has been received.'
},
slack: {
text: 'New payment: {{amount}} from {{user}}'
}
}
})
console.log(webhook.id) // Use this to send webhooks
console.log(webhook.secret) // Use this to verify webhook signatures
Configuring Channels
Each webhook can deliver to multiple channels simultaneously. Configure each channel with the appropriate credentials and settings.
Configure your email provider (Mailgun, SendGrid, AWS SES, etc.):
await notifs.channels.configure('email', {
provider: 'mailgun',
apiKey: process.env.MAILGUN_API_KEY,
domain: 'mail.yourapp.com',
fromEmail: 'notifications@yourapp.com',
fromName: 'Your App'
})
Slack
Add Slack integration via webhook URL or OAuth:
await notifs.channels.configure('slack', {
webhookUrl: process.env.SLACK_WEBHOOK_URL,
channel: '#notifications',
username: 'Notifs Bot',
iconEmoji: ':bell:'
})
SMS
Configure Twilio for SMS delivery:
await notifs.channels.configure('sms', {
provider: 'twilio',
accountSid: process.env.TWILIO_ACCOUNT_SID,
authToken: process.env.TWILIO_AUTH_TOKEN,
fromNumber: '+1234567890'
})
Discord
Add Discord via webhook URL:
await notifs.channels.configure('discord', {
webhookUrl: process.env.DISCORD_WEBHOOK_URL,
username: 'Notifs Bot',
avatarUrl: 'https://yourapp.com/avatar.png'
})
Sending Webhooks
Basic Send
await notifs.webhooks.send('webhook_abc123', {
user: 'john@example.com',
event: 'payment_success',
amount: '$99.00'
})
With Idempotency
Prevent duplicate sends with idempotency keys:
await notifs.webhooks.send('webhook_abc123', {
user: 'john@example.com',
event: 'payment_success',
amount: '$99.00'
}, {
idempotencyKey: `payment_${paymentId}`
})
If you send the same idempotency key within 24 hours, Notifs returns the cached response without sending duplicate notifications.
With Metadata
Attach metadata for tracking and debugging:
await notifs.webhooks.send('webhook_abc123', {
user: 'john@example.com',
amount: '$99.00'
}, {
metadata: {
userId: 'user_456',
invoiceId: 'inv_789',
environment: 'production'
}
})
Webhook Templates
Templates allow you to format messages for each channel using variables from your payload.
Template Syntax
Use double curly braces for variables: {{variableName}}
Example Templates
Email Template:
{
subject: 'Order #{{orderId}} Confirmed',
body: `
Hi {{customerName}},
Your order #{{orderId}} has been confirmed!
Total: {{total}}
Estimated delivery: {{deliveryDate}}
Track your order: {{trackingUrl}}
`
}
Slack Template:
{
text: ':white_check_mark: Order #{{orderId}} confirmed',
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: '*Order Confirmed*\nOrder #{{orderId}} for {{customerName}}'
}
},
{
type: 'section',
fields: [
{ type: 'mrkdwn', text: '*Total:*\n{{total}}' },
{ type: 'mrkdwn', text: '*Delivery:*\n{{deliveryDate}}' }
]
}
]
}
Webhook Retries
Notifs automatically retries failed webhook deliveries with exponential backoff:
- Retry 1: After 1 second
- Retry 2: After 2 seconds
- Retry 3: After 4 seconds
- Retry 4: After 8 seconds
- Retry 5: After 16 seconds
After 5 failed attempts, the webhook is marked as failed and you'll receive an alert.
Manual Retry
Retry a failed webhook manually:
await notifs.webhooks.retry('log_xyz789')
Webhook Logs
View webhook delivery logs in your dashboard or via API:
const logs = await notifs.logs.list({
webhookId: 'webhook_abc123',
limit: 50
})
for (const log of logs.data) {
console.log(`${log.timestamp}: ${log.status}`)
if (log.error) {
console.error(`Error: ${log.error}`)
}
}
Log Retention
- Free Tier: 7 days
- Pro Tier: 30 days
- Enterprise: Custom retention
Rate Limits
Webhook sending is subject to rate limits based on your plan:
| Plan | Rate Limit | Monthly Quota | |------|------------|---------------| | Free | 10/second | 1,000 webhooks | | Pro | 100/second | 100,000 webhooks | | Enterprise | Custom | Unlimited |
Webhook Security
Signature Verification
Every webhook request includes an HMAC-SHA256 signature in the X-Notifs-Signature header. Always verify this signature to ensure requests are genuine.
See the Security documentation for implementation details.
Secret Rotation
Rotate webhook secrets regularly:
const webhook = await notifs.webhooks.rotateSecret('webhook_abc123')
console.log(webhook.secret) // New secret
Important: Update your verification code with the new secret before rotating to prevent downtime.
Testing Webhooks
Test Mode
Use test mode to send webhooks without actually delivering them:
await notifs.webhooks.send('webhook_abc123', {
user: 'test@example.com'
}, {
testMode: true
})
Test mode webhooks appear in logs but aren't delivered to channels.
Webhook Inspector
View real-time webhook requests in the dashboard inspector:
- Go to Webhooks → Inspector
- Select your webhook
- See all incoming requests and delivery status in real-time
Common Patterns
User Notifications
async function notifyUser(userId: string, event: string, data: any) {
await notifs.webhooks.send('user_notifications', {
userId,
event,
...data
}, {
idempotencyKey: `${userId}_${event}_${Date.now()}`,
metadata: { userId, event }
})
}
// Usage
await notifyUser('user_123', 'password_changed', {
email: 'user@example.com',
timestamp: new Date().toISOString()
})
System Alerts
async function sendAlert(severity: string, message: string) {
await notifs.webhooks.send('system_alerts', {
severity,
message,
timestamp: new Date().toISOString(),
hostname: process.env.HOSTNAME
}, {
metadata: { severity, alertType: 'system' }
})
}
// Usage
await sendAlert('critical', 'Database connection pool exhausted')
Batch Notifications
async function sendBatchNotifications(users: User[], event: string) {
const promises = users.map(user =>
notifs.webhooks.send('batch_notifications', {
userId: user.id,
email: user.email,
event,
timestamp: new Date().toISOString()
}, {
idempotencyKey: `batch_${event}_${user.id}`,
metadata: { userId: user.id, batchId: 'batch_123' }
})
)
await Promise.all(promises)
}
Best Practices
- Use Idempotency Keys - Always provide idempotency keys for important operations
- Include Metadata - Add metadata for easier debugging and tracking
- Verify Signatures - Always verify webhook signatures in production
- Handle Failures - Implement proper error handling and retry logic
- Monitor Logs - Regularly check webhook logs for failed deliveries
- Test Thoroughly - Use test mode to verify webhook behavior before going live
- Rotate Secrets - Rotate webhook secrets periodically for security
Troubleshooting
Webhook Not Delivered
- Check webhook logs for error messages
- Verify channel credentials are correct
- Ensure rate limits haven't been exceeded
- Check that the webhook is active
Slow Delivery
- Check rate limits - you may be hitting throttling
- Verify channel provider status (e.g., Slack, Mailgun)
- Contact support for Enterprise plan optimization
Duplicate Deliveries
- Ensure you're using idempotency keys
- Check for retry logic in your code
- Review webhook logs for duplicate requests
Next Steps
- Learn about Security Best Practices
- Explore the SDK Reference
- Check out API Reference for REST API details
- Review Examples for common use cases