Alerts and on-call

Webhooks

A webhook channel sends each alert notification as a JSON POST request to a URL that you choose. Use it to connect Spectate to your own tools, for example a chat bot or a ticket system. This page describes the request, the payloads and the delivery rules. To receive alerts from other tools in Spectate, use an alert source instead.

Add a webhook channel

  1. In the dashboard, select Alerting.
  2. Select New channel.
  3. Under Integration, select Webhook.
  4. Enter a Name and the Webhook URL.
  5. To send headers, select Add header and enter a name and a value.
  6. Select Create channel.
  7. Add the channel to an escalation path with a Notify channel step.

With the public API, send type: "webhook" and a webhook object with url and up to 20 headers. The URL and the header values are write-only. The API never returns them.

The request

Code
POST /spectate HTTP/1.1 Host: hooks.example.com Content-Type: application/json User-Agent: Spectate/2.0 Authorization: Bearer YOUR_SECRET {"event": "alert.fired", "alert": {...}, "chart_url": "..."}
PartValue
MethodPOST
BodyJSON, UTF-8
Content-Typeapplication/json
User-AgentSpectate/2.0
Your headersEach header that you added to the channel

Spectate does not sign webhook requests. To make sure that a request comes from Spectate, add a secret header to the channel, for example Authorization: Bearer YOUR_SECRET, and check it in your receiver. Use an https:// URL so that the secret is encrypted in transit.

You cannot set the headers Connection, Content-Length, Host and Transfer-Encoding.

Events

eventSent when
alert.firedAn escalation step sends a firing alert to the channel.
alert.resolvedAn alert that the channel got resolves, on its own or by hand.
channel.testSomeone sends a test from the dashboard or the API.

Spectate does not send a webhook when someone acknowledges an alert. A channel gets one alert.fired for each escalation step that notifies it, and at most one alert.resolved per alert.

alert.fired

JSONCode
{ "event": "alert.fired", "alert": { "uuid": "9d3f6c2a-6a1e-4f8e-9b7d-2c5e8f1a4b30", "title": "Checkout API is down", "severity": "critical", "source_type": "uptime", "fired_at": "2026-10-27T09:14:03+00:00", "metadata": { "monitor_url": "https://api.example.com/health", "protocol": "https", "error": "Connection timed out after 30 seconds", "location": "eu", "checked_at": "2026-10-27T09:14:01+00:00" } }, "chart_url": "https://api.spectate.net/alert-charts/9d3f6c2a-6a1e-4f8e-9b7d-2c5e8f1a4b30/fired.png?expires=1764407643&signature=..." }

alert.resolved

JSONCode
{ "event": "alert.resolved", "alert": { "uuid": "9d3f6c2a-6a1e-4f8e-9b7d-2c5e8f1a4b30", "title": "Checkout API is down", "severity": "critical", "source_type": "uptime", "fired_at": "2026-10-27T09:14:03+00:00", "resolved_at": "2026-10-27T09:31:47+00:00", "metadata": { "monitor_url": "https://api.example.com/health", "protocol": "https", "error": "Connection timed out after 30 seconds", "location": "eu", "checked_at": "2026-10-27T09:14:01+00:00" } }, "chart_url": "https://api.spectate.net/alert-charts/9d3f6c2a-6a1e-4f8e-9b7d-2c5e8f1a4b30/resolved.png?expires=1764408707&signature=..." }

channel.test

JSONCode
{ "event": "channel.test", "title": "Test notification for Ops webhook", "message": "200 OK - Test notification sent successfully" }

Fields

FieldTypeDescription
eventstringalert.fired, alert.resolved or channel.test.
alert.uuidstringThe alert ID. It is the same in both events of one alert, in the dashboard URL /alerts/{uuid} and in the public API.
alert.titlestringWhat is wrong, for example Checkout API is down.
alert.severitystringcritical, high, medium or low.
alert.source_typestringuptime, performance, certificate, dns, host_metric, domain, status_page or external. See alerts.
alert.fired_atstringWhen the alert fired, ISO 8601.
alert.resolved_atstringWhen the alert resolved, ISO 8601. Only in alert.resolved.
alert.metadataobject or nullDetails from the source. The keys depend on the source type.
chart_urlstring or nullA PNG chart of the data around the alert. null when there is no chart.

The keys in alert.metadata are not fixed. For an uptime alert they include monitor_url, protocol, error, status_code, location, response_time and checked_at, when the check had them. For an alert from an alert source, they include provider, labels, links and the metadata that the tool sent. Read the keys that you need, and ignore keys that you do not know.

The chart_url link is signed and works for 30 days. Uptime, performance and host metric alerts can have a chart.

Delivery

RuleValue
Connect timeout2 seconds
Request timeout5 seconds
SuccessAny 2xx response
RedirectsNot followed. A 3xx response is a failure that Spectate does not retry.
Tries3: at once, after 30 seconds, and 2 minutes after that
No retryHTTP 401, 403, 404 and 410

Answer fast, with a 2xx status, and do slow work after you answer. A request that takes longer than 5 seconds fails, even if your receiver processed it. After a timeout, Spectate sends the same event again. Use event and alert.uuid to find repeated deliveries.

A webhook that keeps failing is disabled automatically. See when Spectate disables a channel.

URL rules

Spectate sends webhooks only to public addresses. A URL must meet these rules:

  • The scheme is http or https.
  • The URL has no user name or password in it.
  • The host is not localhost, and does not end in .localhost or .internal.
  • Every IPv4 and IPv6 address of the host is public. Private, reserved and carrier-grade NAT (100.64.0.0/10) addresses are refused, as are IPv4-mapped and NAT64 IPv6 addresses.

Spectate checks the URL when you save the channel and again before each request. The request goes to the IP address that Spectate checked. A DNS change after the check cannot send it to another address. If the URL redirects, use the final URL in the channel.

  • Channels: all channel types, tests and auto-disable.
  • Alert sources: send alerts from your tools into Spectate.