Uptimeify Docs

Alert-Sources-API

Alert-Sources im Incident Management anlegen, konfigurieren und testen: Ingest-Tokens, optionale HMAC- oder Bearer-Authentifizierung, Payload-Mapping, Wartungsfenster und Statistiken je Source.

Eine Alert-Source ist eine eingehende Integration. Jede Webhook-Source hat ihre eigene Ingest-URL (https://uptimeify.io/api/im/ingest/<token>) und ein Payload-Mapping, das das JSON des Anbieters in einen Alert übersetzt. Wie du Zabbix, Datadog, Grafana und andere auf diese URL zeigen lässt, steht in den Einrichtungsanleitungen. Diese Seite beschreibt die Endpunkte, mit denen du die Sources selbst verwaltest.

Authentifizierung

Jeder Endpunkt braucht IM-Zugriff: eine IM-berechtigte Rolle (admin, editor, responder) oder einen organisationsweiten API-Token. Incident Management muss für die Organisation aktiviert sein. Ein kunden-gescopter Token wird mit 403 Forbidden (customerScopedTokenForbidden) abgewiesen.

  • Lese-Endpunkte (Liste, Detail, Presets, Payloads, Statistik, test-mapping) stehen jedem IM-berechtigten Aufrufer offen.
  • Schreib-Endpunkte (Anlegen, Ändern, Löschen, Token- und Secret-Rotation, disable-auth, test-alert) verlangen zusätzlich die Rolle admin oder eine Team-Admin-Mitgliedschaft im Team der Source. Ein API-Token trägt die Rolle der Person, die ihn erstellt hat. Nimm also einen Token, den ein Organisations-Admin erstellt hat.

Sources sind auf deine Organisation beschränkt. Eine Source einer anderen Organisation antwortet mit 404 Not Found (imSourceNotFound), nie mit 403.

Das Source-Objekt

Liste, Detail, Ändern und disable-auth liefern diese Form. Zugangsdaten tauchen darin nie auf: Ingest-Token, Bearer-Token und HMAC-Secret gibt es nur einmal, vom Endpunkt, der sie erzeugt.

FeldTypBeschreibung
idnumberID der Source.
organizationIdnumberBesitzende Organisation.
teamIdnumberTeam, dessen Eskalation die Source speist.
namestringAnzeigename, bis zu 120 Zeichen.
typestringzabbix, datadog, grafana, alertmanager, sentry, custom, api, email oder uptimeify_monitoring (die eingebaute Brücke aus dem klassischen Monitoring, von der Plattform angelegt).
authModeobject{ url_token?, hmac?: { enabled }, bearer?: { enabled } }. Siehe Optionale Absender-Authentifizierung.
payloadMappingobjectFeld-Mapping, das auf jede eingehende Payload angewendet wird.
autoResolvebooleanOb ein Resolve-Event den Incident automatisch schließt. Wird auf jeden neuen Incident übertragen.
groupingWindowMinutesnumber oder nullGruppierungsfenster. null gruppiert nur nach Dedup-Key.
maintenanceobject oder nullWiederkehrende Wartungsfenster, { windows: [...] }.
snoozeUntilISO 8601 oder nullStummgeschaltet bis zu diesem Zeitpunkt.
secondaryExpiresAtISO 8601 oder nullBis wann der vorige Ingest-Token nach einer Rotation noch gilt.
createdAt, updatedAtISO 8601Zeitstempel.
{
  "id": 7,
  "organizationId": 1,
  "teamId": 3,
  "name": "Zabbix production",
  "type": "zabbix",
  "secondaryExpiresAt": null,
  "payloadMapping": {
    "title": "trigger_name",
    "severity": "event_severity",
    "status": "trigger_status",
    "host": "host_name",
    "dedupKey": "event_id",
    "severityMap": { "Disaster": "sev1", "High": "sev2", "Average": "sev3", "Warning": "sev4", "Information": "sev4", "Not classified": "sev4" },
    "resolveValues": ["RESOLVED", "OK"]
  },
  "autoResolve": true,
  "groupingWindowMinutes": null,
  "maintenance": null,
  "snoozeUntil": null,
  "createdAt": "2026-10-01T08:00:00.000Z",
  "updatedAt": "2026-10-01T08:00:00.000Z",
  "authMode": {}
}

Sources auflisten

GET /api/im/sources

Liefert alle Sources deiner Organisation als Array von Source-Objekten, sortiert nach Name.

curl "$BASE_URL/api/im/sources" \
  -H "Authorization: Bearer $TOKEN"

Source abrufen

GET /api/im/sources/:id

Liefert ein Source-Objekt.

Presets auflisten

GET /api/im/sources/presets

Liefert die eingebauten Presets, die du beim Anlegen als type übergeben kannst. docsSlug ist die Anleitung unter /de/api/incident-management/alert-sources/, vendorTemplate eine fertige Anbieter-Konfiguration (nur Zabbix bringt eine mit, ein Media-Type-YAML), samplePayload die Test-Payload, auf die test-mapping und test-alert zurückfallen.

[
  {
    "name": "zabbix",
    "docsSlug": "zabbix",
    "vendorTemplate": "zabbix_export:\n  version: '7.4'\n  ...",
    "samplePayload": { "event_id": "6633487", "event_severity": "Disaster", "trigger_name": "Zabbix agent is not available on Zabbix server", "trigger_status": "PROBLEM", "host_name": "Zabbix server" }
  },
  { "name": "datadog", "docsSlug": "datadog", "vendorTemplate": null, "samplePayload": { "alert_id": "1234567", "alert_title": "[Triggered] High CPU usage on host web-01" } }
]

Die vollständige Liste ist zabbix, datadog, grafana, alertmanager, sentry, custom (Beispiel-Payloads oben gekürzt).

Source anlegen

POST /api/im/sources

Request Body

FeldTypErforderlichBeschreibung
teamIdnumberJaTeam in deiner Organisation.
namestringJa1 bis 120 Zeichen, Leerraum wird abgeschnitten.
typestringJaEin Preset-Name, api (keine Ingest-URL, gespeist über Events-Ingest) oder email (eingehende Mail-Adresse).
payloadMappingobjectNeinWeglassen, um mit dem Mapping des Presets zu starten. Ein expliziter Wert, auch {}, ersetzt das Preset. Bei email bleibt nur der verschachtelte Schlüssel emailSelectors erhalten, siehe E-Mail-Anleitung.
autoResolvebooleanNeinStandard true.
groupingWindowMinutesnumber oder nullNeinPositive Ganzzahl oder null (Standard).
authModeobjectNeinHier werden nur url_token und enabled: false angenommen. HMAC und Bearer schaltest du über ihre eigenen Endpunkte weiter unten ein.

payloadMapping gibt es in zwei Formen. Die flache Form nutzt String-Selektoren title, severity, status, host, dedupKey, dazu severityMap (Rohwert auf sev1 .. sev4), resolveValues (Array von Strings) und custom (Objekt aus Selektoren). Die Attribut-Form ist { "version": 2, "attributes": [...] }, jedes Attribut { key, standard?, steps?, flags? } mit Schritten { kind: "extract", type: "path" | "jsonpath" | "constant", expr } oder { kind: "valueMap", entries: [{ from, to }], fallback? }. Beide Formen kennen defaultSeverity (sev1 .. sev4, Standard sev3), das greift, wenn die Payload keinen gültigen Schweregrad liefert.

Beispiel (cURL)

curl -X POST "$BASE_URL/api/im/sources" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "teamId": 3, "name": "Zabbix production", "type": "zabbix" }'

