---
title: "Kanäle"
description: "Paging-Kanäle im Incident Management (Webhook, Slack, E-Mail) auflisten, anlegen, ändern und löschen, inklusive der Nur-Schreiben-Behandlung von Webhook-URLs und Headern."
---

`GET /api/im/channels` · `POST /api/im/channels` · `GET /api/im/channels/:id` · `PATCH /api/im/channels/:id` · `DELETE /api/im/channels/:id`

Ein **Kanal** ist ein gemeinsames Paging-Ziel deiner Organisation: ein generischer Webhook, ein eingehender Slack-Webhook oder eine E-Mail-Adresse. Ein Kanal gilt entweder organisationsweit (`teamId: null`) oder gehört zu einem [Team](/de/api/incident-management/teams). Ein Kanal kann in den [Organisationseinstellungen](/de/api/incident-management/org-settings) als Fallback-Kanal der Organisation gesetzt werden, als letzte Instanz, wenn einer Eskalation die Stufen ausgehen.

## Authentifizierung

Erfordert den Basiszugriff auf Incident Management, den jeder Endpunkt dieser API braucht (eine IM-berechtigte Rolle `admin`, `editor` oder `responder`, oder ein organisationsweites API-Token; Incident Management muss für die Organisation aktiviert sein). Lesen darf jede IM-berechtigte Rolle. Einen organisationsweiten Kanal zu **schreiben** erfordert die Rolle `admin`. Einen Team-Kanal zu schreiben erfordert die Rolle `admin` oder eine Team-Admin-Mitgliedschaft in diesem Team. Ein organisationsweites API-Token läuft mit der Rolle der Person, die es erstellt hat; ein Token, das ein Organisations-Admin erstellt hat, darf also jeden Kanal schreiben. Eine Team-Admin-Mitgliedschaft gilt für ein Token nie.

## Kanaltypen und `config`

| `type` | Pflichtfelder in `config` | Optionale Felder in `config` |
|--------|--------------------------|--------------------------|
| `webhook` | `webhookUrl` | `headers` (Objekt aus Header-Name und Wert) |
| `slack` | `webhookUrl` | `headers` |
| `email` | `email` | |

- `webhookUrl` muss eine `http`- oder `https`-URL mit öffentlichem Hostnamen sein. Private, Loopback- und reservierte IP-Adressen, `localhost`, `*.local`, `*.internal`, `home.arpa` und Hostnamen ohne Punkt werden abgelehnt.
- `headers` darf den `Host`-Header nicht setzen.
- `config` darf als JSON höchstens 8 KB groß sein. Weitere Schlüssel werden so gespeichert, wie du sie schickst.

**`webhookUrl` und Header-Werte sind nur schreibbar.** Sie werden verschlüsselt gespeichert und nie zurückgegeben. Jede Antwort ersetzt sie: `webhookUrl` ist `null`, und `hasWebhookUrl` sagt, ob eine URL gespeichert ist; `headers` behält die Header-Namen mit `null` als Wert, und `hasHeaders` sagt, ob überhaupt ein Header gespeichert ist.

## Kanäle auflisten

`GET /api/im/channels`

Liefert alle Kanäle deiner Organisation (organisationsweite und Team-Kanäle), nach Name sortiert, mit aufgelöstem Teamnamen.

### Beispiel (cURL)

```bash
curl -X GET "$BASE_URL/api/im/channels" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"
```

### Antwort (Response)

`200 OK`

```json
[
  {
    "id": 9,
    "organizationId": 1,
    "teamId": 3,
    "teamName": "Platform Team",
    "type": "webhook",
    "name": "Ops webhook",
    "config": {
      "webhookUrl": null,
      "headers": { "X-Api-Key": null },
      "hasWebhookUrl": true,
      "hasHeaders": true
    },
    "isActive": true,
    "createdAt": "2026-09-20T10:00:00.000Z",
    "updatedAt": "2026-09-20T10:00:00.000Z"
  },
  {
    "id": 10,
    "organizationId": 1,
    "teamId": null,
    "teamName": null,
    "type": "email",
    "name": "NOC mailbox",
    "config": { "email": "noc@example.com" },
    "isActive": true,
    "createdAt": "2026-09-20T10:05:00.000Z",
    "updatedAt": "2026-09-20T10:05:00.000Z"
  }
]
```

## Kanal abrufen

`GET /api/im/channels/:id`

Liefert einen Kanal (ohne `teamName`) plus einen `references`-Block, der dir sagt, ob er der Fallback-Kanal der Organisation ist. Ein Fallback-Kanal kann weder gelöscht noch deaktiviert werden.

```json
{
  "id": 10,
  "organizationId": 1,
  "teamId": null,
  "type": "email",
  "name": "NOC mailbox",
  "config": { "email": "noc@example.com" },
  "isActive": true,
  "createdAt": "2026-09-20T10:05:00.000Z",
  "updatedAt": "2026-09-20T10:05:00.000Z",
  "references": {
    "isOrgFallback": true,
    "fallbackOrganizationIds": [1]
  }
}
```

