Skip to main content
Notification destinations are tenant-scoped provider configurations that receive operational notifications (alert fires, scheduled reports). Configurations are stored encrypted in the platform setting vault. See Platform — Notifications for the operator guide. All endpoints require tenant context (X-Tenant-Id or authenticated session) and the X-Requested-With: XMLHttpRequest header on mutating requests.

GET /api/v1/notifications/providers

List all notification destinations for the tenant. Secrets are redacted (••••••••) in the returned config blobs. RBAC: viewer, editor, or admin.

Response

{
  "data": [
    {
      "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
      "kind": "slack",
      "name": "#ops-alerts",
      "enabled": true,
      "createdAt": "2026-04-17T10:00:00.000Z",
      "updatedAt": "2026-04-17T10:00:00.000Z",
      "config": { "webhookUrl": "••••••••" },
      "configSummary": "hooks.slack.com"
    }
  ],
  "kinds": [
    { "kind": "slack", "displayName": "Slack" },
    { "kind": "teams", "displayName": "Microsoft Teams" },
    { "kind": "webhook", "displayName": "Outbound Webhook" },
    { "kind": "ops_email", "displayName": "Ops Email (SES)" }
  ]
}

POST /api/v1/notifications/providers

Create a new destination. Admin only.

Request Body

FieldTypeRequiredDescription
kindstringYesOne of slack, teams, webhook, ops_email
namestringYesHuman-readable label (1–120 chars)
configobjectYesKind-specific config (validated against the adapter schema)
enabledbooleanNoDefaults to true

Config shapes

{ "webhookUrl": "https://hooks.slack.com/services/T/B/XYZ" }
{ "webhookUrl": "https://outlook.office.com/webhook/..." }
{
  "url": "https://alerts.example.com/ingest",
  "secret": "shared-hmac-secret",
  "headers": { "X-Token": "abc" }
}
secret and headers are optional. When secret is present, each POST includes X-Kaireon-Signature: sha256=<hex> over the body.
{
  "fromEmail": "ops-alerts@example.com",
  "toEmails": ["ops@example.com", "oncall@example.com"],
  "replyTo": "support@example.com"
}
Reuses the SES credentials from the platform’s email integration.

Response (201)

Returns the created record (without the config blob — call GET :id for the redacted view).
{
  "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "kind": "slack",
  "name": "#ops-alerts",
  "enabled": true,
  "createdAt": "2026-04-17T10:00:00.000Z",
  "updatedAt": "2026-04-17T10:00:00.000Z"
}

Errors

  • 422config failed the adapter’s schema (e.g., non-HTTPS webhook URL).
  • 400kind is not a recognized adapter.

GET /api/v1/notifications/providers/:id

Read one destination. Returns the redacted config. RBAC: viewer, editor, or admin.

PATCH /api/v1/notifications/providers/:id

Partial update. Admin only.

Request Body

FieldTypeDescription
namestringRename destination
enabledbooleanPause / resume
configobjectMerged into existing config; re-validated against adapter schema
When updating config, supply only the fields that changed. Unsupplied fields keep their current value. Secret-like fields left as the •••••••• placeholder are ignored.

DELETE /api/v1/notifications/providers/:id

Delete a destination. Admin only. Returns 204 on success. Alert rules that reference the deleted destination continue to evaluate but will log delivery_failed on their next fire.

POST /api/v1/notifications/providers/:id/test

Fire the adapter’s testConnection() probe. Admin only.

Response (200 on success, 502 on adapter failure)

{ "success": true, "detail": "Test message sent to Slack." }
{ "success": false, "error": "Slack returned 500: invalid_payload" }

POST /api/v1/notifications/send

Dispatch an ad-hoc notification to one or more destinations. Used by the alert-rule evaluator and scheduled reports; also callable by admins for testing. Admin only.

Request Body

FieldTypeRequiredDescription
providerIdsstring[]Yes1–20 notification provider UUIDs
notificationobjectYesNotification payload (below)

Notification payload

{
  "title": "Alert: acceptance rate drop",
  "body": "acceptance_rate < 0.05 (observed 0.04, baseline 0.08)",
  "severity": "warning",
  "fields": [
    { "label": "Observed", "value": "0.04" },
    { "label": "Threshold", "value": "0.05" }
  ],
  "sourceUrl": "https://app.kaireonai.com/dashboards/operations"
}
severity is one of info, warning, critical. fields and sourceUrl are optional.

Response

200 when at least one provider accepted the dispatch, 502 when every provider failed:
{
  "results": [
    { "providerId": "...", "kind": "slack", "success": true, "providerMessageId": "slack-1714..." },
    { "providerId": "...", "kind": "webhook", "success": false, "error": "Webhook returned 500" }
  ]
}