Antwort (Response)

200 OK: das Source-Objekt plus ingestToken. Der Token steht nur in dieser Antwort. Gespeichert wird nur sein SHA-256-Hash, später lesen kannst du ihn nicht mehr. Die Webhook-URL lautet https://uptimeify.io/api/im/ingest/<ingestToken>. Bei type: "api" ist der Token null. Bei type: "email" enthält die Antwort zusätzlich inboundEmailAddress (<token>@alerts.uptimeify.io).

{
  "id": 7,
  "organizationId": 1,
  "teamId": 3,
  "name": "Zabbix production",
  "type": "zabbix",
  "secondaryExpiresAt": null,
  "payloadMapping": { "title": "trigger_name", "dedupKey": "event_id" },
  "autoResolve": true,
  "groupingWindowMinutes": null,
  "maintenance": null,
  "snoozeUntil": null,
  "createdAt": "2026-10-01T08:00:00.000Z",
  "updatedAt": "2026-10-01T08:00:00.000Z",
  "authMode": {},
  "ingestToken": "Q2hR4mVx9LkP0sTz7bNw1cYe5uJa3fGd"
}

Source ändern

PATCH /api/im/sources/:id

Schick nur die Felder, die du ändern willst. Die Schreibberechtigung wird am aktuellen Team geprüft, beim Verschieben zusätzlich am Zielteam.

