Ausgehende Integrationen
Incident-Management-Ereignisse an Slack, Microsoft Teams, Discord, Jira, PagerDuty, Opsgenie oder einen generischen Webhook weiterleiten, Zustellungen einsehen und erneut senden.
GET /api/im/outbound · POST /api/im/outbound · GET /api/im/outbound/:id · PATCH /api/im/outbound/:id · DELETE /api/im/outbound/:id · GET /api/im/outbound/:id/history · POST /api/im/outbound/:id/retry
Eine ausgehende Integration leitet Incident-Ereignisse (angelegt, bestätigt, Severity oder Status geändert, Kommentar, gelöst) an ein externes System weiter. Anders als ein Kanal, der ein Paging-Ziel einer Eskalation ist, spiegelt eine ausgehende Integration den Lebenszyklus des Incidents in ein anderes Werkzeug. Eine Integration gilt entweder organisationsweit (teamId: null) oder gehört zu einem Team.
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 (Liste, Detail, Verlauf) darf jede IM-berechtigte Rolle. Anlegen, Ändern, Löschen und erneutes Senden erfordern bei einer organisationsweiten Integration die Rolle admin, bei einer Team-Integration die Rolle admin oder eine Team-Admin-Mitgliedschaft. Ein organisationsweites API-Token läuft mit der Rolle der Person, die es erstellt hat; ein Token, das ein Organisations-Admin erstellt hat, erfüllt diese Hürde also. Eine Team-Admin-Mitgliedschaft gilt für ein Token nie.
Integrationstypen und config
type | Pflichtfelder in config | Optionale Felder in config | Nur schreibbare Felder |
|---|---|---|---|
slack | webhookUrl | webhookUrl | |
teams | webhookUrl | webhookUrl | |
discord | webhookUrl | webhookUrl | |
jira | baseUrl (muss mit https:// beginnen), email, apiToken, projectKey | issueType (Standard Task) | apiToken |
pagerduty_v2 | routingKey | routingKey | |
opsgenie | apiKey | region (us oder eu, Standard eu) | apiKey |
webhook | webhookUrl | bearerToken, headers (Objekt aus Header-Name und Wert) | webhookUrl, bearerToken, headers |
Nur schreibbare Felder werden verschlüsselt gespeichert und nie zurückgegeben. Jede Antwort setzt sie auf null und ergänzt pro Feld ein Flag: hasWebhookUrl, hasApiToken, hasRoutingKey, hasApiKey, hasBearerToken, und bei webhook zusätzlich hasHeaders (das ganze headers-Objekt kommt als null zurück).
URLs werden beim Speichern nicht auf Erreichbarkeit geprüft. Vom Kunden angegebene Ziele werden beim Senden geprüft: Eine URL, die auf eine private oder lokale Adresse auflöst, lässt die Zustellung scheitern; sie erscheint dann als failed im Zustellverlauf.
Das filters-Objekt
| Feld | Typ | Beschreibung |
|---|---|---|
teams | integer[] | Nur Ereignisse von Incidents dieser Team-IDs weiterleiten. |
severities | string[] | Teilmenge von sev1, sev2, sev3, sev4. |
event_kinds | string[] | Teilmenge von incident_created, acknowledged, severity_changed, status_changed, comment, resolved. |
Ein leeres Objekt {} leitet alles weiter. Bei jira wird ein weggelassenes event_kinds zu ["incident_created"], Jira bekommt also ein Ticket pro Incident.
Integrationen auflisten
GET /api/im/outbound
Liefert alle Integrationen deiner Organisation, nach Name sortiert, Geheimnisse geschwärzt.
Beispiel (cURL)
curl -X GET "$BASE_URL/api/im/outbound" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json"Antwort (Response)
200 OK
[
{
"id": 6,
"organizationId": 1,
"teamId": null,
"type": "pagerduty_v2",
"name": "PagerDuty bridge",
"config": { "routingKey": null, "hasRoutingKey": true },
"filters": { "severities": ["sev1", "sev2"] },
"isActive": true,
"createdAt": "2026-09-22T12:00:00.000Z",
"updatedAt": "2026-09-22T12:00:00.000Z"
}
]Integration abrufen
GET /api/im/outbound/:id
Liefert eine Integration, in derselben Form wie ein Listeneintrag.
Integration anlegen
POST /api/im/outbound
Request Body
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
type | string | Ja | Einer der Typen oben. Lässt sich später nicht ändern. |
name | string | Ja | Getrimmt, maximal 200 Zeichen. |
config | object | Ja | Siehe Integrationstypen und config. |
teamId | integer | null | Nein | Team deiner Organisation, oder null/weggelassen für eine organisationsweite Integration. |
filters | object | Nein | Siehe das filters-Objekt. Standard {}. |
Neue Integrationen sind immer aktiv.
Beispiel (cURL)
curl -X POST "$BASE_URL/api/im/outbound" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "jira",
"name": "Jira OPS",
"teamId": 3,
"config": {
"baseUrl": "https://example.atlassian.net",
"email": "ops-bot@example.com",
"apiToken": "ATATT3xFfGF0aB12",
"projectKey": "OPS"
}
}'Antwort (Response)
200 OK: die angelegte Integration, Geheimnisse geschwärzt.
{
"id": 7,
"organizationId": 1,
"teamId": 3,
"type": "jira",
"name": "Jira OPS",
"config": {
"baseUrl": "https://example.atlassian.net",
"email": "ops-bot@example.com",
"apiToken": null,
"projectKey": "OPS",
"hasApiToken": true
},
"filters": { "event_kinds": ["incident_created"] },
"isActive": true,
"createdAt": "2026-09-22T12:10:00.000Z",
"updatedAt": "2026-09-22T12:10:00.000Z"
}Integration ändern
PATCH /api/im/outbound/:id
Teilweise Aktualisierung von name, teamId, filters, config und isActive (Boolean, oder die Strings "true"/"false"). Andere Schlüssel, auch type, werden ignoriert. Du brauchst die Schreibhürde für den aktuellen Geltungsbereich der Integration und, wenn du teamId änderst, auch für den neuen (null macht sie organisationsweit).
filtersersetzt die gespeicherten Filter vollständig.configwird mit der gespeicherten Konfiguration zusammengeführt, danach wird das Ergebnis gegen den Typ geprüft. Lass ein nur schreibbares Feld weg oder schicknulloder"", um den gespeicherten Wert zu behalten.- Bei
webhookersetzt ein mitgeschicktesheadersalle gespeicherten Header samt Werten. Lassheadersweg, um sie zu behalten.
curl -X PATCH "$BASE_URL/api/im/outbound/7" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "isActive": false }'200 OK: die aktualisierte Integration, Geheimnisse geschwärzt.
Integration löschen
DELETE /api/im/outbound/:id
Löscht auch den Zustellverlauf der Integration.
curl -X DELETE "$BASE_URL/api/im/outbound/7" \
-H "Authorization: Bearer $TOKEN"200 OK
{ "ok": true }Zustellverlauf
GET /api/im/outbound/:id/history
Zustellversuche einer Integration, neueste zuerst. Zustellungen werden 90 Tage aufbewahrt.
Query-Parameter
| Parameter | Typ | Beschreibung |
|---|---|---|
limit | integer | Seitengröße, Standard 50, begrenzt auf 1 bis 200. |
before | integer | Cursor: liefert Zustellungen mit einer kleineren id. Übergib nextCursor der vorigen Seite. |
curl -X GET "$BASE_URL/api/im/outbound/6/history?limit=20" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json"200 OK. requestSummary enthält nur den Typ, den Ursprung des Ziels (ohne Pfad) und die Methode; responseSummary enthält den Statuscode und einen gekürzten Body. Keins von beiden enthält Geheimnisse.
{
"deliveries": [
{
"id": 88412,
"integrationId": 6,
"incidentId": 42,
"eventKind": "incident_created",
"status": "failed",
"requestSummary": { "type": "pagerduty_v2", "url": "https://events.pagerduty.com", "method": "POST" },
"responseSummary": { "statusCode": 429, "body": "Rate limit exceeded" },
"at": "2026-09-22T13:02:11.000Z"
}
],
"nextCursor": null,
"hasMore": false
}status ist sent, failed oder retrying.
Zustellung erneut senden
POST /api/im/outbound/:id/retry
Stellt einen neuen Sendeauftrag für eine Zustellung dieser Integration in die Warteschlange. Gesendet wird der aktuelle Stand des Incidents (Titel, Severity, Status von jetzt), nicht der ursprüngliche Payload. Der Aufruf kehrt zurück, sobald der Auftrag eingereiht ist; das Ergebnis erscheint als neuer Eintrag im Zustellverlauf.
Begrenzt auf 10 Wiederholungen pro Minute und Integration. Die Grenze zählt jeden berechtigten Aufruf, auch einen, der danach an der Validierung scheitert.
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
deliveryId | integer | Ja | id einer Zustellung aus dem Verlauf dieser Integration. |
curl -X POST "$BASE_URL/api/im/outbound/6/retry" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "deliveryId": 88412 }'200 OK
{ "ok": true }Häufige Fehler
401 Unauthorizedwenn du nicht authentifiziert bist403 Forbidden(imAccessDenied) bei Verwendung eines kunden-gescopten Tokens, oder wenn deine Session keine IM-berechtigte Rolle hat403 Forbidden(imNotEnabled) wenn Incident Management für die Organisation nicht aktiviert ist403 Forbidden(imOutboundWriteDenied) wenn du eine organisationsweite Integration ohne die Rolleadminschreibst403 Forbidden(imTeamWriteDenied) wenn du eine Team-Integration ohne die Schreibhürde für dieses Team schreibst400 Bad Request(invalidRequestBody) wenn:idkeine positive Ganzzahl ist,nameodertypefehlt oder ungültig ist, ein Pflichtfeld inconfigfehlt,baseUrlbeijiranichthttpsnutzt, ein Eintrag infiltersungültig ist,teamIdoderisActiveungültig ist, oderdeliveryIdfehlt404 Not Found(imOutboundNotFound) wenn die Integration nicht existiert oder zu einer anderen Organisation gehört404 Not Found(imOutboundDeliveryNotFound) wenndeliveryIdkeine Zustellung dieser Integration ist422 Unprocessable Entity(invalidTeamId) wennteamIdnicht zu deiner Organisation gehört422 Unprocessable Entity(imOutboundNotRetryable) wenn der Typ der Integration nicht erneut gesendet werden kann429 Too Many Requests(imOutboundRetryRateLimited) wenn die Wiederholungsgrenze erreicht ist.data.retryAfterist die Wartezeit in Sekunden
Organisationseinstellungen
Die Incident-Management-Einstellungen deiner Organisation lesen und ändern: Monitoring-Brücke, SMS/Anruf-Mehrverbrauch und Fallback-Kanal.
Berichte
Incident-Bericht (Volumen, MTTA, MTTR nach Team, Schweregrad oder Monat) und On-Call-Bericht (Minuten pro Person) für einen Zeitraum, als JSON oder CSV.