Destinations
Destinations receive alert notifications. Connect them under Monitoring → Destinations. A workspace can have several of each kind; each has a Test. contract.dev channels lists, tests, enables, disables and removes them.
Default monitors notify every destination, including ones connected later, until narrowed on the monitor’s page. Custom monitors notify the destinations chosen when they are created.
Telegram
Select Add to a group or Message the bot and choose the chat. The destination appears once the chat is linked.
Slack
Select Add to Slack and choose the channel during authorization. One authorization is one channel.
Discord
Select Add to a server to add the contract.dev bot, then choose the channel. One install covers the server.
Webhook
New webhook destinations are not offered. Existing ones keep receiving a signed JSON POST for each notification, as follows. They do not appear under Destinations; contract.dev channels lists them and can test or remove them.
Headers
| Header | Value |
|---|---|
Content-Type | application/json |
X-Contract-Dev-Event | The event name (below) |
X-Contract-Dev-Signature | sha256= followed by the hex HMAC-SHA256 of the raw body, keyed with the destination’s secret |
User-Agent | contract.dev-alerts/1 |
Events
| Event | When |
|---|---|
invariant.warning | The episode opened at the warning line |
invariant.breached | The episode opened at, or was already at, the alert line |
invariant.escalated | An open warning crossed the alert line |
invariant.still_breached | Hourly reminder while alerting and unacknowledged |
invariant.resolved | The value returned to healthy |
Body
{
"type": "invariant.breached",
"level": "alert",
"title": "ETH buffer fell below 25,000 ETH",
"incident": {
"id": "cmfz1k2a80001abcd…",
"kind": "breach",
"level": "alert",
"peakLevel": "alert",
"openedAt": "2026-09-20T08:42:11.000Z",
"alertedAt": "2026-09-20T08:51:03.000Z",
"resolvedAt": null,
"notifyCount": 1,
"inputs": {
"eth_buffer": { "raw": "24811000000000000000000", "at": "2026-09-20T08:51:03.000Z", "block": "23456789" }
},
"alertInputs": null
},
"invariant": {
"id": "cmfz0x9d40007wxyz…",
"name": "ETH buffer",
"exprText": "eth_buffer >= 25000",
"warnExprText": "eth_buffer >= 30000",
"metricId": "cmfyzq1e20003pqrs…"
},
"url": "https://app.contract.dev/metrics/cmfyzq1e20003pqrs…"
}inputs is keyed by the rule’s aliases, derived from metric labels, each with the raw value, its timestamp and, where available, its block. exprText is the alert assertion; the monitor is Healthy while it holds. For a default monitor, inputs carries the reading instead: the contract, the sentence it was judged on, the numbers behind it and the transactions it names.
Verify by computing HMAC-SHA256 over the raw body with the destination’s secret and comparing to the header in constant time. Non-2xx responses are retried with backoff up to eight times. Redirects are not followed.
Notes
Delivery is send-only; acknowledge from the app or CLI. Connecting, testing and removing destinations requires an owner or admin.
contract.dev channels lists destinations; monitor add --to accepts their ids, labels or kinds.