FeldTypBeschreibung
namestring1 bis 120 Zeichen.
teamIdnumberVerschiebt die Source in ein anderes Team derselben Organisation.
payloadMappingobjectErsetzt das ganze Mapping, es wird nicht zusammengeführt. null setzt ein leeres Mapping.
authModeobjectWird mit dem gespeicherten Wert zusammengeführt. hmac.enabled: true / bearer.enabled: true gehen erst, wenn ein Secret existiert (siehe unten). bearer.token_hash wird abgelehnt.
autoResolveboolean
groupingWindowMinutesnumber oder nullnull entfernt das Fenster.
maintenanceobject oder null{ "windows": [{ "dow": [1,2,3,4,5], "from": "22:00", "to": "23:30", "timezone": "Europe/Berlin" }] }. from/to als 24-h-HH:MM, dow ISO-Wochentage 1 (Montag) bis 7, timezone eine IANA-Zone, höchstens 20 Fenster. null entfernt die Wartung. Alerts innerhalb eines Fensters werden unterdrückt.
snoozeUntilISO 8601 oder nullSchaltet die Source bis zu diesem Zeitpunkt stumm. Ein Wert in der Vergangenheit wird angenommen und wirkt nicht. null hebt es auf.

Den Ingest-Token änderst du hier nicht, dafür gibt es rotate-token.

curl -X PATCH "$BASE_URL/api/im/sources/7" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "snoozeUntil": "2026-10-09T18:00:00Z", "groupingWindowMinutes": 15 }'

200 OK: das geänderte Source-Objekt.

Source löschen

DELETE /api/im/sources/:id

Wird mit 409 abgelehnt, solange die Source noch offene Alerts hat oder primäre Source eines offenen Incidents ist (alles, was nicht resolved oder merged ist). Löse diese zuerst. Die Monitoring-Brücke (uptimeify_monitoring) lässt sich nicht löschen.

200 OK: { "success": true }.

Der Body der 409 (imSourceReferencesExist) nennt, was das Löschen blockiert (jede Liste höchstens 50 Einträge):

{
  "statusCode": 409,
  "statusMessage": "Source is still referenced by open alerts or incidents",
  "data": {
    "code": "imSourceReferencesExist",
    "openAlertCount": 2,
    "openIncidents": [{ "id": "42", "title": "Database connection pool exhausted" }]
  }
}

Ingest-Token rotieren

POST /api/im/sources/:id/rotate-token

Kein Request Body. Erzeugt einen neuen Ingest-Token. Der vorige Token gilt noch 7 Tage weiter (bis secondaryExpiresAt), so kannst du die Konfiguration beim Anbieter umstellen, ohne Alerts zu verlieren. Der neue Token steht nur in dieser Antwort. Bei einer E-Mail-Source lautet die neue Eingangsadresse <ingestToken>@alerts.uptimeify.io.

{
  "ingestToken": "Vn8kT1qZ4xLb7RwE0mYc2sHa9uJd6fPg",
  "secondaryExpiresAt": "2026-10-16T09:30:00.000Z"
}

Optionale Absender-Authentifizierung

