Skip to content
cronpad
Alerts / Alert channels

Alert channels

A channel is a destination for alerts. cronpad supports email and webhooks; webhook channels can format their body for Slack or Discord incoming webhooks, or send a generic signed JSON payload for your own systems. Every channel has a Send test button (POST /api/v1/alert-channels/{id}/test).

Email

{"kind": "email", "name": "On-call", "config": {"to": ["oncall@example.com"]}}
  • Verification links expire after 24 hours. Use Resend verification (POST /api/v1/alert-channels/{id}/verify) if a link expires. Changing the recipient list requires every address to verify again.
  • Every address must be verified: cronpad emails a confirmation link, and the channel only sends after it’s clicked. This prevents cronpad from being used to email people who didn’t ask for it.
  • Remote SMTP servers must support STARTTLS; loopback SMTP relays may use plaintext.
  • Self-hosted servers need SMTP settings in [alerts.email].

Slack and Discord

Create an incoming webhook in Slack or Discord, then:

{"kind": "webhook", "name": "#ops", "config": {"url": "https://hooks.slack.com/services/T000/B000/XXXX", "format": "slack"}}

Use "format": "discord" for Discord webhook URLs. Messages include the event, job name, run time, attempts, last error and a link to the run in the dashboard.

Generic webhook

{"kind": "webhook", "name": "PagerDuty bridge", "config": {"url": "https://alerts.example.com/cronpad", "format": "generic"}}

cronpad sends a POST with this body:

{
  "event": "run.failed",
  "occurred_at": "2026-11-10T03:31:12Z",
  "workspace_id": "ws_01J9X…",
  "job": {"id": "job_01J9ZK3Q…", "name": "nightly-report", "tags": ["reports"]},
  "run": {
    "id": "run_01J9ZM1A…",
    "scheduled_at": "2026-11-10T03:30:00Z",
    "status": "failed",
    "attempts": 3,
    "last_error": "HTTP 503: upstream unavailable"
  },
  "suppressed_count": 0,
  "url": "https://app.cronpad.com/runs/run_01J9ZM1A…"
}

Requests are signed exactly like job webhooks (Standard Webhooks headers), with a per-channel signing secret shown when you create the channel. See Verify signatures.

Delivery

  • Deliveries use a stable webhook-id across retries. Receivers should deduplicate this ID: a restart after delivery but before recording success can repeat a request.
  • Alerts are sent from a durable outbox and retried with backoff up to 8 times if the channel is down.
  • suppressed_count tells you how many identical alerts were held back by the rule’s cooldown since the last one was sent.