/ guides / uptime-alerts-slack-discord-webhook

Uptime alerts in Slack, Discord or a webhook

Send downtime alerts to Slack, Discord, Telegram or your own signed webhook: what triggers an alert, what stays quiet, and how repeats and recovery work.

Updated

To get uptime alerts in Slack, paste a Slack incoming webhook URL into your monitoring tool as an alert channel, and every outage posts a message to the Slack channel that webhook belongs to. Fettle is uptime monitoring for developers that alerts by email and Telegram on every plan, and by webhook, Slack and Discord from Plus. An alert goes out when a monitor's regions agree it is down, again when it recovers, and when an SSL certificate is about to expire. Partial failures stay quiet.

This guide covers setting up each channel, what fires an alert and what does not, and how repeats, acknowledgement and routing work.

Which alert channels does Fettle support?

Fettle alerts by email, Telegram, webhook, Slack and Discord. On every plan you get email and Telegram; webhook, Slack and Discord start on Plus. Email is not a channel you add: every alert also goes to the inbox of the person who created the monitor or heartbeat. Channels are added in the dashboard, not through the API.

The limit on how many channels an organization can have depends on the plan; the pricing page lists it. Each channel belongs to an organization, so everyone on the team sees the same alerts in the same Slack or Discord channel.

How do I send uptime alerts to Slack?

