Setting up channels (Slack, PagerDuty, Teams, Email, Webhook)
Each notification channel needs a value from the destination system. This page covers how to get that value and which ObserveKit config field it goes in. Add channels in Settings → Notification Channels (see Notification channels).
Slack
- In Slack, create an Incoming Webhook (Slack app → Incoming Webhooks → Add New Webhook to Workspace → pick the channel → Allow).
- Copy the webhook URL (
https://hooks.slack.com/services/…). - In ObserveKit: channel type Slack, set
webhook_urlto that URL.
Optional: timeout_seconds (default 10).
Microsoft Teams
- In the target Teams channel, add an Incoming Webhook connector (channel … → Connectors / Workflows → Incoming Webhook), name it, and Create.
- Copy the generated URL.
- In ObserveKit: channel type Teams, set
webhook_url. (Notifications render as Adaptive Cards.)
PagerDuty
- In PagerDuty, open the Service you want to page → Integrations → add an Events API v2 integration.
- Copy the Integration Key.
- In ObserveKit: channel type PagerDuty, set
routing_keyto that Integration Key.
> The field is `routing_key` (the Events API v2 integration key) — not integration_key. ObserveKit posts to events.pagerduty.com/v2/enqueue; a success is HTTP 202.
Email (SMTP)
Channel type Email. Config fields:
| Field | Required | Notes |
|---|---|---|
smtp_host | yes | e.g. smtp.gmail.com |
smtp_port | yes | e.g. 587 |
smtp_username | no | auth username |
smtp_password | no | auth password / app password / API key |
from | yes | sender address |
to | yes | recipients, comma-separated |
use_tls | no | default true (STARTTLS) |
Common providers:
- Gmail / Google Workspace:
smtp.gmail.com:587,use_tls: true, username = the address, password = an App Password (not your login password). - Microsoft 365:
smtp.office365.com:587,use_tls: true. - SendGrid:
smtp.sendgrid.net:587, username =apikey(literally), password = your SendGrid API key.
Webhook (custom receiver)
Channel type Webhook. Fields: webhook_url (required), secret (optional, enables signing), header_<Name> (optional, forwards a custom header), timeout_seconds (default 10).
Payload
ObserveKit POSTs JSON:
{
"event_type": "IncidentCreated",
"incident_id": "...",
"title": "High error rate on payments",
"severity": "critical",
"status": "open",
"dedup_key": "...",
"auto_action": false,
"timestamp": "2026-07-09T12:00:00Z",
"actor_id": "...",
"summary": "...",
"labels": { "service": "payments", "cluster": "prod" },
"deep_link": "https://observekit.expeed.com/incidents/<id>"
}(auto_action is a raw boolean; timestamp is RFC3339; labels is an object.)
Verifying the signature (HMAC)
If you set a secret, ObserveKit signs each request:
- Header: `X-ObserveKit-Signature`
- Value: `sha256=<hex>` where
<hex>is HMAC-SHA256 of the raw request body using yoursecret.
Verify by recomputing over the exact bytes you received (don't re-serialize the JSON) and comparing:
expected = "sha256=" + hex(hmac_sha256(secret, raw_body)) constant_time_equal(expected, X-ObserveKit-Signature)
No secret → no signature header is sent.
After setup
Use Send test on the channel to confirm delivery before wiring it into a routing policy. Not getting notifications? See Troubleshooting.