Der Token in der URL ist immer Pflicht. Zusätzlich kannst du eine Signatur oder einen Header verlangen:

  • HMAC: Der Absender schickt X-Uptimeify-Timestamp (Unix-Sekunden, höchstens 5 Minuten Abweichung) und X-Uptimeify-Signature, das hex-codierte HMAC-SHA256 über <timestamp>.<roher Body> mit dem Secret der Source. Ein Präfix sha256= wird akzeptiert.
  • Bearer: Der Absender schickt Authorization: Bearer <token>.

Eine Anfrage, die eine dieser Prüfungen nicht besteht, wird genau wie ein unbekannter Token beantwortet (404). authMode.url_token wird gespeichert, hat aber keine Wirkung.

HMAC-Secret setzen

POST /api/im/sources/:id/set-hmac-secret

FeldTypErforderlichBeschreibung
secretstringNeinDein eigenes Secret, mindestens 16 Zeichen. Weglassen, um ein 256-Bit-Secret erzeugen zu lassen.

Schaltet HMAC ein (authMode.hmac.enabled: true). Ein weiterer Aufruf ersetzt das Secret, das alte gilt sofort nicht mehr. Das Secret wird verschlüsselt gespeichert und nur in dieser Antwort zurückgegeben:

{ "secret": "c2VjcmV0LWV4YW1wbGUtbm90LXJlYWwtMTIzNDU2Nzg5MA", "hmacEnabled": true }

Bearer-Token rotieren

POST /api/im/sources/:id/rotate-bearer-token

Kein Request Body. Erzeugt einen 256-Bit-Bearer-Token und schaltet Bearer-Authentifizierung ein. Ein vorheriger Bearer-Token gilt sofort nicht mehr. Gespeichert wird nur ein Hash, der Token steht nur in dieser Antwort:

{ "token": "b3V0LW9mLWJhbmQtZXhhbXBsZS10b2tlbi1ub3QtcmVhbA", "bearerEnabled": true }

HMAC oder Bearer abschalten

POST /api/im/sources/:id/disable-auth

FeldTypErforderlichBeschreibung
modestringJahmac oder bearer.

Setzt authMode.<mode>.enabled auf false und liefert das Source-Objekt. Das Secret bleibt gespeichert, daher schaltet PATCH mit { "authMode": { "hmac": { "enabled": true } } } es ohne neues Secret wieder ein. Einen schon abgeschalteten Modus abzuschalten gelingt ebenfalls.

Mapping testen

POST /api/im/sources/:id/test-mapping

Wendet das gespeicherte Mapping der Source auf eine Payload an, ohne etwas anzulegen. Reihenfolge der Payload: payload aus dem Body, sonst die zuletzt empfangene Payload der Source, sonst die Beispiel-Payload des Presets. Ein Mapping-Fehler ist kein HTTP-Fehler: Die Antwort ist 200 mit ok: false.

FeldTypErforderlichBeschreibung
payloadobjectNeinDie JSON-Payload, die gemappt werden soll.
curl -X POST "$BASE_URL/api/im/sources/7/test-mapping" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "payload": { "event_id": "6633487", "event_severity": "Disaster", "trigger_name": "Zabbix agent is not available on Zabbix server", "trigger_status": "PROBLEM", "host_name": "Zabbix server" } }'
{
  "ok": true,
  "alert": {
    "title": "Zabbix agent is not available on Zabbix server",
    "severity": "sev1",
    "status": "open",
    "host": "Zabbix server",
    "dedupKey": "6633487",
    "custom": {}
  },
  "attributes": [
    { "key": "title", "standard": true, "value": "Zabbix agent is not available on Zabbix server", "resolved": true, "flags": {} },
    { "key": "severity", "standard": true, "value": "sev1", "resolved": true, "flags": {} },
    { "key": "status", "standard": true, "value": "PROBLEM", "resolved": true, "flags": {} },
    { "key": "host", "standard": true, "value": "Zabbix server", "resolved": true, "flags": {} },
    { "key": "correlationId", "standard": true, "value": "6633487", "resolved": true, "flags": { "grouped": true } }
  ]
}

Bei einem Fehler: { "ok": false, "error": "title selector resolved to nothing on this payload" }.

