Alerts
Webhook/email/push alert rules evaluated on a 5-minute cron, plus firing history.
These endpoints accept a Bearer API key or a dashboard session cookie (requireSession) — see Authentication. They’re mounted twice: at the plain paths below (key-scoped to the key’s own project) and at /api/orgs/:orgSlug/projects/:projectSlug/alerts (session-scoped, used by the dashboard). Both mounts run the same handler.
GET /api/alerts
List alert rules for the project. Also available at /api/orgs/:orgSlug/projects/:projectSlug/alerts.
Auth: API key (Bearer) or session cookie
Response 200
{
"rules": [
{
"id": "alr_01hxyz",
"project_id": "proj_01abc",
"name": "High error rate",
"condition_field": "level",
"condition_value": "error",
"threshold": 20,
"window_minutes": 15,
"webhook_url": "https://hooks.example.com/scrywatch",
"notify_type": "webhook",
"notify_email": null,
"cooldown_minutes": 15,
"enabled": 1,
"last_triggered_at": 1720478000000,
"created_by": "user_01abc",
"created_at": 1720392000000
}
]
}
enabled is 0/1 (D1 has no boolean type). notify_type is webhook | email | push.
POST /api/alerts
Create an alert rule. Also available at /api/orgs/:orgSlug/projects/:projectSlug/alerts.
Auth: API key (Bearer) or session cookie · Content-Type: application/json
Request body
| field | type | required | description |
|---|---|---|---|
| name | string | yes | |
| condition_field | string | yes | |
| condition_value | string | yes | |
| threshold | number | yes | |
| window_minutes | number | yes | |
| webhook_url | string | if notify_type is webhook (the default) | Must be https://, and must not target localhost/loopback/RFC1918/link-local hosts |
| notify_type | string | no | webhook (default) | email | push |
| notify_email | string | if notify_type is email | |
| cooldown_minutes | number | no | Default 15 |
Response 201
{ "id": "alr_01hxyz" }
Errors: 400, shape { "error": "<message>" }:
"Missing required fields"— one ofname/condition_field/condition_value/threshold/window_minutesis absent"Webhook URL is required for webhook alerts""Email address is required for email alerts""Webhook URL must be a valid URL"/"Webhook URL must use HTTPS"/"Webhook URL must not target private or local addresses"
PATCH /api/alerts/:id
Update an alert rule. Also available at /api/orgs/:orgSlug/projects/:projectSlug/alerts/:id.
Auth: API key (Bearer) or session cookie
Request body — any subset of: name, condition_field, condition_value, threshold, window_minutes, webhook_url, notify_type, notify_email, cooldown_minutes, enabled. If webhook_url is included it’s validated with the same rules as POST /api/alerts.
Response 200
{ "ok": true }
Errors:
404—{ "error": "Not found" }if no rule with that ID exists in this project400—{ "error": "<message>" }— same webhook URL validation errors asPOST /api/alerts, ifwebhook_urlis provided and invalid404—{ "error": "Not found or no changes" }if the update matched the rule but touched zero columns (e.g. an empty body)
DELETE /api/alerts/:id
Delete an alert rule. Also available at /api/orgs/:orgSlug/projects/:projectSlug/alerts/:id.
Auth: API key (Bearer) or session cookie
Response 200
{ "ok": true }
Errors: 404 — { "error": "Not found" } if no rule with that ID exists in this project
GET /api/alerts/history
Recent alert firings for the project. Also available at /api/orgs/:orgSlug/projects/:projectSlug/alerts/history.
Auth: API key (Bearer) or session cookie
Response 200
{
"history": [
{
"id": "alh_01hxyz",
"project_id": "proj_01abc",
"rule_id": "alr_01hxyz",
"triggered_at": 1720478000000,
"event_count": 23,
"webhook_status": null
}
]
}
Returns the most recent 20 firings for the project, ordered by triggered_at descending — there is no limit/offset query param on this route. webhook_status is currently always null — the alerts cron (insertAlertHistory in packages/worker/src/cron/alerts.ts) does not perform a webhook HTTP call or record its delivery status.
Common responses (401; 402 and 429 don’t apply to these endpoints) — see Authentication.