Webhooks allow you to receive real-time notifications when events occur in your Level organization. When an event happens, Level will send an HTTP POST request to your configured endpoint with details about the event.
Setting Up Webhooks
Creating a Webhook
- Navigate to Settings → Webhooks in your Level dashboard
- Click Create webhook
- Configure your webhook:
- URL: Your endpoint that will receive webhook requests
- Secret: A secret key used to validate webhook authenticity (recommended)
- Event types: Select which events you want to receive
- Status: Enable/disable the webhook
Managing Webhooks
- View webhook request logs and responses in real-time
- Retry failed webhook deliveries
- Monitor webhook performance and success rates
Event Types
Level supports the following webhook events:
Event Type | Description |
---|---|
alert_active | Triggered when an alert becomes active |
alert_resolved | Triggered when an alert is resolved |
device_created | Triggered when a new device is added |
device_updated | Triggered when a device is modified |
device_deleted | Triggered when a device is removed |
group_created | Triggered when a new group is created |
group_updated | Triggered when a group is modified |
group_deleted | Triggered when a group is removed |
Webhook Payload Structure
All webhook payloads follow this consistent structure:
{
"event_type": "device_created",
"event_id": "550e8400-e29b-41d4-a716-446655440000",
"occurred_at": "2025-03-15T14:30:00.000Z",
"data": {
"id": "123456789",
// and other properties
}
}
Payload Fields
- event_type: The type of event that occurred
- event_id: Unique identifier for this webhook delivery
- occurred_at: ISO 8601 timestamp when the event occurred
- data: Event-specific data containing the affected resource
Securing Webhooks
Level signs webhook payloads using HMAC SHA256 to ensure authenticity.
Signature Verification
Each webhook request includes an X-Level-Signature
header:
X-Level-Signature: sha256=a1b2c3d4e5f6...
To verify the signature:
Node.js Example
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
const receivedSignature = signature.replace('sha256=', '');
return crypto.timingSafeEqual(
Buffer.from(expectedSignature, 'hex'),
Buffer.from(receivedSignature, 'hex')
);
}
Python Example
import hmac
import hashlib
def verify_webhook(payload, signature, secret):
expected_signature = hmac.new(
secret.encode('utf-8'),
payload.encode('utf-8'),
hashlib.sha256
).hexdigest()
received_signature = signature.replace('sha256=', '')
return hmac.compare_digest(expected_signature, received_signature)
Ruby Example
require 'openssl'
def verify_webhook(payload, signature, secret)
expected_signature = OpenSSL::HMAC.hexdigest('SHA256', secret, payload)
received_signature = signature.gsub('sha256=', '')
Rack::Utils.secure_compare(expected_signature, received_signature)
end
Handling Webhook Deliveries
Best Practices
- Respond quickly: Return a 2xx status code within 10 seconds
- Process asynchronously: Queue webhook processing for complex operations
- Validate signatures: Always verify webhook authenticity using the secret
- Handle duplicates: Use the
event_id
to prevent processing duplicate events - Implement idempotency: Ensure your webhook handler can safely process the same event multiple times
Delivery and Retries
- Level delivers webhooks asynchronously using background jobs
- Failed deliveries are automatically retried up to 3 times
- Retry attempts use exponential backoff with jitter (2+ minutes between attempts)
- Only HTTP 2xx responses are considered successful
Example Handler (Express.js)
const express = require('express');
const app = express();
app.use(express.raw({ type: 'application/json' }));
app.post('/webhooks/level', (req, res) => {
const signature = req.headers['x-level-signature'];
const payload = req.body.toString();
// Verify signature
if (!verifyWebhook(payload, signature, process.env.LEVEL_WEBHOOK_SECRET)) {
return res.status(401).send('Unauthorized');
}
const event = JSON.parse(payload);
// Process event asynchronously
processWebhookEvent(event);
// Respond immediately
res.status(200).send('OK');
});
async function processWebhookEvent(event) {
switch (event.event_type) {
case 'alert_active':
await handleAlertActive(event.data);
break;
case 'device_created':
await handleDeviceCreated(event.data);
break;
// Handle other event types...
}
}
Troubleshooting
Viewing Request Logs
Access detailed webhook request logs in Settings → Webhooks → [Your Webhook]:
- Request and response bodies
- HTTP status codes
- Error messages
- Delivery timestamps
Common Issues
- 404/500 errors: Check your endpoint URL and server status
- Timeout errors: Ensure your handler responds within 10 seconds
- Signature validation fails: Verify your secret matches the webhook configuration
- Missing events: Check that the event type is selected in your webhook configuration
Testing Webhooks
- Use webhook testing tools like ngrok for local development
- Check webhook logs for delivery details and responses
- Use the "Re-run request" feature to replay failed deliveries
- Monitor webhook success rates in the dashboard
For additional support, contact our developer support team.