Connect your data

Slack and webhooks

Connect Slack channels and webhooks to VitalSentinel alerts, test them, verify webhook signatures, and fix delivery problems.

View as Markdown

Slack and webhooks send VitalSentinel alerts outside the app. A Slack channel gets each alert as a Slack message. A webhook sends each alert to your own web address as signed JSON, for on-call tools, chat bots or scripts.

What Slack and webhooks are for

  • Slack channels: your team reads the alerts in a Slack channel. Each alert message has the problem, the facts, the next steps and a button that opens the alert in VitalSentinel.
  • Webhooks: VitalSentinel sends each alert to an endpoint. An endpoint is a web address on your server or in another tool that receives data. Use a webhook to send alerts to a tool that VitalSentinel does not connect to directly.

You connect Slack channels and webhooks once for the workspace. Then you select them in each alert rule. The in-app notification and the email notification stay available on every plan. See Alert delivery.

Before you start

  • Plan: Slack and webhooks are available on Lite and higher plans. On a lower plan, the workspace Integrations page shows the chip On Lite and higher plans and the text "Available on Lite and higher plans. Email and in-app alerts stay on every plan." A workspace owner also sees See plans. See Plans and limits.
  • Role: only workspace owners and admins can connect Slack, add webhooks and use the buttons on each row. Members see the rows and Recent deliveries, but no other buttons.
  • Where: open the workspace Settings, then click Integrations in the Workspace Settings sidebar. The Slack and webhook cards are below Google accounts.

Connect a Slack channel

Each Slack channel is a separate connection. To send alerts to two channels, connect Slack two times.

  1. On the workspace Integrations page, click Add to Slack.
  2. On the Slack page, sign in to your Slack workspace if Slack asks.
  3. Select the channel for your alerts.
  4. Approve the request.

Slack then sends you back to the Integrations page. The message Slack channel connected confirms the connection. The new row shows the channel name, the Slack workspace and the chip Connected.

If no Slack channel is connected yet, the card shows No Slack channels connected and "Pick a channel and VitalSentinel posts your alerts there. Each channel is a separate connection."

Connect Slack from an alert rule

If the workspace has no Slack channel, the Delivery part of an alert rule shows a Slack card with Connect Slack.

  1. Click Connect Slack. Slack opens in a new tab.
  2. In Slack, select the channel and approve the request.
  3. Go back to the tab with the alert rule. The new channel shows in the rule without a reload.

Private channels and archived channels

  • Private channel: you must be a member of a private channel before you can select it in Slack. Join the channel in Slack first, then click Add to Slack again.
  • Archived channel: Slack does not accept messages in an archived channel. If somebody archives a connected channel, the row shows Needs reconnecting and "The channel was archived". Unarchive the channel in Slack and reconnect it, or connect another channel.

Slack workspace admin approval

Some Slack workspaces allow only apps that an owner or app manager approved. In that case, Slack does not let you install VitalSentinel at once. If your Slack workspace allows requests, you can send a request for approval in Slack. When your Slack admin approves VitalSentinel, click Add to Slack again. Some Slack workspaces restrict an app completely. Then only your Slack admin can change that.

Slack channel rows

