Operating / Notifications
Notifications
Where an account wants to be told things, and which things.
A channel is somewhere the account wants to be told things. Four kinds:
| Kind | Target |
|---|---|
| an address | |
| Slack | an incoming webhook URL |
| Discord | an incoming webhook URL |
| Webhook | a URL of your own, which gets JSON posted to it |
Account → Notification channels → Add. Then Test it, which sends a real message through the real path, so a mistyped webhook fails here rather than during an incident.
A Slack or Discord webhook URL is a bearer credential – whoever holds it can post into that channel – so the target is stored encrypted and never shown back in full.
A channel can be switched off without deleting it; it shows as Paused and is told nothing until it is switched back on. Adding, changing and removing channels is admin only.
An email channel needs this KamalCloud to have outgoing mail configured. Where it has none, the page says so, because an email channel with no mail server behind it fails quietly.
Events
| Event | Group | Severity |
|---|---|---|
deployment.succeeded |
Deploys | info |
deployment.failed |
Deploys | high |
task.failed |
Deploys | high |
removal.failed |
Deploys | high |
backup.failed |
Backups | high |
backup.overdue |
Backups | high |
backup.incomplete |
Backups | medium |
server.status_changed |
Servers | info |
server.traffic |
Servers | medium |
provider.rejected |
Servers | critical |
certificate.expiring |
Domains | high |
Each channel subscribes to whichever it likes.
What a new channel subscribes to
By default: the things that are always worth an interruption, and nothing that is merely news.
deployment.failed, task.failed, removal.failed, backup.failed, backup.overdue,
backup.incomplete, provider.rejected, server.traffic, certificate.expiring.
Notably not deployment.succeeded – a channel that pings on every successful deploy is a
channel people mute, and then they miss the failures too. Turn it on deliberately if you want it.
Repeats
Some alerts describe something that stays true, and those stay quiet for 24 hours once they have
been sent: server.traffic, backup.overdue, certificate.expiring, provider.rejected and
server.status_changed. A traffic warning is true for the rest of the month; saying so every
hour is noise.
This applies per subject, so a second server going over its allowance is a second alert.
Everything else is sent every time it happens. A failed deploy, a failed task run, a failed or incomplete backup – a second one is a second thing, and each one sends.
Webhook payloads
The webhook kind posts JSON. Point it at whatever you already run – an incident tool, a bot, a queue.
{
"event": "deployment.failed",
"severity": "high",
"title": "…",
"body": "…",
"url": "https://…",
"subject": null,
"account": "Acme",
"delivered_at": "2026-09-14T11:20:04Z"
}
subject is set only for the alerts that repeat-suppress, and is what they are keyed on.
When a channel breaks
The last delivery time and the last error are kept on the channel, so a webhook that started returning 404 is visible rather than silent. The page also lists the 30 most recent deliveries across every channel, each with its status and any error. Test it to confirm before assuming nothing has happened.