Alert channels

Alerts always show in the console. An alert channel also sends them where your team works:

Type What you need
Slack The channel name or ID, and an incoming webhook URL for it
PagerDuty The integration (routing) key of a PagerDuty service. Optionally the PagerDuty API URL, and a client name and link shown in incidents
Webhook Any URL that accepts a JSON POST. Optionally a proxy, basic auth, or a token sent in the Authorization header

A fleet sends its alerts, and those of the workloads on it, to the channels in its configuration. Which alerts fire is set by the alert rules.

The API examples below share this setup:

export STREAMTIME_TOKEN=<your-access-token>
export API=https://api.example.com/organizations/<org>
import os
from streamtime_sdk.client import AuthenticatedClient

client = AuthenticatedClient(
    base_url="https://api.example.com",
    token=os.environ["STREAMTIME_TOKEN"],
)
ORG = "<org>"

Uses the generated client in streamtime-sdk/typescript/client.

import { client } from "./client/client.gen";

client.setConfig({
  baseUrl: "https://api.example.com",
  headers: { Authorization: `Bearer ${process.env.STREAMTIME_TOKEN}` },
});
const org = "<org>";
package main

import (
    "bytes"
    "crypto/rand"
    "encoding/hex"
    "encoding/json"
    "net/http"
    "os"
)

const api = "https://api.example.com/organizations/<org>"

// newKey returns a random idempotency key.
func newKey() string {
    b := make([]byte, 16)
    rand.Read(b)
    return hex.EncodeToString(b)
}

// call sends one request with the access token and a JSON body (or none).
// An optional idempotency key is sent as the Idempotency-Key header.
func call(method, path string, body any, idempotencyKey ...string) (*http.Response, error) {
    var buf bytes.Buffer
    if body != nil {
        if err := json.NewEncoder(&buf).Encode(body); err != nil {
            return nil, err
        }
    }
    req, err := http.NewRequest(method, api+path, &buf)
    if err != nil {
        return nil, err
    }
    req.Header.Set("Authorization", "Bearer "+os.Getenv("STREAMTIME_TOKEN"))
    req.Header.Set("Content-Type", "application/json")
    if len(idempotencyKey) > 0 {
        req.Header.Set("Idempotency-Key", idempotencyKey[0])
    }
    return http.DefaultClient.Do(req)
}

Add an alert channel

  1. Go to Settings → Alert Channels and select Create Alert Channel.
  2. Enter an Identifier and choose the Receiver Type.
  3. Slack: Channel and Webhook URL. PagerDuty: Routing Key, and optionally URL, Client and Client URL. Webhook: URL, and optionally Proxy URL, basic auth or Auth Token.
  4. Save.
curl -X POST "$API/alert-channels/" \
  -H "Authorization: Bearer $STREAMTIME_TOKEN" -H "Content-Type: application/json" \
  -d '{"identifier": "ops", "type": "slack",
       "receiver_config": {"receiver_type": "slack", "channel": "#operations",
                           "api_url": "https://hooks.slack.com/services/<path>"}}'

Then list it in a fleet’s configuration:

curl -X PATCH "$API/fleet/<fleet>/" \
  -H "Authorization: Bearer $STREAMTIME_TOKEN" -H "Content-Type: application/json" \
  -d '{"config": {"alert_channels": ["ops"]}}'

The fields each type takes: GET $API/alert-channels/configuration-profiles/.

from streamtime_sdk.api.alert_channels import organizations_alert_channels_create
from streamtime_sdk.models import AlertChannel

organizations_alert_channels_create.sync(
    ORG,
    client=client,
    body=AlertChannel.from_dict({
        "identifier": "ops",
        "type": "slack",
        "receiver_config": {
            "receiver_type": "slack",
            "channel": "#operations",
            "api_url": "https://hooks.slack.com/services/<path>",
        },
    }),
)
import { organizationsAlertChannelsCreate } from "./client";

await organizationsAlertChannelsCreate({
  path: { org_identifier: org },
  body: {
    identifier: "ops",
    type: "slack",
    receiver_config: {
      receiver_type: "slack",
      channel: "#operations",
      api_url: "https://hooks.slack.com/services/<path>",
    },
  },
});
resp, err := call("POST", "/alert-channels/", map[string]any{
    "identifier": "ops",
    "type":       "slack",
    "receiver_config": map[string]any{
        "receiver_type": "slack",
        "channel":       "#operations",
        "api_url":       "https://hooks.slack.com/services/<path>",
    },
})
if err != nil {
    return err
}
defer resp.Body.Close()
streamtime alert-channel create --config '{"identifier": "ops", "type": "slack",
  "receiver_config": {"receiver_type": "slack", "channel": "#operations",
                      "api_url": "https://hooks.slack.com/services/<path>"}}'
streamtime alert-channel config-schema   # the fields each type takes

Not available in MCP. MCP reads the alerts themselves: “Which alerts are firing on the payments fleet?”

variable "slack_webhook_url" {
  type      = string
  sensitive = true
}

resource "streamtime_alert_channel" "ops" {
  identifier = "ops"
  type       = "slack"
  receiver_config = jsonencode({
    api_url = var.slack_webhook_url
    channel = "#operations"
  })
}
terraform import streamtime_alert_channel.ops ops

The provider fills receiver_type from type when you leave it out. Webhook channels need url; PagerDuty channels need routing_key. The configuration is sensitive and kept in Terraform state. Changing the destination updates the channel in place; changing its identifier replaces it. terraform destroy removes the channel from Streamtime.

See streamtime_alert_channel.