- Polling. A cron job calls
GET /v1/alertsand walks pages until it sees anidyou’ve already stored. - Webhook. Register an endpoint via
POST /v1/webhooksand let Signa push alerts to you. - Webhook + reconciliation. Push for low latency, then periodically call
POST /v1/alerts/lookupwith the IDs you’ve persisted to confirm nothing was lost during a receiver outage.
Deduplicate by alert ID
Alerts are immutable, but the samealert.created event can arrive at your endpoint multiple times across retries and redeliveries. Use the webhook-id header (which equals the alert’s prefixed ID, alt_*) as your idempotency key.
processing -> done state and only flip to done after the side effect returns success.
Polling pattern
GET /v1/alerts endpoint accepts:
| Parameter | Type | Notes |
|---|---|---|
limit | number | 1..100, default 20. |
cursor | string | Opaque cursor from the previous response. |
severity | normal | high | critical | Filter by severity. |
event_type | string | One of the three event types. |
epoch | all | current | all (default) includes alerts from prior query revisions/replays. Set to current to keep only alerts from each watch’s current evaluation_epoch. |
Reconciliation pattern
For defense-in-depth on top of webhooks, run a daily job that asks Signa “did you ever fire these IDs?” — useful when you suspect a webhook outage.alerts.lookup() takes an array of 1-100 prefixed alert IDs (alt_*) per call:
alt_* ID — fail the whole request with 400 validation_error, listing each bad entry by index. Well-formed but unknown IDs, and IDs that belong to another organization, are silently dropped from the result. Any gap between the IDs you sent and the alerts you got back is real.
Severity-based routing
A typical production setup has two cron jobs:| Cadence | Filter | What it does |
|---|---|---|
| 1/min | severity=critical | Pages on-call. |
| 1/hour | (no filter) | Catches normal and high for the daily review queue. |