> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getmcpulse.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Channels

> Four destinations on /settings/channels. Two are yours, two are the account's, and delivery is the intersection of what a rule uses and what you accept.

**Channels are destinations. [Alerts](/alerts/rules) are rules.** A rule says how loud it is; a person says what they are willing to hear; a notification arrives only where the two agree.

|             | Scope         | Config                  | Delivery              | Sending? |
| ----------- | ------------- | ----------------------- | --------------------- | -------- |
| **In-app**  | Yours         | none                    | One row per recipient | ✓        |
| **Email**   | Yours         | none                    | One row per recipient | Queued   |
| **Slack**   | The account's | Webhook URL, admin only | **Once per firing**   | Queued   |
| **Discord** | The account's | Webhook URL, admin only | **Once per firing**   | Queued   |

## Why two of them cannot be a personal preference

An incoming webhook posts to one fixed channel in one workspace. It is a single destination for the whole team — and posting the same message there once per team member is the same message five times.

So Slack and Discord are connected by an admin and used by rules; in-app and email are per person, per account.

## A webhook URL never comes back

The API returns a masked hint — `…/T01ABCDEF/B02GHIJKL/xyzS••••••••` — enough to recognise which webhook it is, useless to anyone who reads the response. The same rule [API keys](/api-keys/create) follow, for the same reason: an endpoint that hands a credential back turns every read of that page into a way to take it.

## The host is checked

The stored URL is fetched server-side, so accepting an arbitrary one would make the API a request forwarder pointed wherever the caller likes — at an internal address, or at a cloud metadata endpoint. Pinning the host to the provider's own is the cheap half of not building an SSRF.

It also catches the ordinary mistake: pasting the app page instead of the webhook, which would otherwise be a connection that silently never posts.

## A rule may name a channel nobody has connected

The evaluator finds no connection and delivers nothing there. It does not error, and it does not invent a destination.

Hiding the option until the account wires it up would mean setting the alert up twice — once before connecting and once after.

## Only in-app actually sends

Email, Slack and Discord record deliveries as `queued`, and nothing drains them yet.

Every channel carries a `delivers` flag through the API, and the page shows **"Not sending yet"** where it is false. A toggle that silently does nothing is the worst control on any page, and the honest version costs one boolean.

## The inbox is the delivery record

There is no separate notifications table. A notification **is** a delivery — two records for it could disagree about whether you were told.

Deliveries are fanned out when a rule fires, not resolved when you open the inbox: the audience is who was on the team at that moment, and working it out on read would quietly rewrite history every time somebody joined or left.

`GET /v1/account/inbox` reads it; `POST /v1/account/inbox/read` marks items read, by id or `{ "all": true }`.

## Reading the catalogue

`GET /v1/account/channels` returns **the catalogue as well as** the stored preferences — every destination's label, its sentence, and whether it `delivers` yet. So the [MCP server](/mcp/overview) can answer "what am I being told through" without a second copy that drifts.

`PUT /v1/account/channels` merges: only the switches you send are changed.

## Related

* [Alert rules](/alerts/rules)
* [The weekly digest](/alerts/digest)
