> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kaireonai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Notifications

> CRUD and test endpoints for notification destinations (Slack, Teams, outbound webhook, ops email).

<Note>
  **See also**: [Notifications concept and configuration](/operations-reporting/notifications) for what this API powers, when to call it, and how it is configured.
</Note>

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](../operations-reporting/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

```json theme={null}
{
  "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

| Field     | Type    | Required | Description                                                 |
| --------- | ------- | -------- | ----------------------------------------------------------- |
| `kind`    | string  | Yes      | One of `slack`, `teams`, `webhook`, `ops_email`             |
| `name`    | string  | Yes      | Human-readable label (1–120 chars)                          |
| `config`  | object  | Yes      | Kind-specific config (validated against the adapter schema) |
| `enabled` | boolean | No       | Defaults to `true`                                          |

### Config shapes

<AccordionGroup>
  <Accordion title="kind: slack">
    ```json theme={null}
    { "webhookUrl": "https://hooks.slack.com/services/T/B/XYZ" }
    ```
  </Accordion>

  <Accordion title="kind: teams">
    ```json theme={null}
    { "webhookUrl": "https://outlook.office.com/webhook/..." }
    ```
  </Accordion>

  <Accordion title="kind: webhook">
    ```json theme={null}
    {
      "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.
  </Accordion>

  <Accordion title="kind: ops_email">
    ```json theme={null}
    {
      "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.
  </Accordion>
</AccordionGroup>

### Response (201)

Returns the created record (without the `config` blob — call `GET :id` for the redacted view).

```json theme={null}
{
  "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

* `422` — `config` failed the adapter's schema (e.g., non-HTTPS webhook URL).
* `400` — `kind` 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

| Field     | Type    | Description                                                      |
| --------- | ------- | ---------------------------------------------------------------- |
| `name`    | string  | Rename destination                                               |
| `enabled` | boolean | Pause / resume                                                   |
| `config`  | object  | Merged 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 a connection probe against the configured provider. **Admin only.**

### Response (200 on success, 502 on adapter failure)

```json theme={null}
{ "success": true, "detail": "Test message sent to Slack." }
```

```json theme={null}
{ "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

| Field          | Type      | Required | Description                      |
| -------------- | --------- | -------- | -------------------------------- |
| `providerIds`  | string\[] | Yes      | 1–20 notification provider UUIDs |
| `notification` | object    | Yes      | Notification payload (below)     |

### Notification payload

```json theme={null}
{
  "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:

```json theme={null}
{
  "results": [
    { "providerId": "...", "kind": "slack", "success": true, "providerMessageId": "slack-1714..." },
    { "providerId": "...", "kind": "webhook", "success": false, "error": "Webhook returned 500" }
  ]
}
```
