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

  1. In Slack, create an Incoming Webhook (Slack app → Incoming WebhooksAdd New Webhook to Workspace → pick the channel → Allow).
  2. Copy the webhook URL (https://hooks.slack.com/services/…).
  3. In ObserveKit: channel type Slack, set webhook_url to that URL.

Optional: timeout_seconds (default 10).

Microsoft Teams

  1. In the target Teams channel, add an Incoming Webhook connector (channel … → Connectors / Workflows → Incoming Webhook), name it, and Create.
  2. Copy the generated URL.
  3. In ObserveKit: channel type Teams, set webhook_url. (Notifications render as Adaptive Cards.)

PagerDuty

  1. In PagerDuty, open the Service you want to page → Integrations → add an Events API v2 integration.
  2. Copy the Integration Key.
  3. In ObserveKit: channel type PagerDuty, set routing_key to 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:

FieldRequiredNotes
smtp_hostyese.g. smtp.gmail.com
smtp_portyese.g. 587
smtp_usernamenoauth username
smtp_passwordnoauth password / app password / API key
fromyessender address
toyesrecipients, comma-separated
use_tlsnodefault 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 your secret.

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.