# Alerts via Telegram, Slack, email and webhooks

> Each workspace connects its own Telegram bot, Slack webhook, email sender (SMTP/Resend) or HTTPS webhook, then sets rules.

Alerts tell your team about new issues, regressions and spikes. **Each workspace connects its own senders** — your Telegram bot, your Slack webhook, your email account, or your own HTTPS endpoint. Belvador has no shared default sender, so messages come from your name and your provider's limits apply.

Alerts live under **Alerts** in a workspace. Owners and admins manage them; adding, editing or deleting a destination asks for your authenticator code.

## 1. Add a destination

**Destinations** are where alerts are delivered. Choose **Add destination**, give it a name, pick the projects it may receive, then one of:

### Telegram

1. In Telegram open **@BotFather**, send `/newbot` and follow the prompts. Copy the token it gives you.
2. Paste it as **Bot token** (it looks like `123456789:AA…`) and choose **Check bot**. Belvador shows **Bot found: @yourbot**.
3. Show the bot where to send alerts:
   - **Open Telegram** (or scan the QR code with your phone) to start a private chat with the bot, or
   - **Add to a group**, then in the group send the message Belvador shows.
4. Belvador waits for that message and shows the chat it found — private chat, group or channel.
5. For a channel, or a bot that already uses a webhook, choose **Enter the chat ID instead**. Group and channel IDs start with `-100`.

Before saving, Belvador sends a “connected” message to that chat. The bot token is stored encrypted and used only to send alerts.

### Slack

1. In Slack: **Apps → Incoming Webhooks → Add to Slack**, pick a channel and copy the webhook URL.
2. Paste it as **Webhook URL** — it starts with `https://hooks.slack.com/services/`.

Belvador sends a confirmation message to the channel before saving.

### Email

Choose how to send:

| Send with | You enter |
|---|---|
| **SMTP account** | Provider (presets for common providers, or **Other provider**), **SMTP server**, **Port** — 465 for TLS, 587 for STARTTLS — **Username** and **Password** |
| **Resend** | A **Resend API key** with “Sending access” |

Then the **From** address (a display name in front is fine) and up to 10 recipient **Addresses**.

- For SMTP, use an **app password**, not your normal password; the account needs 2-step sign-in. Belvador never sends a password without encryption.
- With Resend, the From address must be on a domain verified in Resend.
- Microsoft 365: your admin must allow SMTP sign-in for the mailbox. Outlook.com accounts only allow Microsoft sign-in, which is not supported yet.

Belvador first sends a test email to you; the destination is saved only if your mail server accepts it. Each recipient then gets a confirmation email and must choose **Confirm this address** before alerts reach them — your own sign-in address is confirmed automatically. Every alert email has a **Stop these emails** link.

The destination shows how many emails were sent today and warns when you approach your provider's daily limit.

### Webhook