## Kanal anlegen

`POST /api/im/channels`

### Request Body

| Feld | Typ | Erforderlich | Beschreibung |
|-------|------|----------|-------------|
| `type` | string | Ja | `webhook`, `slack` oder `email`. |
| `name` | string | Ja | Anzeigename, getrimmt, maximal 120 Zeichen. |
| `config` | object | Ja | Siehe [Kanaltypen und `config`](#kanaltypen-und-config). |
| `teamId` | integer \| null | Nein | Team deiner Organisation, oder `null`/weggelassen für einen organisationsweiten Kanal. |
| `isActive` | boolean | Nein | Standard `true`. Jeder andere Wert als `true` legt einen inaktiven Kanal an. |

### Beispiel (cURL)

```bash
curl -X POST "$BASE_URL/api/im/channels" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "webhook",
    "name": "Ops webhook",
    "teamId": 3,
    "config": {
      "webhookUrl": "https://hooks.example.com/im/7f3a",
      "headers": { "X-Api-Key": "k_live_51b2" }
    }
  }'
```

### Antwort (Response)

`200 OK`: der angelegte Kanal, mit geschwärzten Geheimnissen wie oben beschrieben. Die Antwort gibt die URL und die Header-Werte, die du gerade geschickt hast, nie zurück.

## Kanal ändern

`PATCH /api/im/channels/:id`

Nimmt nur `name`, `type`, `config`, `isActive` und `teamId` an; jeder andere Schlüssel oder ein leerer Body ergibt `400`. Du brauchst Schreibrechte auf den aktuellen Geltungsbereich des Kanals und, wenn du `teamId` änderst, auch auf den neuen (einen Kanal organisationsweit zu machen erfordert die Rolle `admin`).

`config` wird mit der gespeicherten Konfiguration zusammengeführt, du musst also nie Geheimnisse erneut senden, die du nicht zurücklesen kannst:

- Lass `webhookUrl` weg oder schick `null` oder `""`, um die gespeicherte URL zu behalten. Schick eine neue URL, um sie zu ersetzen.
- Wenn du `headers` schickst, ersetzt das die gespeicherte Menge an Header-Namen. Ein Header mit dem Wert `null` oder `""` behält seinen gespeicherten Wert; ein Header, den du weglässt, wird entfernt.
- Wenn du `type` änderst, wird die zusammengeführte Konfiguration gegen den neuen Typ geprüft; ein `email`-Kanal, den du auf `webhook` umstellst, braucht also eine `webhookUrl`.
- Den Fallback-Kanal der Organisation zu deaktivieren (`isActive: false`) wird mit `409` abgelehnt.

```bash
curl -X PATCH "$BASE_URL/api/im/channels/9" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Ops webhook (primary)", "config": { "headers": { "X-Api-Key": null } } }'
```

`200 OK`: der aktualisierte Kanal, Geheimnisse geschwärzt.

## Kanal löschen

`DELETE /api/im/channels/:id`

Wird mit `409` abgelehnt, solange der Kanal der Fallback-Kanal der Organisation ist; setz `fallbackChannelId` in den [Organisationseinstellungen](/de/api/incident-management/org-settings) vorher auf einen anderen Kanal (oder auf `null`).

```bash
curl -X DELETE "$BASE_URL/api/im/channels/9" \
  -H "Authorization: Bearer $TOKEN"
```

`200 OK`

```json
{ "success": true }
```

## Häufige Fehler

- `401 Unauthorized` wenn du nicht authentifiziert bist
- `403 Forbidden` (`imAccessDenied`) bei Verwendung eines kunden-gescopten Tokens, oder wenn deine Session keine IM-berechtigte Rolle hat
- `403 Forbidden` (`imNotEnabled`) wenn Incident Management für die Organisation nicht aktiviert ist
- `403 Forbidden` (`imChannelWriteDenied`) wenn du den Geltungsbereich des Kanals (oder das Ziel einer Verschiebung) nicht schreiben darfst
- `400 Bad Request` (`invalidRequestBody`) wenn `:id` keine positive Ganzzahl ist, `type`, `name` oder `config` fehlt oder ungültig ist, `webhookUrl` oder `email` die Prüfung nicht besteht, `config` größer als 8 KB ist, `teamId` kein Team deiner Organisation ist, `isActive` kein Boolean ist (beim Ändern), oder der Body beim Ändern leer ist oder nicht unterstützte Schlüssel enthält
- `400 Bad Request` (`webhookHostHeaderForbidden`) wenn `config.headers` den `Host`-Header setzt
- `404 Not Found` (`imChannelNotFound`) wenn der Kanal nicht existiert oder zu einer anderen Organisation gehört
- `409 Conflict` (`imChannelReferencesExist`) beim Löschen des Fallback-Kanals der Organisation. `data.fallbackOrganizationIds` nennt die verweisende Organisation
- `409 Conflict` (`imChannelIsOrgFallback`) beim Deaktivieren des Fallback-Kanals der Organisation
