Send alerts to Slack or a webhook
Alerts normally arrive by email. You can also send them to a Slack channel, or to any tool that accepts a webhook — and, once one of those is set up, turn the emails off.
What gets sent
The same alerts you'd get by email:
- A monitored site goes down, and when it recovers
- A health score regression, or a visual change on a page
- Pages that regressed in a full-site crawl
- Your monthly client reports being ready (Agency plan)
There is one Slack destination and one webhook per account, shared by all your websites. Everything below is set up on the Notifications page (account menu → Notifications).
Slack
1. Create an incoming webhook
- Go to api.slack.com/apps, click Create New App and choose From scratch. Name it something like "Cuttlefish QA" and pick your workspace.
- In the app's settings, open Incoming Webhooks and switch Activate Incoming Webhooks on.
- Click Add New Webhook to Workspace, choose the channel alerts should post to, and click Allow. (If you're not a workspace admin, Slack may ask an admin to approve it first.)
- Copy the Webhook URL. It starts with
https://hooks.slack.com/services/.
Official guide: Sending messages using incoming webhooks. Menus change from time to time — Slack's own documentation is the source of truth.
2. Add it to Cuttlefish QA
- Open the Notifications page, paste the URL into the Slack box and click Save Slack webhook.
- Click Send test. A test message should appear in your channel within a few seconds.
Treat the webhook URL like a password: anyone who has it can post to that channel. We only show a shortened version of it on the page. If it leaks, delete the webhook in Slack and create a new one.
Webhook (Zapier, Make, n8n or your own code)
We send an HTTP POST with a JSON body to an address you choose. This is the route to use for anything that isn't Slack — a Zap that posts to Microsoft Teams or Discord, a row in a spreadsheet, a ticket in your issue tracker, or your own server.
1. Get a webhook address from your tool
- Create a Zap and choose Webhooks by Zapier as the trigger, with the event Catch Hook.
- Copy the Custom Webhook URL it gives you and save it on our Notifications page.
- Click Send test on our page, then Test trigger in Zapier so it can read the fields (
event,title,message,url). - Add the action you want, such as a Teams or Discord message or an email.
- Create a scenario that starts with the Webhooks module and the Custom webhook trigger.
- Add a webhook, copy its address and save it on our Notifications page.
- Click Send test on our page so Make can learn the data structure, then add your next module.
- Add a Webhook node, set the method to POST, and copy its Production URL.
- Save that address on our Notifications page and activate your workflow.
The address must be reachable from the internet over https, so a self-hosted n8n needs a public domain.
Create an endpoint that accepts POST requests with JSON and returns any 2xx status. Verify the signature (below) before trusting the request.
2. Requirements for the address
- It must start with
https://and be reachable from the public internet. Addresses that point to private or internal networks (likelocalhostor192.168.x.x) are refused. - Redirects are not followed. Use the final address.
- Respond within a few seconds with a
2xxstatus. If we get a server error or a timeout we try once more.
3. What we send
POST /your/endpoint
Content-Type: application/json
X-Cuttlefish-Event: site.down
X-Cuttlefish-Signature: sha256=<hex digest>
{
"version": 1,
"event": "site.down",
"title": "Your site is down: https://example.com",
"message": "We couldn't reach …",
"url": "https://cuttlefishqa.com/…",
"occurred_at": "2026-10-16T09:00:00Z"
}
The event is one of:
| Event | When |
|---|---|
site.down | A monitored site has failed two checks in a row |
site.recovered | A site that was reported down is back |
scan.regression | A scan found the health score dropped or new issues appeared |
visual.change | A visual check found a page looks different |
crawl.regression | A full-site crawl found pages that got worse |
reports.ready | Monthly client reports are ready to download |
test | You clicked Send test |
url can be empty for some events. We may add new fields over time, so ignore ones you don't recognise.
4. Verify the signature
Anyone who learns your endpoint address could send it fake alerts. To check a request really came from us, compute an HMAC-SHA256 of the raw request body using your signing secret (shown on the Notifications page) and compare it with the X-Cuttlefish-Signature header.
Python
import hmac, hashlib
expected = "sha256=" + hmac.new(SECRET.encode(), raw_body, hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, request.headers["X-Cuttlefish-Signature"])
Node.js
const crypto = require('crypto');
const expected = 'sha256=' + crypto.createHmac('sha256', SECRET).update(rawBody).digest('hex');
const given = req.get('X-Cuttlefish-Signature') || '';
const ok = given.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(given));
Use the body exactly as received, before any JSON parsing; re-serialising it changes the bytes and the signature won't match. Zapier, Make and n8n's basic webhook triggers don't check signatures, so for those the hard-to-guess address is the protection — keep it private.
If your secret leaks, click Regenerate secret on the Notifications page and update your receiver. The old secret stops matching straight away.
Turning alert emails off
Once Slack or a webhook is set up, the Email section of the Notifications page lets you switch alert emails off. A few rules keep alerts from disappearing:
- You can only turn emails off while at least one Slack or webhook destination is saved.
- If you remove your last destination, emails switch back on automatically.
- Account emails such as password resets and email verification are not alerts and are always sent.
Troubleshooting
- "That doesn't look like a Slack incoming webhook URL"
- It must start with
https://hooks.slack.com/services/. Copy the Webhook URL from the Incoming Webhooks page, not an app or channel link. - "That URL points to a private or internal address"
- We can only send to addresses on the public internet. For local development, use a tunnel service that gives you a public https address.
- The page says "Last delivery failed: HTTP 404"
- The destination no longer exists. For Slack this usually means the webhook was deleted or the app was removed — create a new one and replace the URL. For a webhook, check the address, and that a Zap or workflow isn't switched off.
- "HTTP 3xx: redirects aren't followed"
- Your address redirects somewhere else (often
httptohttps, or addingwww). Save the final address instead. - "Could not connect"
- Your endpoint didn't answer in time or refused the connection. Make sure it's online and not behind a firewall or bot protection that blocks our requests.
- Signature check always fails
- The usual cause is hashing the parsed JSON rather than the raw body, or using an old secret after regenerating it. Also check there's no extra whitespace in the secret you copied.
- The test works but I'm not getting real alerts
- Alerts only fire when something actually happens: for downtime, a monitored site must fail two checks in a row, and automatic monitoring depends on your plan. Check that the alert would have been sent by email too.
Still stuck? Contact us and tell us which destination you're setting up — we're happy to help.