Create an incoming webhook in Slack, then paste its URL into a new Slack channel in the Fettle dashboard under Channels. Fettle checks that the URL is a real Slack webhook address (https://hooks.slack.com/services/…), stores it encrypted, and the channel is ready at once: there is no separate verification step.

On the Slack side, per Slack's own guide to incoming webhooks: create a Slack app, switch on Incoming Webhooks, click "Add New Webhook to Workspace" and pick the channel it should post to. One webhook posts to one Slack channel, so a second destination means a second webhook and a second Fettle channel. Slack treats the URL as a secret, and so does Fettle: after you save it, the dashboard shows only the start of the address.

Each message has a colored bar and a title (down, recovered, SSL expiring), followed by the monitor's name, its target, the failure detail and the time in your organization's timezone. A "View in Fettle" link opens the incident (for SSL alerts, the monitor).

How do I send uptime alerts to Discord?

The same way: create a webhook on the Discord channel, copy its URL (https://discord.com/api/webhooks/…) and add it as a Discord channel in the Fettle dashboard. Fettle sends each alert as an embed with the same color coding as Slack, the monitor, target, failure detail and time as fields, and a link to the incident in the title.

Discord's developer docs describe webhooks as a low-effort way to post messages to a channel without a bot user.

How do I get alerts on Telegram?

Add a Telegram channel in the dashboard. Fettle gives you a one-time link to its Telegram bot; open it, press Start, and the chat is linked and verified. The link expires after a while, so if you wait too long, request a new one.

Each link connects the chat to one organization; to get alerts from two organizations in the same chat, link it once from each.

How do I receive alerts on my own webhook?

Add a webhook channel with a public HTTPS URL. Fettle POSTs a versioned JSON body for each alert and signs it with a secret it shows you once, when you save the channel. Your receiver checks the signature and then does whatever you want: page someone, open a ticket, post to a chat tool Fettle does not support directly.

Each delivery carries an event name, a timestamp, a delivery id and the signature in headers (X-Fettle-Event, X-Fettle-Timestamp, X-Fettle-Delivery, X-Fettle-Signature). The body names the source (monitor or heartbeat), its target (null for a heartbeat), and for incidents the incident id and its structured cause, such as TIMEOUT, HTTP_5XX or HEARTBEAT_MISSED:

{
  "event": "triggered",
  "incident": {
    "cause": "HTTP_5XX",
    "cause_detail": "status code 503 not in expected set",
    "id": "0192f3a4-5b6c-7d8e-9f01-23456789abcd",
    "resolved_at": null,
    "started_at": "2026-10-31T09:12:04.120000+00:00"
  },
  "organization": { "id": "0192f3a4-0000-7000-8000-000000000001" },
  "source": {
    "id": "0192f3a4-1111-7111-8111-111111111111",
    "name": "Checkout API",
    "target": "https://www.example.com/health",
    "type": "monitor"
  },
  "ssl": null,
  "timestamp": "2026-10-31T09:12:04.480000+00:00",
  "version": "1"
}

A delivery that fails with a 429, a 5xx, a timeout or a connection error is retried with growing gaps for about five minutes; a 4xx answer is final. The delivery id stays the same on every retry, so your receiver can drop duplicates. The full contract, including how to verify the signature in Node.js and Python, is in the webhooks reference.

Before relying on any Slack, Discord or webhook channel, press its test button. Fettle posts a test event straight away and shows the HTTP status your side returned.

What triggers an alert?

Four things: an incident opening, an incident closing, a certificate nearing expiry, and a reminder for an incident nobody has handled. Everything else, including a single failed check and a failure only some regions see, is recorded in check results without sending anything.

  • Down. A monitor opens an incident when every region that reported recently sees it failing, for as many rounds in a row as its confirmation threshold (1 to 10). A heartbeat opens one when its ping is overdue, or when the job reports /fail.
  • Recovered. The incident closes on the first round where every region sees the target up, or on the next heartbeat ping, and a recovery alert goes out. Recovery alerts are never held back by the cooldown below.
  • SSL expiring. An SSL monitor alerts once when its certificate enters the warning window you set (1 to 365 days before expiry). A renewed certificate, with a new expiry date, starts fresh. This alert is not an incident. The SSL expiry guide covers choosing the window.
  • Reminder. From Plus, an incident that stays open and unacknowledged repeats its down alert at an interval and up to a count set by the plan.

What does a degraded monitor mean for alerts?

Nothing is sent. A monitor turns degraded when at least one region keeps failing for the confirmation threshold while others still see it up. Degraded shows on the dashboard and the uptime chart so you can see it, but it opens no incident and does not lower uptime.

That is deliberate. A failure seen from one place is often the network between that region and your host, not your service. Requiring every region to agree before paging anyone is the main reason Fettle's alerts are worth answering. How the regions vote is in the multi-region monitoring guide.

How do repeats, cooldown and acknowledgement work?

Each monitor and heartbeat has a notification cooldown, 60 seconds to 24 hours, that stops a duplicate down alert for the same incident within that window. From Plus, an open incident is re-sent as a reminder, up to the plan's count, until someone acknowledges it or it resolves. Acknowledging stops the reminders; the recovery alert still arrives.

Acknowledge from the incident page in the dashboard, with POST /v1/incidents/{id}/acknowledge through the API, or by asking an agent connected over MCP, which calls acknowledge_incident. That is how one person tells everyone else in the Slack channel "I have this" without the channel getting the same alert every few minutes.

Can different monitors alert different channels?

Yes. Each monitor and heartbeat takes a list of channel ids. With a list, it alerts only those channels (if verified and active). With no list, it alerts every verified, active channel in the organization, so a new channel covers existing monitors straight away. Email to the creator goes out either way.

You pick channels in the monitor form, or pass channel_ids when you create a monitor through the uptime monitoring API. Channel ids come from GET /v1/channels/directory, or from the list_channels tool over MCP:

curl -s -X POST https://api.fettle.sh/v1/monitors \
  -H "Authorization: Bearer fettle_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
        "name": "Checkout API",
        "type": "HTTP",
        "target": "https://www.example.com/health",
        "interval_seconds": 300,
        "timeout_seconds": 10,
        "regions": ["eu-central"],
        "channel_ids": ["<id of your #oncall Slack channel>"]
      }'

A common split: production monitors alert the on-call Slack channel, staging and side projects alert a quieter Discord channel.

What Fettle does not do

There is no phone call or SMS channel, and no built-in on-call rotation or escalation policy. If you need either, point a webhook channel at the tool that does it. Planned work should not page anyone: a maintenance window holds incidents and alerts while checks keep running.

More on what an uptime check is and how it decides "down" is in the uptime monitoring overview and the rest of the guides.

Questions

Does Fettle alert when only one region sees my site down?
No. An incident and its alert need every region that reported recently to agree the target is down for the confirmation count you set. A failure only some regions see marks the monitor degraded, with no alert.
Can I send different monitors to different Slack channels?
Yes. Add one Slack channel per Slack destination, then pick channels on each monitor or heartbeat. A monitor with no channel list alerts every verified, active channel in the organization.
How do I check that my webhook receiver works before a real outage?
Use the test button on the channel in the dashboard. Fettle posts a test event, signed like a real one, and shows the HTTP status your receiver answered, so you can fix it before an incident.

Start monitoring in a minute

The free plan checks up to 20 monitors as often as every 3 minutes from 1 region, and emails you when one breaks. See pricing for the paid intervals, or follow the quickstart to do it from the API.