Notification Channels
Notification channels let you receive real-time alerts when webhook deliveries fail, routes recover, or circuit breakers trip. Send notifications to Slack, Microsoft Teams, Discord, PagerDuty, email, or custom webhooks.
Warning
Paid plans only
Notification channels are available on Starter, Pro and Business. On the Free plan every
/api/notification-channels request returns 403.
Channel Types
| Type | Description | Best For |
|---|---|---|
| Slack | Send Block Kit messages to Slack channels | Team alerts |
| Microsoft Teams | Send Adaptive Cards to Teams channels | Enterprise team alerts |
| Discord | Send embedded messages to Discord channels | Developer/community alerts |
| PagerDuty | Create incidents via Events API v2 | On-call incident management |
| Send emails to multiple recipients | On-call notifications | |
| Webhook | POST to custom HTTP endpoints | Integration with monitoring tools |
Creating Channels
Slack Channel
curl -X POST "https://api.hookbase.app/api/notification-channels" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "Ops Slack",
"type": "slack",
"config": {
"webhookUrl": "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"
}
}'To get a Slack webhook URL:
- Go to your Slack workspace settings
- Navigate to Apps → Incoming Webhooks
- Create a new webhook and select a channel
Email Channel
curl -X POST "https://api.hookbase.app/api/notification-channels" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "On-Call Team",
"type": "email",
"config": {
"emails": ["oncall@example.com", "team@example.com"]
}
}'Custom Webhook Channel
curl -X POST "https://api.hookbase.app/api/notification-channels" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "Monitoring Webhook",
"type": "webhook",
"config": {
"url": "https://your-service.com/alerts",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer whr_your_api_key"
},
"secret": "optional-signing-secret"
}
}'The signing key is secret (hmacSecret is accepted as an alias and stored as secret). The
secret is never returned: responses show hasSecret: true instead. On update, leave the key out to
keep the current secret, or send null or "" to remove it.
Config options:
| Field | Required | Description |
|---|---|---|
url | Yes | Must start with http |
method | No | POST (default) or PUT |
headers | No | Merged over Content-Type: application/json |
secret | No | HMAC-SHA256 signing key; see HMAC Signing |
Microsoft Teams Channel
curl -X POST "https://api.hookbase.app/api/notification-channels" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "DevOps Team",
"type": "teams",
"config": {
"webhookUrl": "https://yourtenant.webhook.office.com/webhookb2/..."
}
}'The URL must contain .webhook.office.com/. A legacy https://outlook.office.com/webhook/...
Office 365 connector URL is rejected with 400.
To get a Microsoft Teams webhook URL:
- Open your Teams channel
- Click the ... menu → Workflows (or Connectors on older tenants)
- Choose Post to a channel when a webhook request is received
- Name it and click Create
- Copy the webhook URL — it is on
*.webhook.office.com
Teams notifications use Adaptive Cards with color-coded status, structured data fields, and a link to your Hookbase dashboard.
PagerDuty Channel
curl -X POST "https://api.hookbase.app/api/notification-channels" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "On-Call Paging",
"type": "pagerduty",
"config": {
"routingKey": "R02ABCDEFGHIJKLMNOPQRSTUVWXYZ012",
"severity": "error",
"customService": "Hookbase Webhooks"
}
}'Config options:
| Field | Required | Description |
|---|---|---|
routingKey | Yes | Integration key from PagerDuty, exactly 32 characters. Any other length is rejected with 400 |
severity | No | Default severity: critical, error, warning, or info |
customService | No | Custom service name (defaults to "Hookbase") |
To get a PagerDuty integration key:
- Go to Services → Select or create a service
- Click Integrations → Add Integration
- Select Events API v2
- Copy the Integration Key (32 characters)
PagerDuty Features
Automatic Incident Management:
- Deduplication: Incidents are deduplicated by route/cron ID, preventing duplicate alerts
- Auto-Resolve: When a route recovers, the incident is automatically resolved
- Severity Mapping: Circuit breaker events use "critical" severity, failures use "error"
| Hookbase Event | PagerDuty Action | Severity |
|---|---|---|
| Delivery Failure | Trigger | error (configurable) |
| Circuit Opened | Trigger | critical |
| Cron Failure | Trigger | error (configurable) |
| Recovery | Resolve | info |
| Circuit Closed | Resolve | info |
Discord Channel
curl -X POST "https://api.hookbase.app/api/notification-channels" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "Dev Alerts",
"type": "discord",
"config": {
"webhookUrl": "https://discord.com/api/webhooks/...",
"username": "Hookbase Bot",
"avatarUrl": "https://hookbase.app/logo.png"
}
}'Config options:
| Field | Required | Description |
|---|---|---|
webhookUrl | Yes | Discord webhook URL |
username | No | Bot display name (defaults to webhook name) |
avatarUrl | No | Bot avatar image URL |
To create a Discord webhook:
- Go to your Discord channel
- Click the gear icon → Integrations → Webhooks
- Click New Webhook
- Name it and copy the Webhook URL
Discord notifications use embedded messages with color-coded status (red for failures, green for success), inline fields, and timestamps.
Tip
Rate Limiting
Discord webhooks have rate limits (~30 requests/minute). For high-volume alerting, consider using PagerDuty or a custom webhook with batching.
Linking Channels to Routes
Channels must be linked to specific routes to receive notifications:
curl -X POST "https://api.hookbase.app/api/notification-channels/{channelId}/routes" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"routeId": "{routeId}",
"notifyOnFailure": true,
"notifyOnRecovery": true,
"notifyOnCircuitOpen": true
}'Notification Triggers
| Trigger | Default | Description |
|---|---|---|
notifyOnFailure | true | When the route's consecutive-failure count reaches its failureThreshold (default 3) |
notifyOnSuccess | false | On every successful delivery. Noisy; for smoke-testing a route |
notifyOnRecovery | true | When the route succeeds again after having reached its failureThreshold |
notifyOnCircuitOpen | true | When the circuit breaker trips open |
Failure alerts fire on the crossing rather than on every failure — the count has to land exactly
on failureThreshold, so a route that goes on failing past it alerts once, not repeatedly.
Recovery mirrors that: a success only alerts if the count had reached the threshold first, so a
brief blip that self-heals is silent on both sides.
Linking the same route to the same channel twice returns 400.
Managing Channels via Dashboard
- Navigate to Settings → Notifications
- Click Add Channel
- Select the channel type
- Configure the channel settings
- Click Create
Linking Routes in Dashboard
- Find your channel in the list
- Click the expand arrow to see linked routes
- Click Link Route
- Select a route and choose notification triggers
- Click Link Route
Testing Channels
Send a test notification to verify your configuration:
Via API
curl -X POST "https://api.hookbase.app/api/notification-channels/{channelId}/test" \
-H "Authorization: Bearer {token}"Via Dashboard
- Navigate to Settings → Notifications
- Find the channel
- Click the Test button
Notification Payloads
Slack Message Format
Block Kit blocks — a header, a field section, the error, a dashboard button and a context footer:
{
"blocks": [
{
"type": "header",
"text": { "type": "plain_text", "text": "🔴 Route Delivery Failed", "emoji": true }
},
{
"type": "section",
"fields": [
{ "type": "mrkdwn", "text": "*Route:*\nGitHub → Slack" },
{ "type": "mrkdwn", "text": "*Source:*\nGitHub" },
{ "type": "mrkdwn", "text": "*Destination:*\nSlack relay" },
{ "type": "mrkdwn", "text": "*Failures:*\n5 consecutive" }
]
},
{
"type": "section",
"text": { "type": "mrkdwn", "text": "*Error:*\n```Connection timeout```" }
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": { "type": "plain_text", "text": "View in Dashboard" },
"url": "https://www.hookbase.app/dashboard"
}
]
},
{
"type": "context",
"elements": [
{ "type": "mrkdwn", "text": "Sent from *Hookbase* • 2024-01-15T10:30:00.000Z" }
]
}
]
}Custom Webhook Payload
The event type and a timestamp at the top level, with the event itself under data:
{
"type": "route_failure",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"type": "route_failure",
"routeId": "route_123",
"routeName": "GitHub → Slack",
"sourceName": "GitHub",
"destinationName": "Slack relay",
"destinationUrl": "https://example.com/webhook",
"errorMessage": "Connection timeout",
"consecutiveFailures": 5,
"eventId": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbb0002",
"dashboardUrl": "https://www.hookbase.app/dashboard"
}
}type is one of route_failure, route_success, route_recovery, circuit_opened,
circuit_recovery, cron_failure, cron_success, anomaly_volume_spike, anomaly_volume_drop
or schema_drift_detected. The keys under data depend on it.
Email Format
Subject: [Hookbase] Delivery Failures: GitHub → Slack
Body includes route details, failure count, last error, and links to the dashboard.
Teams Adaptive Card Format
{
"type": "message",
"attachments": [{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {
"type": "AdaptiveCard",
"version": "1.4",
"body": [
{
"type": "TextBlock",
"text": "Route Delivery Failed",
"size": "Large",
"weight": "Bolder",
"color": "attention"
},
{
"type": "FactSet",
"facts": [
{ "title": "Route", "value": "GitHub → Slack" },
{ "title": "Destination", "value": "slack-webhook" },
{ "title": "Consecutive Failures", "value": "5" }
]
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "View in Dashboard",
"url": "https://app.hookbase.app/..."
}
]
}
}]
}PagerDuty Events API v2 Format
{
"routing_key": "your-routing-key",
"event_action": "trigger",
"dedup_key": "hookbase-route-route_123",
"payload": {
"summary": "Route \"GitHub → Slack\" delivery failed: Connection timeout",
"source": "slack-webhook",
"severity": "error",
"timestamp": "2024-01-15T10:30:00Z",
"component": "Hookbase",
"group": "webhook-delivery",
"class": "route_failure",
"custom_details": {
"route": "GitHub → Slack",
"source": "GitHub",
"destination": "slack-webhook",
"consecutive_failures": "5",
"dashboard_url": "https://www.hookbase.app/dashboard"
}
},
"links": [
{
"href": "https://www.hookbase.app/dashboard",
"text": "View in Hookbase Dashboard"
}
]
}Discord Embed Format
{
"embeds": [{
"title": "Route Delivery Failed",
"color": 15680580,
"fields": [
{ "name": "Route", "value": "GitHub → Slack", "inline": true },
{ "name": "Source", "value": "GitHub", "inline": true },
{ "name": "Failures", "value": "5 consecutive", "inline": true }
],
"url": "https://app.hookbase.app/...",
"footer": { "text": "Hookbase" },
"timestamp": "2024-01-15T10:30:00.000Z"
}],
"username": "Hookbase Bot"
}HMAC Signing (Webhook Channels)
For webhook channels, you can configure HMAC signing for security:
curl -X POST "https://api.hookbase.app/api/notification-channels" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "Secure Webhook",
"type": "webhook",
"config": {
"url": "https://your-service.com/alerts",
"method": "POST",
"secret": "your-secret-key"
}
}'The header is X-Hookbase-Signature, and its value is sha256= followed by the hex-encoded
HMAC-SHA256 of the raw request body. Strip the prefix before comparing:
const crypto = require('crypto');
function verifySignature(rawBody, header, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
// The header is "sha256=<hex>", not the bare digest.
const received = Buffer.from(String(header).replace(/^sha256=/, ''), 'hex');
const digest = Buffer.from(expected, 'hex');
return received.length === digest.length && crypto.timingSafeEqual(received, digest);
}Sign the bytes you received, not a re-serialized object: JSON.parse followed by
JSON.stringify can reorder keys and change the digest.
Best Practices
- Set up before issues occur: Don't wait for failures to configure notifications
- Use multiple channels: Send to both Slack and email for critical routes
- Configure recovery alerts: Know when issues are resolved, not just when they start
- Test regularly: Verify channels work before you need them
- Don't over-notify: Choose appropriate triggers to avoid alert fatigue
Managing Linked Routes
View linked routes
curl -X GET "https://api.hookbase.app/api/notification-channels/{channelId}/routes" \
-H "Authorization: Bearer {token}"Update link settings
curl -X PATCH "https://api.hookbase.app/api/notification-channels/{channelId}/routes/{routeId}" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"notifyOnFailure": true,
"notifyOnRecovery": false,
"notifyOnCircuitOpen": true
}'Unlink a route
curl -X DELETE "https://api.hookbase.app/api/notification-channels/{channelId}/routes/{routeId}" \
-H "Authorization: Bearer {token}"