WarmblyDocs

Operator notifications

Send instance events to Discord, Slack, a signed webhook, or an email address.

Your instance can tell you when something happens on it: a new signup, a worker going offline, a workspace asking for more capacity. Configure the destinations in the admin panel under Configuration > Notifications.

These are operator alerts, not customer alerts. They are instance-wide and go to you. The per-workspace event delivery your customers configure is Webhooks, which is a separate, queued and retried system.

Channels

A channel is one destination. You can add up to 25.

TypeWhat to pasteNotes
DiscordAn incoming webhook URLServer settings, then Integrations, then New Webhook
SlackAn incoming webhook URLCreate a Slack app with an incoming webhook
WebhookAny HTTPS endpointReceives the event as JSON, optionally signed
EmailAn addressNeeds a working platform mail transport

Each channel picks which events it wants. Leave every event unchecked and it receives all of them, including ones added in later versions.

Use Test on a channel to deliver a sample alert immediately. A test ignores the channel's on/off switch and its event selection, so it always sends, and it reports the transport error directly when delivery fails.

URL safety

Webhook URLs must be HTTPS and resolve to a publicly routable host. Inline credentials are rejected. This is the same posture customer webhooks use, and it exists so a notification channel cannot be pointed at your internal network.

To point a channel at a host on your own network, set WARMBLY_ALLOW_UNSAFE_WEBHOOK_URLS=true. That also permits plain HTTP. Only do this on a deployment where you control the network.

Signing

A webhook channel with a signing secret sends:

X-Warmbly-Signature: t=<unix>,v1=<hex>
X-Warmbly-Event: <event key>

v1 is HMAC-SHA256(secret, "<unix>." + body), the same scheme as customer webhooks, so an existing verifier works unchanged. The body is:

{
  "event": "worker.offline",
  "title": "Worker stopped responding",
  "summary": "No healthy replacement of the same tier was available…",
  "severity": "urgent",
  "fields": [{ "label": "Worker", "value": "…" }],
  "link": "https://app.example.com",
  "timestamp": "2026-01-01T00:00:00Z"
}

Credentials

A chat webhook URL is a bearer credential: anyone holding it can post to that channel. The admin API never returns one in full. A saved channel reads back with its URL reduced to a host and the tail of its path, and its signing secret replaced by a placeholder. Sending those values back unchanged means "keep what is stored", so saving an unrelated toggle cannot wipe a credential. To change a URL or secret, type the new value in full.

Events

EventFires when
Enterprise inquiry submittedSomeone asks for enterprise pricing from the plan chooser
Limit increase requestedA workspace asks for more capacity than its plan allows
Payment failedStripe could not collect an invoice
Workspace createdA new organization is created
User registeredA new account finishes signing up
Worker went offlineA worker stops heartbeating and no healthy replacement of its tier is available
Warmup ban appealedA blocked mailbox asks to rejoin the warmup pool
Workspace risk escalatedRisk scoring moves a workspace into a different posture

A self-hosted instance is offered the subset that means something without billing, so the panel never lists an event that cannot fire there.

Worker and risk alerts are deduplicated: a worker that stays down does not re-alert for six hours, and a risk alert only fires on an actual change of posture.

Delivery behaviour

Delivery is best effort and deliberately so. An alert never blocks or fails the request that produced it, and a chat server that is slow or unreachable is not allowed to slow the product down. There is no retry queue. If a channel is down when an event fires, that alert is lost.

If alerts stop arriving, use Test first: it is synchronous and tells you exactly what the transport said.

On this page