Notification Channels
Where alerts are forwarded when they are created: a generic webhook (optionally HMAC-SHA256 signed), a Discord webhook, a Slack incoming webhook, or in-app.
Returns every notification channel of the workspace, newest first, active or not. The channel
config (URL, secret, headers) is not included; use GET /v1/alerts/channels/detail.
Authorization
ApiKeyAuth Send your API key as a bearer token: Authorization: Bearer sq_YOUR_API_KEY.
In: header
Response Body
application/json
application/json
curl -X GET "https://example.com/v1/alerts/channels"{ "channels": [ { "id": "1f2e3d4c-5b6a-4978-8a9b-0c1d2e3f4a5b", "name": "Slack #compliance", "channel_type": "SLACK", "is_active": true, "filter_severity": [ "HIGH", "CRITICAL" ], "filter_sources": null, "filter_entity_types": null, "created_at": "2026-09-01 09:00:00" } ]}Creates an active notification channel. From then on, every new alert whose severity, source and entity type pass the channel's filters is forwarded to it.
channel_type is upper-cased before validation. WEBHOOK, DISCORD and SLACK require a
config.url that is an https:// URL whose host resolves only to public addresses: loopback,
private, link-local and similar ranges are refused, and redirects are not followed when
delivering. The URL is checked again on every delivery; a refused one is recorded as a failed
delivery (Blocked destination: ...). IN_APP and EMAIL need no config (it defaults to {}).
IN_APP and EMAIL channels are stored but nothing is sent to them by the dispatcher: alerts
already appear in the web app, and no email is sent. Only WEBHOOK, DISCORD and SLACK
produce outbound requests and delivery records.
Filters are stored as given. Each one must be a JSON array of strings to take effect; null,
an omitted field, [], or any value that is not an array of strings means "match everything".
See CreateChannel for the matching rules.
Authorization
ApiKeyAuth Send your API key as a bearer token: Authorization: Bearer sq_YOUR_API_KEY.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
curl -X POST "https://example.com/v1/alerts/channels" \ -H "Content-Type: application/json" \ -d '{ "name": "Risk engine webhook", "channel_type": "WEBHOOK", "config": { "url": "https://hooks.example.com/seqlense", "secret": "whsec_5f2b8c0e1d", "headers": { "X-Team": "compliance" } }, "filter_severity": [ "HIGH", "CRITICAL" ], "filter_sources": null, "filter_entity_types": null }'{ "status": "ok", "id": "1f2e3d4c-5b6a-4978-8a9b-0c1d2e3f4a5b"}Permanently deletes a channel together with its delivery records (they disappear from the
deliveries of past alerts). Returns {"status":"ok"} even when the channel does not exist.
To stop deliveries but keep the history, set is_active to false instead.
Authorization
ApiKeyAuth Send your API key as a bearer token: Authorization: Bearer sq_YOUR_API_KEY.
In: header
Query Parameters
Channel ID.
uuidResponse Body
application/json
application/json
application/json
curl -X DELETE "https://example.com/v1/alerts/channels?id=497f6eca-6276-4993-bfeb-53cbbbba6f08"{ "status": "ok"}Updates a channel. Only the fields present in the body change; channel_type cannot be changed.
configreplaces the whole stored config (it is not merged), so send theurlandsecretagain when changing only the headers. ForWEBHOOK,DISCORDandSLACKit is validated as on creation (anhttps://URL on a public host),400otherwise.nameis trimmed but not length-checked here.- A filter can be cleared by sending
nullor[]; omitting it keeps the current value. is_active: falsepauses the channel without deleting it.
Authorization
ApiKeyAuth Send your API key as a bearer token: Authorization: Bearer sq_YOUR_API_KEY.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
curl -X PUT "https://example.com/v1/alerts/channels" \ -H "Content-Type: application/json" \ -d '{ "id": "1f2e3d4c-5b6a-4978-8a9b-0c1d2e3f4a5b", "is_active": false }'{ "status": "ok"}Returns one channel including its config exactly as stored. For a signed webhook this includes
the secret in clear, so treat this response as sensitive.
Authorization
ApiKeyAuth Send your API key as a bearer token: Authorization: Bearer sq_YOUR_API_KEY.
In: header
Query Parameters
Channel ID.
uuidResponse Body
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/alerts/channels/detail?id=497f6eca-6276-4993-bfeb-53cbbbba6f08"{ "id": "1f2e3d4c-5b6a-4978-8a9b-0c1d2e3f4a5b", "name": "Risk engine webhook", "channel_type": "WEBHOOK", "config": { "url": "https://hooks.example.com/seqlense", "secret": "whsec_5f2b8c0e1d", "headers": { "X-Team": "compliance" } }, "filter_severity": [ "HIGH", "CRITICAL" ], "filter_sources": null, "filter_entity_types": null, "is_active": true, "created_at": "2026-09-01 09:00:00", "updated_at": "2026-09-12 16:45:20"}Creates a real alert (source: system-test, severity: INFO, title Test alert, no entity,
metadata {}) and dispatches it exactly like any other alert.
Two consequences worth knowing:
- The test alert goes to every active channel whose filters match, not only the one named
by
id. Theidis only checked to exist. - The named channel itself receives nothing if its filters exclude
INFOor thesystem-testsource.
The test alert stays in the alert list with status OPEN (resolve or delete it afterwards).
Its deliveries in GET /v1/alerts/detail?id=<test_alert_id> show what each channel returned.
Authorization
ApiKeyAuth Send your API key as a bearer token: Authorization: Bearer sq_YOUR_API_KEY.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/alerts/channels/test" \ -H "Content-Type: application/json" \ -d '{ "id": "1f2e3d4c-5b6a-4978-8a9b-0c1d2e3f4a5b" }'{ "status": "ok", "test_alert_id": "8b9c0d1e-2f3a-4b5c-9d6e-7f8a9b0c1d2e"}