Each row in the Slack channels card shows the channel (for example #alerts), the Slack workspace and a status chip:

ChipMeaning
ConnectedAlerts go to the channel. The row shows Send test.
Needs reconnectingSlack refused the messages. Alerts to the channel are paused. The row shows Reconnect.

A row with Needs reconnecting gives the reason, followed by "Alerts are paused.":

  • "The channel was removed"
  • "The channel was archived"
  • "The app was removed from the channel"
  • "Slack no longer allows posting there"
  • "The saved connection could not be read"
  • "Slack refused our messages" (any other reason)

When a channel stops working, the person who connected it gets one notice in the app: "Slack channel #name stopped working". The notice also says: "If it stays disconnected for 14 days, we remove it."

Send a test message to Slack

  1. On the row of the channel, click Send test.
  2. Open the channel in Slack and look for the test message.

If the test works, the message "Test message sent. Check the channel in Slack." shows. If it fails, the message starts with "The test did not go through" and gives the reason in brackets, for example HTTP 404 channel_not_found. The Slack test message has the tag Test and the title "Test alert from VitalSentinel".

Reconnect a Slack channel

  1. On the row with Needs reconnecting, click Reconnect.
  2. In Slack, select the same channel and approve the request.

The row then shows Connected again, and the alert rules that used the channel use it again. If you select a different channel, VitalSentinel adds it as a new row. The old row stays until you disconnect it. If a channel stays disconnected for 14 days, VitalSentinel removes it and sends you a notice.

Disconnect a Slack channel

  1. On the row of the channel, click the trash icon.
  2. In the dialog Disconnect Slack channel, click Disconnect.

Alerts stop going to the channel, and VitalSentinel removes the channel from every alert rule. VitalSentinel also revokes its access in Slack and deletes the saved connection.

Use a channel or a webhook in an alert rule

  1. Open an alert rule, or click Create alert on the Alerts page.
  2. Under Delivery, select each Slack channel card (Slack – #channel) and webhook card (Webhook – name) that must get the alert.
  3. Click Save alert.

You cannot add a channel with Needs reconnecting or a webhook with Turned off to a rule. If the workspace has no webhook, the rule shows a Webhooks card with Set up a webhook. See Alert delivery.

Add a webhook

  1. On the workspace Integrations page, click Add webhook. The Add a webhook window opens.
  2. In Name, enter a name, for example "Ops on-call".
  3. In Endpoint URL, enter the address of your endpoint. It must be a public https:// address.
  4. Click Add webhook. The Copy your signing secret window opens.
  5. Click the copy icon next to Signing secret.
  6. Keep the secret in a safe place, for example in your password manager.
  7. Click I have saved it.

With no webhook, the card shows No webhooks yet and "Send alerts to your own endpoint as signed JSON, for on-call tools, chat bots or scripts."

The signing secret

The signing secret shows only one time. VitalSentinel cannot show it again. If you lose it, rotate the secret and update your endpoint.

The signing secret starts with whsec_. Your endpoint uses it to make sure that a request came from VitalSentinel and that nobody changed it. See Verify the webhook signature.

Webhook rows

Each row in the Webhooks card shows the webhook name, the host of the endpoint and a status chip: On or Turned off. A turned-off row also shows the reason, for example "10 failed deliveries in a row". The row has these buttons:

  • Send test: sends a test alert to the endpoint. This button shows only when the webhook is on.
  • Turn off or Turn on: stops or starts the alerts to the endpoint.
  • The key icon: rotates the signing secret.
  • The trash icon: removes the webhook.

Send a test to a webhook

Click Send test on the row. If your endpoint answers with a success status, the message "Test delivered. Your endpoint answered with a success status." shows. If not, the message starts with "The test did not go through" and gives the reason, for example HTTP 401. The test request has the type value test. A failed test does not turn the webhook off.

Rotate the signing secret

When you rotate the secret, the current secret stops working at once. Requests signed with the new secret fail on your endpoint until you update it.

  1. On the row, click the key icon.
  2. In the dialog Rotate signing secret, click Rotate secret.
  3. In the Copy your signing secret window, copy the new secret.
  4. Update the secret on your endpoint.
  5. Click I have saved it.

Remove a webhook

  1. On the row, click the trash icon.
  2. In the dialog Remove webhook, click Remove webhook.

Alerts stop going to the endpoint, and VitalSentinel removes the webhook from every alert rule. VitalSentinel also deletes its signing secret.

Recent deliveries

Click Recent deliveries on a Slack channel row or a webhook row to see the last ten messages sent there, newest first. Each line shows a status, Alert or Test message, the error (if there is one) and the date and time.

StatusMeaning
SentSlack or your endpoint accepted the message.
FailedThe delivery did not work. The line shows the reason, for example HTTP 500 or network error.
SkippedVitalSentinel did not send the message, for example because the webhook is off or the channel needs reconnecting.
PendingThe delivery is not finished yet.

If VitalSentinel tried a delivery more than one time, the line shows the attempt number, for example "attempt 2". If nothing was sent yet, the list shows "Nothing has been sent here yet."

What VitalSentinel sends to a webhook

VitalSentinel sends each alert to the endpoint as an HTTPS POST request with a JSON body. An alert rule sends one request when the alert starts and one when the problem stops.

Webhook headers

HeaderValue
Content-Typeapplication/json
User-AgentVitalSentinel-Webhooks/1
X-VitalSentinel-Event-IdThe ID of the event. It is the same on each retry of the same event.
X-VitalSentinel-TimestampThe time of this attempt, in Unix seconds.
X-VitalSentinel-Signaturev1= followed by the signature, in hexadecimal.

Webhook payload

{
  "schema": "vitalsentinel.alert.v1",
  "event_id": "6f1a0f6e-2b3c-4d5e-8f90-a1b2c3d4e5f6",
  "type": "fired",
  "timestamp": "2026-10-16T10:00:00+00:00",
  "rule": { "id": "…", "name": "Site is down" },
  "domain": { "id": "…", "name": "example.com" },
  "module": "uptime",
  "metric": "is_down",
  "severity": "critical",
  "title": "Site is down",
  "message": "Your site does not answer. Visitors cannot open it.",
  "metrics": {
    "current_value": 1.0,
    "threshold_value": 1.0,
    "current_display": "Yes",
    "threshold_display": "Yes",
    "device": null
  },
  "url": "https://app.vitalsentinel.com/dashboard/domains/…/uptime"
}

Payload fields

FieldMeaning
typefired when the alert starts, resolved when the problem stops, test for Send test.
severitycritical, warning or info.
title, messageThe headline and the sentence that the alert shows in the app.
rule, domainThe alert rule and the domain, each with an id and a name.
metricsThe current value and the threshold, as numbers and as display text. Values can be null.
urlThe link that opens the alert in VitalSentinel.
event_idThe ID of the event. A resolved event has its own ID.

New fields can come in a later version of vitalsentinel.alert.v1. Make your endpoint ignore fields that it does not know.

Verify the webhook signature

Each webhook request has a signature. Your endpoint calculates the same signature with your signing secret. If the two values are the same, the request came from VitalSentinel and nobody changed it.

How the signature is made

  1. Take the value of the X-VitalSentinel-Timestamp header.
  2. Add a period (.) and the raw request body, exactly as received.
  3. Calculate an HMAC-SHA256 of this text. Use the full signing secret, with whsec_, as the key.
  4. Write the result in lowercase hexadecimal and put v1= before it.
  5. Compare the result with the X-VitalSentinel-Signature header.

Also reject a request if the timestamp is more than five minutes from your server time. This stops somebody who sends an old request again. Use the raw body, not a parsed and re-encoded JSON object, because a small change makes the signature different.

Node.js example

import crypto from 'node:crypto';

// rawBody is a Buffer with the request body, exactly as received.
export function verify(secret, rawBody, timestamp, signature, toleranceSeconds = 300) {
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > toleranceSeconds) return false;
  const expected =
    'v1=' + crypto.createHmac('sha256', secret).update(`${timestamp}.`).update(rawBody).digest('hex');
  const a = Buffer.from(expected);
  const b = Buffer.from(signature);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

In Express, use express.raw({ type: 'application/json' }) on the webhook route to get the raw body.

Python example

import hashlib, hmac, time

def verify(secret: str, body: bytes, timestamp: str, signature: str, tolerance: int = 300) -> bool:
    if abs(time.time() - int(timestamp)) > tolerance:
        return False
    expected = "v1=" + hmac.new(secret.encode(), timestamp.encode() + b"." + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)

Both examples compare the values in constant time, so the time of the comparison gives no information about the signature.

Retries and automatic turn-off

Your endpoint must answer with a 2xx status code to accept a webhook request. Answer fast, in less than five seconds, and do slow work after you answer.

  • Retries: if your endpoint answers 408, 429 or a 5xx status, or does not answer, VitalSentinel tries again. It makes up to four attempts in total, with a short wait between them. Each attempt has a new timestamp and a new signature.
  • No retries: VitalSentinel does not retry other status codes, for example 400, 401 or 404. It also does not follow redirects, so a 3xx answer is a failed delivery.
  • Duplicates: a retry has the same event_id. Use it to ignore an event that your endpoint already processed.
  • Automatic turn-off: if 10 deliveries in a row fail, VitalSentinel turns the webhook off. The row shows Turned off and "10 failed deliveries in a row". The person who added the webhook gets the notice "Webhook "name" was turned off".

To start the alerts again, fix the endpoint, click Send test, then click Turn on.

Troubleshooting

Why can I not see Add to Slack or Add webhook?

  • If the card shows On Lite and higher plans, the workspace plan does not include Slack and webhooks. See Plans and limits.
  • If you are a member, the buttons do not show. Ask a workspace owner or admin.

Why does the Integrations page say "Slack was not connected"?

MessageWhat to do
"You declined access in Slack, so nothing was connected."Click Add to Slack again and approve the request.
"That connection attempt expired, so nothing was connected. Please try again."Click Add to Slack again and finish the steps in Slack without a long pause.
"Only workspace owners and admins can connect Slack, so nothing was connected."Ask a workspace owner or admin to connect Slack.
"Slack alerts are available on Lite and higher plans, so nothing was connected."Upgrade the plan, or use email alerts.
"Slack could not finish connecting, so nothing was connected. Please try again."Try again. If it fails again, contact support.

Why can I not install VitalSentinel in Slack?

Your Slack workspace can require admin approval for apps. If Slack lets you send a request, send it. After your Slack admin approves VitalSentinel, click Add to Slack again. If you cannot find a private channel in the Slack list, join that channel in Slack first.

Why does a Slack channel show "Needs reconnecting"?

Slack refused the alerts for the channel, and the row gives the reason. For example, somebody archived or deleted the channel, or removed the VitalSentinel app. If the channel still exists, click Reconnect and select the same channel. If the channel is gone, disconnect the row and connect another channel.

Why is my endpoint URL refused?

The Endpoint URL field shows the reason:

  • "The URL must start with https://": use an https:// address. VitalSentinel does not send to http://.
  • "That address is not reachable from the internet. Use a public HTTPS URL.": the address points to a private network, for example localhost or an internal server. Use a public address.
  • "Enter a valid HTTPS URL without a username or password.": remove the user name and password from the address.

Why do my webhook deliveries fail?

Open Recent deliveries on the webhook row and read the reason.

  • HTTP 401 or HTTP 403: your endpoint or a firewall refuses the request. Allow requests without a login, and check the signature instead.
  • HTTP 404: the path of the endpoint is wrong.
  • HTTP 301 or HTTP 302: your endpoint redirects. Enter the final address.
  • network error: your endpoint did not answer in time, or the TLS certificate is not valid.

Why does the webhook signature not match?

  • Calculate the signature on the raw request body. A JSON parser changes the spaces and the order of the text.
  • Use the full secret, with whsec_ at the start.
  • If somebody rotated the secret, use the new secret.
  • Use the timestamp from the X-VitalSentinel-Timestamp header of the same request.

Why was my webhook turned off?

VitalSentinel turns a webhook off after 10 failed deliveries in a row. Fix the endpoint, click Send test, and if the test works, click Turn on.

Why do some deliveries show "Skipped"?

VitalSentinel skips a delivery in these cases: the webhook is off, the Slack channel needs reconnecting, or the plan no longer includes Slack and webhooks. The line shows the reason. Fix the cause, and the next alerts go out again.

On this page

VitalSentinel

Catch issues before they cost you

Track SEO, performance, and uptime in one place and get alerted the moment something breaks – hours before it hits your traffic.

  • Free plan for 1 domain
  • Set up in minutes
  • No credit card required