← Knowledge hub
Tutorialby Uptime Room· September 24, 2026· 5 min read

Discord Webhook Alerts: Route Downtime to a Channel

Discord webhook alerts put downtime in the channel people already watch. Here is the embed payload, the mention control and the rate limit that drops alerts.

Discord webhook alerts land downtime notices in the channel your team and often your users already have open. The plumbing takes five minutes. The parts that decide whether the channel stays useful are the embed payload, the mention rules and the rate limit, and none of the vendor integration pages cover those.

Getting the URL

Webhooks are created in the channel, not in a developer portal. Open the channel, choose Edit Channel, then Integrations, then Webhooks, then New Webhook. Name it, pick an avatar if you care, and copy the URL. Discord's introduction to webhooks has the same path with screenshots.

That URL is a credential. Anyone holding it can post as that webhook, which is why Discord invalidates webhook URLs it finds posted publicly. Keep it in the same place you keep API tokens, and rotate it by deleting the webhook and creating a new one.

A bare POST proves the wiring before you build anything on top.

curl -X POST "$DISCORD_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{"content":"test from the deploy host"}'

A 204 with no body means success. A 404 means the webhook was deleted, and a 401 means the token portion of the URL is wrong.

The embed object, and the colour trap

A plain content string works and looks like chat. An embed looks like an alert, with a coloured bar down the left edge that makes state readable at a glance. Discord's webhook reference documents the execute endpoint and the fields it accepts.

{
  "username": "Uptime Room",
  "embeds": [{
    "title": "DOWN: api.example.com",
    "url": "https://status.example.com",
    "color": 15158332,
    "description": "HTTP 503 from 2 of 3 regions",
    "fields": [
      { "name": "Monitor", "value": "api https", "inline": true },
      { "name": "Regions", "value": "LHR, SIN", "inline": true },
      { "name": "Since", "value": "14:02 UTC", "inline": true }
    ],
    "timestamp": "2026-09-23T14:02:11.000Z"
  }]
}

color is a decimal integer, not a hex string, and this is where most first attempts fail. Red is 15158332, green is 3066993, amber is 15844367. Convert your hex with a calculator once and keep the three constants somewhere.

Keep the title to the state and the host. Whoever reads it on a phone sees roughly forty characters before truncation, so "DOWN: api.example.com" beats a full sentence every time.

Stopping the 3am @everyone

By default, any mention text in an embed or in content will ping. A monitor that flaps overnight can therefore notify an entire server, repeatedly, and that is how a channel gets muted permanently.

The allowed_mentions object is the control.

{
  "content": "<@&123456789012345678> api.example.com is DOWN",
  "allowed_mentions": { "parse": [], "roles": ["123456789012345678"] }
}

An empty parse array disables every mention type, and listing one role id re-enables exactly that role. So an on-call role gets pinged, @everyone never fires by accident, and a hostname that happens to look like a mention stays inert.

We prefer pinging a role only on a confirmed DOWN, and posting recoveries with mentions off entirely. Nobody needs a notification sound to learn that something came back.

Why do discord webhook alerts go missing?

Rate limits, almost always. Each webhook has its own limit, and a monitor in a flapping state will find it. Discord returns 429 with a retry_after value in the body, and anything you send during that window is simply not delivered. The alert you most wanted is the one that gets dropped. The rate limit documentation explains the headers that come back with it.

Two fixes, and you want both. Handle the 429 properly by reading retry_after and sleeping, rather than retrying immediately in a loop that makes it worse. Then stop the flapping at the source, because a webhook is not the right place to solve alert noise. Confirmation across regions and a suspect state before a down verdict do that job, and our post on reducing alert noise walks through the trade-offs.

We tested a deliberately unstable check against a single webhook and watched roughly a third of the messages return 429 once it started oscillating. The channel showed an incomplete story, which is worse than no story.

Keeping an incident in one thread

Channel-level discord webhook alerts become unreadable during a long incident, because the updates interleave with everything else people are typing. Appending ?thread_id= and a thread id to the webhook URL posts into that thread instead.

curl -X POST "$DISCORD_WEBHOOK_URL?thread_id=1234567890123456789" \
  -H "Content-Type: application/json" \
  -d '{"content":"recovered, 12m 40s total"}'

The first alert goes to the channel, someone starts a thread from it, and every follow-up lands inside. The channel keeps one line per incident and the detail stays one click away.

The channel your users are in

This is where Discord differs from a work chat tool. Plenty of projects run their community server in the same place as their engineering channels, so an outage message can reach customers directly.

That is an opportunity and a hazard. A public channel receiving raw monitor output leaks internal hostnames, region names and error bodies. Split it. A private channel gets the full embed, and a public one gets a short state line plus a link to the status page you publish. The same split is worth applying to planned maintenance windows.

Wire the private one to whichever monitor types matter. Uptime Room supports Discord among 15 integrations as of September 2026, and probes run from six regions, so a single failing region does not fire anything on its own. The pricing page lists which confirmation rules come with each plan.

Discord is broadcast, not escalation

A message in a channel reaches people who are looking at the channel. At 3am nobody is. Chat delivers context well and wakes people badly, which is the same limitation every chat integration shares.

Pair it with a channel that survives a sleeping phone, such as SMS, a voice call or a push notification, and let Discord carry the detail once someone is awake. Our notes on what a down verdict really means cover which events deserve that escalation at all.

Common mistakes

Sending a hex string as color. The API accepts the payload and renders a grey bar, so it fails silently. Use the integer.

Retrying immediately on 429. It extends the penalty window and drops more alerts. Read retry_after and wait.

One webhook for everything. Deploys, backups and outages in one channel means the outage scrolls past. One webhook per severity, each in its own channel.

Well-built discord webhook alerts use an embed with a real colour, mentions restricted to an on-call role, graceful 429 handling, and a thread per incident. Add a paging channel underneath, because chat alone will not wake anyone. The free plan covers 10 monitors at a one-minute interval as of September 2026, so start free and point the first webhook at a test channel.

FAQ

How do I create a Discord webhook?

Webhooks live in channel settings rather than a developer portal. Open the channel, choose Edit Channel, then Integrations, then Webhooks, then New Webhook. Give it a name and copy the URL. Treat that URL as a credential, because anyone who has it can post as the webhook, and Discord invalidates webhook URLs it finds published in public places.

Why is my Discord embed grey instead of coloured?

The color field takes a decimal integer, not a hex string. Sending a value like the usual hash-prefixed hex is accepted by the API and renders as a default grey bar, so the failure is silent. Convert the hex once and store the constants. Red is 15158332, green is 3066993 and amber is 15844367.

How do I stop a monitor pinging everyone in Discord?

Use the allowed_mentions object on the payload. An empty parse array disables every mention type, including everyone and here, no matter what the message text contains. Adding one role id to the roles array re-enables that single role, so an on-call group still gets notified while a flapping check cannot wake the whole server.

How to monitor server uptime with Discord?

Run the checks somewhere outside your own network, then point the alert route at a webhook URL for the channel you want. Confirm a failure across more than one probe region before the message fires, otherwise one bad network path pages people for nothing. Send recoveries to the same channel with mentions disabled so the follow-up stays quiet.

Related reading