Navigation
Getting Started
Guides
Integrations
Integrations
Slack
Send incident notifications to Slack via Block Kit: one timeline-style thread per incident, every lifecycle event.
Slack
Yorker posts incident notifications to Slack via an Incoming Webhook. Slack is the timeline channel: by default it receives every lifecycle event, so your channel becomes a running record of the incident.
For the underlying model (lifecycle states, event types, scoped hypothesis), see Incidents.
Set up
- In Slack, create an Incoming Webhook and copy the URL.
- In Yorker, go to Settings > Notification Channels, click Create Channel, pick Slack, and paste the webhook URL.
- The channel is subscribed to incidents by default. Wire it to any alert rule and it will participate in incident dispatch.
Or via the API:
curl -X POST https://yorkermonitoring.com/api/notification-channels \
-H "Authorization: Bearer $YORKER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "ops-channel",
"channel": {
"type": "slack",
"webhookUrl": "https://hooks.slack.com/services/T.../B.../..."
}
}'What gets posted
Slack receives every incident event by default:
openedalert_attachedseverity_changedacknowledgedauto_resolvedclosedreopenednote_added
The opened event uses a rich Block Kit layout: header, severity, affected checks, locations, symptom window, shared failing domains, hypothesis, ruled-out list, and a View in Yorker button. Subsequent events are single-section status lines so the thread reads like a timeline.
Example opened payload:
{
"blocks": [
{ "type": "header", "text": { "type": "plain_text", "text": "๐ด Incident opened โ Checkout API outage" } },
{ "type": "section", "text": { "type": "mrkdwn", "text": "*Severity*: `CRITICAL` ยท *Incident*: <https://yorkermonitoring.com/dashboard/incidents/inc_abc|inc_abc>" } },
{ "type": "section", "fields": [
{ "type": "mrkdwn", "text": "*Affected checks*\nCheckout API" },
{ "type": "mrkdwn", "text": "*Locations*\nloc_us_east_1, loc_eu_west_1" },
{ "type": "mrkdwn", "text": "*Symptom window*\n2026-04-15T09:58:00Z โ ongoing" },
{ "type": "mrkdwn", "text": "*Shared failing domains*\napi.stripe.com" }
]},
{ "type": "section", "text": { "type": "mrkdwn", "text": "*Hypothesis*\nStripe API is returning 503/504; checkout is blocked." } },
{ "type": "section", "text": { "type": "mrkdwn", "text": "*Ruled out*\nโข DNS resolution: NXDOMAIN not observed\nโข TLS: handshake completes" } },
{ "type": "context", "elements": [{ "type": "mrkdwn", "text": "Scope: `external_symptoms_only` โ Yorker measures external symptoms only" }] },
{ "type": "actions", "elements": [{ "type": "button", "text": { "type": "plain_text", "text": "View in Yorker" }, "url": "https://yorkermonitoring.com/dashboard/incidents/inc_abc" }] }
]
}Template overrides
Every event's default payload can be replaced with a Handlebars-rendered Block Kit JSON string. The template renders against the full incident event context.
Edit in the web UI
The fastest way to author overrides is the per-channel template editor. Open Settings > Notification Channels, click Templates next to the Slack channel, and you get:
- A Handlebars editor with JSON syntax highlighting
- A live preview pane that renders your template against one of six canonical fixtures (single HTTP failure, multi-location burst, browser check, MCP, etc.)
- A per-event drop-down so you can author one template per lifecycle event
- A library sidebar with curated starter blocks and end-to-end examples (runbook-style, terse-ack, etc.) that apply with a click
- Compare with saved diff view before you save
- Send test: dispatches the current saved template to the real Slack webhook using the selected fixture (60-second cooldown per channel)
- Reset to default per field: clears the override and falls back to the shipping payload
Saved overrides apply immediately to the next incident dispatch for that channel.
Edit via the API
curl -X PUT https://yorkermonitoring.com/api/notification-channels/nch_abc \
-H "Authorization: Bearer $YORKER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"incidentTemplate": {
"channelType": "slack",
"overrides": {
"opened": {
"blocks": "{\"blocks\":[{\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"{{severityEmoji incident.severity}} *{{incident.title}}*\\n{{payload.hypothesis.summary}}\"}}]}"
}
}
}
}'The blocks body must render to a JSON object with a blocks: [...] array. A render error or a parse error falls back to the default payload and logs a warning. A bad template never fails dispatch. Each body is capped at 32 KiB.
Use "default" as the event key to define a single override that applies to every event type that doesn't have its own entry.
Available helpers
{{severityEmoji incident.severity}}returns๐ด / ๐ก / ๐ต{{eventEmoji eventType}}returns๐จ / โ / ๐บ / ๐ค / โ / โ๏ธ / ๐ / ๐{{upperCase str}},{{titleCase str}}{{join array ", "}}{{#ifHasSource "synthetic_http"}}โฆ{{/ifHasSource}}matchessynthetic_http,synthetic_browser, orsynthetic_mcp{{jsonBody payload}}splats a value as raw JSON (alreadyJSON.stringifyd). In JSON-producing channels (Slack, webhook, PagerDuty, ServiceNow) escaping is disabled, so{{jsonBody x}}and{{{jsonBody x}}}are equivalent. In email HTML templates the double-stash form is HTML-escaped by default; use triple-stash only as an explicit opt-out.
Render context
The full context mirrors serializeIncidentEventForExport:
eventId,eventType,incidentId,teamId,occurredAtactor:{ type: "user" | "system", id }payload: the full event payload (observations, hypothesis, event-specific fields)incident:{ incidentId, title, severity, state, openedAt, triageUrl }
Disabling incident routing
To fall back to the legacy per-alert Slack dispatch, set incidentSubscribed: false on the channel:
curl -X PUT https://yorkermonitoring.com/api/notification-channels/nch_abc \
-H "Authorization: Bearer $YORKER_API_KEY" \
-d '{ "incidentSubscribed": false }'