Skip to content

Notification channels

Get pinged in Slack, Discord, or Telegram when inbound mail arrives, emails bounce, deliverability dips, or a webhook auto-disables. Channels are sibling to webhooks — same retry + auto-disable guarantees, but PostStack does the formatting so the message is human-readable rather than a JSON blob.

Supported platforms

Slack

Uses Incoming Webhooks. In your Slack workspace, add the "Incoming Webhooks" app, pick the channel you want to post in, and copy the webhook URL.

text
config.webhookUrl  https://hooks.slack.com/services/T000/B000/abc123

Discord

Uses Discord webhooks. In your server, open the target channel → Edit Channel → Integrations → Webhooks → New Webhook → Copy URL.

text
config.webhookUrl  https://discord.com/api/webhooks/<id>/<token>

Telegram

Uses the Telegram Bot API. Message @BotFather, run /newbot, and copy the token it gives you. Add the bot to the target chat or channel, send any message, then call https://api.telegram.org/bot<token>/getUpdates to find the chat id.

text
config.botToken  123456789:ABCdef-GhIJklm_NopQRsTuvWXyz
config.chatId    -1001234567890

Events

Each channel subscribes to one or more event types. Subscribe to as many or as few as you want; only the events in events trigger a post to the channel.

  • inbound_email.received — new mail arrived at a mailbox under one of your verified domains
  • email.bounced — an outbound email hard- or soft-bounced
  • email.complained — the recipient flagged your email as spam
  • email.suppressed — an address was added to your suppression list
  • webhook.disabled — one of your webhook endpoints auto-disabled after 20 consecutive failures
  • domain.verification_failed — a domain failed re-verification
  • deliverability.degraded — deliverability metrics dropped below a healthy threshold

Scope

Channels target one of three scopes:

  • Team-wide (default, both domainId and mailboxId null) — fires for any matching event across the whole team.
  • Per-domain (domainId set) — fires only when the event relates to that domain.
  • Per-mailbox (mailboxId set) — fires only when inbound mail lands in that specific mailbox.

Multiple channels can match the same event — they all fire (stacking model, not most-specific-wins). Use this to route, e.g., your support@ mailbox to a customer- facing Slack channel and the team-wide email.bounced stream to an engineering Telegram chat at the same time.

API

POST
/notification-channels

Create a notification channel. The config shape varies per platform — pick one of slack | discord | telegram.

json
{
  "type": "telegram",
  "name": "Ops alerts",
  "events": ["email.bounced", "webhook.disabled"],
  "config": {
    "botToken": "123456789:ABCdef-GhIJklm_NopQRsTuvWXyz",
    "chatId": "-1001234567890"
  }
}
GET
/notification-channels

List all notification channels for your team. Secrets in config are masked.

json
{
  "channels": [
    {
      "publicId": "nc_abc...",
      "type": "telegram",
      "name": "Ops alerts",
      "events": ["email.bounced"],
      "active": true,
      "configSummary": { "botToken": "•••••", "chatId": "-1001234567890" },
      "consecutiveFailures": 0,
      "disabledAt": null,
      "lastUsedAt": "2026-05-27T09:32:11.000Z",
      "createdAt": "2026-05-27T10:00:00.000Z"
    }
  ]
}
PUT
/notification-channels/:publicId

Update a channel's name, events, scope, or config. Omitted config fields are preserved (so you can rotate just the bot token without re-supplying the chat id). Set enabled:true to re-enable an auto-disabled channel.

json
{
  "name": "Ops alerts (renamed)",
  "events": ["email.bounced", "email.complained"],
  "enabled": true
}
POST
/notification-channels/:publicId/test

Send a canned test notification to the channel. Useful for verifying the integration works without waiting for a real event.

json
{ "success": true, "statusCode": 200, "responseBody": "ok" }
DELETE
/notification-channels/:publicId

Delete a channel. The full delivery history is removed (cascade).

json
{ "success": true }

Retry & auto-disable

Failed deliveries retry with exponential backoff up to 8 attempts (30 s, 2 m, 10 m, 30 m, 2 h, 8 h, 16 h). Platform rate-limit 429 responses honour the platform's Retry-After hint instead of the default schedule. After 20 consecutive permanently-failed deliveries the channel auto-disables, the team owner gets an email, and an in-app notification appears in the dashboard bell. Re-enable from the dashboard or via PUT /notification-channels/:publicId with { "enabled": true } once the integration is healthy again.

Scopes

Two OAuth scopes guard the API: notifications:read for list/get/deliveries endpoints, notifications:manage for create/update/delete/test/replay. Granting notifications:manage implicitly grants :read.