Predict.aiDocs
Notifications

Channels

Deliver notifications to Slack, Teams, PagerDuty, or your own webhook.

A channel endpoint is a delivery target you configure — a Slack incoming-webhook URL, a Teams workflow URL, a PagerDuty routing key, or any HTTPS URL of your own. When an event fires with that channel enabled in your preferences, the notification fans out to every enabled endpoint of the matching type.

typeconfigNotes
slack{ "url": … }Must be a hooks.slack.com incoming-webhook URL. Delivered as a Block Kit message with a severity color.
teams{ "url": … }A Teams Workflows (or legacy connector) webhook URL. Delivered as an Adaptive Card.
pagerduty{ "routing_key": … }An Events API v2 integration key. Retries of the same event collapse into one incident.
webhook{ "url": …, "secret": … }Any public HTTPS URL. secret is optional and enables request signing.

in_app, email, and websocket are built in — they need no endpoint and don't appear here. You can create up to 20 endpoints per account.

List endpoints

curl "$API_BASE/v1/notifications/channels" \
  -H "Authorization: Bearer $TOKEN"
{
  "data": {
    "items": [
      {
        "channel_id": "nch_9A4F72C1E08B4D3AA65201",
        "type": "slack",
        "label": "Data team Slack",
        "enabled": true,
        "config_hint": "hooks.slack.com (…XwZq)",
        "has_secret": false,
        "created_at": "2026-07-01T14:22:10+00:00",
        "updated_at": "2026-07-01T14:22:10+00:00",
        "last_result": { "at": "2026-07-14T18:05:44+00:00", "ok": true, "detail": "HTTP 200" }
      }
    ]
  }
}

Full URLs and secrets never come back — config_hint is a masked recognizer, and last_result reflects the most recent delivery attempt so you can spot a broken endpoint at a glance.

Create an endpoint

curl -X POST "$API_BASE/v1/notifications/channels" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "webhook",
    "label": "Ops receiver",
    "config": {
      "url": "https://ops.example.com/hooks/predictai",
      "secret": "whsec_k3H9…"
    }
  }'
{
  "data": {
    "channel": {
      "channel_id": "nch_2D81B6F09C3E4A57B41830",
      "type": "webhook",
      "label": "Ops receiver",
      "enabled": true,
      "config_hint": "ops.example.com (…ctai)",
      "has_secret": true,
      "created_at": "2026-07-15T10:02:19+00:00",
      "updated_at": "2026-07-15T10:02:19+00:00",
      "last_result": null
    }
  }
}

Request body

FieldMeaning
type requiredslack, teams, pagerduty, or webhook.
config requiredThe type's config from the table above — a url, or routing_key for PagerDuty, plus an optional secret for webhooks.
label optionalDisplay name.
enabled optionalPass false to create the endpoint paused. Defaults to true.

Errors

StatusWhyExample message
400Unknown type"type must be one of ['pagerduty', 'slack', 'teams', 'webhook']"
400URL missing, not HTTPS, or not a public host"Webhook URL must use https"
400Slack URL isn't an incoming webhook"Slack URL must be a hooks.slack.com incoming-webhook URL"
400Routing key too short to be real"PagerDuty integration (routing) key looks invalid"
400Already at 20 endpoints"Endpoint limit reached (20)"

Update an endpoint

Send only what you're changing:

FieldMeaning
label optionalRename the endpoint.
enabled optionalPause (false) or resume (true) delivery.
config optionalPartial too — omit url or secret and the stored value is kept.
curl -X PUT "$API_BASE/v1/notifications/channels/nch_2D81B6F09C3E4A57B41830" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": false }'

Returns 200 with the updated channel object. Config updates are partial too: omit url or secret and the stored value is kept (you never received the full value back, so you can't be expected to resend it). Changing the config clears last_result — health is unknown until the next delivery or test. An unknown channel_id returns 404 with "Endpoint not found".

Delete an endpoint

curl -X DELETE "$API_BASE/v1/notifications/channels/nch_2D81B6F09C3E4A57B41830" \
  -H "Authorization: Bearer $TOKEN"
{ "data": { "deleted": "nch_2D81B6F09C3E4A57B41830" } }

Deleting an endpoint doesn't touch your preferences — events that route to that channel type simply have one fewer place to go.

Test an endpoint

Synchronously pushes a canned message — titled "Test notification from Predict.ai" — through the endpoint and reports the result:

curl -X POST "$API_BASE/v1/notifications/channels/nch_9A4F72C1E08B4D3AA65201/test" \
  -H "Authorization: Bearer $TOKEN"
{ "data": { "ok": true, "detail": "HTTP 200" } }

If the delivery fails, the response is 502 with the reason — e.g. { "data": { "ok": false, "detail": "HTTP 404: no service" } } or "timed out". Either way, the attempt is stamped onto the endpoint's last_result. Deliveries time out after 6 seconds.

Webhook payloads

Generic webhook endpoints receive a JSON POST per notification:

{
  "delivery_id": "dlv_3f9c02ab714e58d0",
  "event_code": "deployment.failed",
  "category": "deployments",
  "severity": "critical",
  "title": "Deployment failed",
  "body": "Daily sales forecaster failed to deploy: capacity check failed.",
  "link": "https://app.predict.ai/workspaces/8b1f3c2a-…/deployments/c47d…",
  "metadata": { "deployment_id": "c47d…", "workspace_id": "8b1f3c2a-…" },
  "sent_at": "2026-07-15T10:11:38+00:00"
}

Each request carries identifying headers:

HeaderValue
X-PredictAI-EventThe event_code, e.g. deployment.failed
X-PredictAI-DeliveryUnique per delivery, e.g. dlv_3f9c02ab714e58d0
X-PredictAI-Signaturesha256=<hex> — only when the endpoint has a secret
User-AgentPredictAI-Notifications/1.0

To verify a signed request, compute HMAC-SHA256 of the raw request body with your secret and compare against the header:

import hashlib, hmac

expected = "sha256=" + hmac.new(
    secret.encode(), raw_body, hashlib.sha256
).hexdigest()
valid = hmac.compare_digest(expected, request.headers["X-PredictAI-Signature"])

Respond with any 2xx within 6 seconds. Delivery is fire-and-forget — a failed attempt is recorded on last_result but not retried, so keep your receiver fast and treat the feed as the source of truth.

On this page