alert.status ist nur dann resolved, wenn der gemappte Statuswert nach resolveValues gleich resolved ist (ohne Beachtung der Groß-/Kleinschreibung), alles andere ist open. Ohne dedupKey-Selektor ist der Dedup-Key der SHA-1 aus Titel plus Host.

Test-Alert auslösen

POST /api/im/sources/:id/test-alert

Stellt einen echten Alert in die normale Ingest-Pipeline. Meist öffnet das einen echten Incident und alarmiert, wer für das Team der Source On-Call ist. Payload: payload aus dem Body, sonst die Beispiel-Payload des Presets (kein Rückgriff auf zuletzt empfangene Payloads). Der Body ist wie bei der Ingest-URL auf 256 KB und 20 Verschachtelungsebenen begrenzt.

FeldTypErforderlichBeschreibung
payloadbeliebiges JSONNeinDie Payload, die eingespielt wird. Pflicht bei api- und email-Sources, die keine Beispiel-Payload haben.

200 OK: { "enqueued": true }.

Letzte Payloads

GET /api/im/sources/:id/payloads

Bis zu 10 zuletzt empfangene Roh-Payloads der Source, neueste zuerst. Hilfreich beim Bauen eines Mappings. Sie liegen in einem kurzlebigen Cache, eine leere Liste ist bei einer ruhigen Source normal.

{ "payloads": [ { "event_id": "6633487", "trigger_status": "PROBLEM" } ] }

Source-Statistik

GET /api/im/sources/:id/stats

Tageszähler der letzten 30 Tage mit Daten, älteste zuerst. day ist ein UTC-Kalendertag. alerts zählt eingehende Alerts, deduped die, die in einen schon offenen Alert eingeflossen sind, incidents die geöffneten Incidents.

{
  "days": [
    { "day": "2026-10-07", "alerts": 41, "deduped": 33, "incidents": 3 },
    { "day": "2026-10-08", "alerts": 12, "deduped": 9, "incidents": 1 }
  ]
}

Häufige Fehler

  • 401 Unauthorized (unauthorized) wenn du nicht authentifiziert bist
  • 403 Forbidden (customerScopedTokenForbidden) bei einem kunden-gescopten Token
  • 403 Forbidden (imAccessDenied) wenn deine Session keine IM-berechtigte Rolle hat
  • 403 Forbidden (imNotEnabled) wenn Incident Management für die Organisation nicht aktiviert ist
  • 403 Forbidden (imTeamWriteDenied) bei einem Schreib-Endpunkt ohne Rolle admin oder Team-Admin-Mitgliedschaft
  • 400 Bad Request (invalidRequestBody) wenn :id keine positive Ganzzahl ist, teamId/name/type fehlt oder ungültig ist, ein Mapping, eine Wartung oder snoozeUntil fehlerhaft ist, authMode.bearer.token_hash mitgeschickt wird, mode nicht hmac/bearer ist oder ein mitgegebenes HMAC-Secret kürzer als 16 Zeichen ist
  • 404 Not Found (imSourceNotFound) wenn die Source nicht existiert oder zu einer anderen Organisation gehört
  • 422 Unprocessable Entity (invalidTeamId) wenn teamId kein Team der Organisation ist
  • 422 Unprocessable Entity (imAuthModeNotProvisionable) wenn HMAC oder Bearer per Anlegen/PATCH eingeschaltet wird, bevor ein Secret existiert
  • 409 Conflict (imSourceReferencesExist) beim Löschen einer Source mit offenen Alerts oder Incidents
  • 409 Conflict (imSourceProtected) beim Löschen der Monitoring-Brücke
  • 400 Bad Request (imSourceHasNoIngestToken) beim Rotieren des Tokens einer api-Source
  • 400 Bad Request (imNoTestPayloadAvailable) wenn test-mapping oder test-alert keine Payload zur Verfügung hat
  • 413 Payload Too Large (payloadTooLarge), 422 Unprocessable Entity (invalidJson, payloadTooDeep) bei test-alert
  • 503 Service Unavailable (unavailable) wenn test-alert den Alert nicht einreihen kann, sicher wiederholbar

Auf dieser Seite