Webhook
Send Seenty alerts as HTTP POST requests to any endpoint with HMAC signature verification.
Generic Webhook
The generic webhook channel lets you send Seenty alert notifications as HTTP POST requests to any URL. This is the most flexible notification option -- use it to integrate with custom dashboards, internal tools, automation platforms (Zapier, Make, n8n), or any service that can receive HTTP requests.
Webhook integration is available on Starter plans and above.
What you get
Each webhook notification is an HTTP POST request containing:
- JSON payload -- Structured event data including event type, resource details, severity, and timestamp.
- HMAC-SHA256 signature -- An optional cryptographic signature in the request header so your endpoint can verify that the request came from Seenty.
- Retry logic -- If your endpoint returns an error (5xx or timeout), Seenty retries the delivery.
Setup
Prepare your endpoint
Set up an HTTP endpoint that can receive POST requests with a JSON body. The endpoint should return a 200 status code to acknowledge receipt.
Add the channel in Seenty
- Go to Integrations > Notification Channels.
- Click Add Channel and select Webhook.
- Enter a name for the channel (e.g., "Internal Dashboard Webhook").
- Enter the Webhook URL -- the full URL of your endpoint (e.g.,
https://api.example.com/seenty-alerts). - Optionally, enter a Signing Secret. If provided, Seenty will include an HMAC-SHA256 signature in the
X-Seenty-Signatureheader of every request. - Click Save.
Test the integration
Click the Test button to send a test payload to your endpoint. Verify that your endpoint receives the request and returns a 200 response.
Assign to monitors or policies
Add the webhook channel to the monitors or escalation policies that should trigger webhook notifications.
Payload format
Every webhook notification sends a JSON payload with the following structure:
{
"event_type": "monitor.down",
"timestamp": "2026-04-29T14:30:00Z",
"organization_id": "org_abc123",
"resource": {
"type": "monitor",
"id": "mon_xyz789",
"name": "API Health Check",
"url": "https://api.example.com/health"
},
"details": {
"status": "down",
"status_code": 503,
"response_time_ms": null,
"region": "us-east-1",
"error": "Connection refused"
},
"severity": "high",
"dashboard_url": "https://app.seenty.com/monitors/mon_xyz789"
}Event types
| Event type | Description |
|---|---|
monitor.down | A monitor detected that the target is unreachable or returning errors. |
monitor.up | A previously failing monitor has recovered. |
ssl.expiring | An SSL certificate is approaching its expiration date. |
incident.created | A new incident was triggered. |
incident.acknowledged | An incident was acknowledged by a responder. |
incident.resolved | An incident was resolved. |
finding.created | A new security finding was detected. |
Signature verification
If you configured a Signing Secret, Seenty includes an X-Seenty-Signature header with every request. This header contains an HMAC-SHA256 hash of the request body, computed using your signing secret.
To verify the signature on your endpoint:
const crypto = require('crypto');
function verifySignature(body, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(body, 'utf-8')
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}Always use constant-time comparison (like timingSafeEqual) when verifying signatures to prevent timing attacks.
Troubleshooting
Webhook not being received?
- Verify the URL is correct and publicly accessible (Seenty cannot reach endpoints behind a firewall or VPN without proper configuration).
- Check that your endpoint returns a
200status code. Non-2xx responses are treated as failures. - Look at your server logs for incoming requests from Seenty's IP addresses.
Signature verification failing?
- Ensure you are computing the HMAC over the raw request body (not a parsed and re-serialized version, which may differ in whitespace or key order).
- Verify the signing secret matches exactly what you configured in Seenty.
- Check that you are comparing the hex-encoded digest, not the raw binary.
Duplicate notifications?
- If your endpoint returns an error or times out, Seenty will retry the delivery. Make your endpoint idempotent by checking the
event_typeandtimestampcombination.