Paste the HTTPS **Endpoint URL** of your own system. Belvador sends one signed test event first and saves only if it answers `2xx`, then shows the signing secret once. Every alert arrives as signed JSON in the Standard Webhooks format — see [Custom webhooks](https://belvador.dev/en/docs/alerts/webhooks) for verification code, event types and retries.

### PagerDuty and incident.io

For on-call paging, connect an on-call tool instead of a chat:

- **PagerDuty** — in PagerDuty open **Service → Integrations → Events API v2** and copy the **Integration key** (32 characters); pick your account's region (US or EU).
- **incident.io** — in incident.io open **Alerts → Sources → HTTP**, create a source and copy its **Alert source ID** (26 characters) and **Source token**.

Belvador sends one test alert and resolves it straight away before saving. These destinations receive [incidents](https://belvador.dev/en/docs/incidents) as one page each — opened, acknowledged (PagerDuty), resolved — rather than one page per alert, and are never held by quiet hours.

## 2. Create a rule

**Rules** decide which errors are worth a message. Choose **New rule**:

| Field | Options |
|---|---|
| **Alert on** | **Errors**, **Connection problems**, **Monitor incidents**, **Uptime checks** or **SLOs** (see below) |
| **When** | **New issue**, **Regression** (a resolved issue came back), **Escalating** (a sudden rise) |
| **Projects** | All projects, or the ones you pick |
| **Minimum level** | **Warning or higher**, **Error or higher**, **Fatal only** |
| **Environments** | Comma separated, such as `production`. Empty = every environment |
| **Don't repeat for** | Minutes before the same issue can alert again |
| **Destinations** | One or more destinations from step 1 |

Saving asks you to confirm.

## Connection problem alerts

Every workspace also starts with the default rule **SDK connection problems**. It sends one message when Belvador opens a [connection problem](https://belvador.dev/en/docs/sdk/verify#connection-problem-codes) for a project — a revoked key still in use, errors from a blocked origin, errors dropped by limits, server code outside Belvador's middleware — and one **Connection OK again** message when the problem closes. A problem that comes back within 6 hours reopens quietly instead of alerting again. Messages name the project and the problem and link to its **Connection** tab; they never contain error messages, page addresses or keys.

To add another rule like it, choose **New rule → Alert on → Connection problems**. Minimum level, environments and **Don't repeat for** do not apply. Turning the rule off stops the messages; the Connection tab still shows every problem.

## Monitor alerts

The default rule **Monitor problems** sends one message when a [monitor](https://belvador.dev/en/docs/monitors/overview) — including a [ping URL monitor](https://belvador.dev/en/docs/monitors/heartbeat) — starts failing — a missed run, a failed run, a run over its maximum runtime, or a result that needs review — and one **Recovered** message when it is healthy again. A change from one kind of failure to another does not send a new message. Messages name the monitor, project, environment, schedule and the last healthy run, and link to the monitor; they never contain error messages, keys, user ids or trace ids. When the node was offline during the problem, the message says it was detected late.

To narrow it, choose **New rule → Alert on → Monitor incidents** and pick the incident kinds, projects, environments and **Don't repeat for**. A muted monitor sends nothing, whatever the rules say; its incidents still show on the page.

## Uptime alerts

The default rule **Uptime problems** sends one message when an [uptime check](https://belvador.dev/en/docs/uptime/quickstart) goes down — failing from most regions — and one **Back up** message when it is reachable again, plus at most one warning a day while its HTTPS certificate is close to expiry. Messages name the check, project, environment, target without its query string, the failure reason and the failing regions; they never contain response bodies or headers.

To narrow it, choose **New rule → Alert on → Uptime checks** and pick projects, environments and **Don't repeat for**. A muted check keeps checking and recording but sends nothing.

## SLO alerts

The default rule **SLO burn** sends one message when an [SLO](https://belvador.dev/en/docs/slos) starts burning its error budget too fast — a fast burn pages, a slow burn opens a ticket — and one when it is back within budget. An SLO with too little data sends nothing rather than a guess.

To narrow it, choose **New rule → Alert on → SLOs** and pick the severities, projects, environments and **Don't repeat for**. Paused or muted SLOs send nothing. Thresholds and windows: [Burn-rate alerts](https://belvador.dev/en/docs/slos/alerts).

## Status and history

Each destination shows **Waiting**, **Active**, **Failing** or **Disabled**. **Failing** means the provider refused recent messages — a revoked bot token, a removed webhook, a changed mail password. Update the destination to fix it; **Attempts** on a destination lists each try with its HTTP status, time taken and the provider's reply.

The delivery history lists time, event, destination and status:

| Status | Meaning |
|---|---|
| **Sent** | Accepted by the provider (HTTP 2xx or the mail server's OK). It does not mean someone has read it |
| **Queued** | Waiting to be sent |
| **Throttled** | Skipped because the same issue alerted recently (**Don't repeat for**) |
| **Retrying** | The provider failed; Belvador tries again |
| **Failed** | Gave up after retrying, or the receiver refused it for good. Owners and admins can **Send again** within 7 days |
| **Held** | Waiting for the end of quiet hours or for the next digest ([notification policies](https://belvador.dev/en/docs/alerts/policies)) |
| **In digest** | Sent as one line of a digest message |

A **late** mark means the message went out later than usual, for example after the node reconnected.

Related alerts can be grouped into one [incident](https://belvador.dev/en/docs/incidents) with one message per destination, and a [notification policy](https://belvador.dev/en/docs/alerts/policies) adds quiet hours, digests, a fallback chain when a destination keeps failing, and escalation when nobody takes an incident.
