Benachrichtigungskanäle
Verwalte, wie und wohin Alerts zugestellt werden. Kanäle können auf Organisationsebene (Standard für alle Kunden), auf Kundenebene (Override für einen bestimmten Kunden) oder auf Website-Ebene (Override für einen bestimmten Monitor) liegen.
Authentifizierung
Alle Beispiele setzen einen Bearer-Token voraus:
BASE_URL="https://uptimeify.io"
TOKEN="<dein-api-token>"Kanaltypen und Config
Jeder Kanaltyp hat eine spezifische config-Struktur:
| Type | Config Fields | Notes |
|---|---|---|
email | { email, to } | E-Mail-Adresse und Empfängername |
sms | { phoneNumber } | Telefonnummer im internationalen Format |
webhook | { url, method?, headers?, bodyTemplate?, timeout?, retryAttempts?, retryDelay?, expectedStatusCodes?, secret? } | HTTP-Webhook. secret für HMAC-Signierung |
slack | { webhookUrl, username?, iconEmoji?, color? } | Slack Incoming-Webhook-URL. Die URL enthält das Posting-Token und gilt als Geheimnis |
discord | { webhookUrl, username?, color? } | Discord Incoming-Webhook-URL. Die URL enthält das Posting-Token und gilt als Geheimnis |
teams | { webhookUrl } | Microsoft-Teams-Workflow- bzw. Connector-URL. Gilt als Geheimnis |
pagerduty | { routingKey } | PagerDuty Events API v2 Routing-Key |
pushover | { userKey, apiToken } | Pushover User-Key und API-Token |
opsgenie | { apiKey } | Opsgenie API-Key |
Geheimnisse (Webhook-secret, Slack-/Discord-/Teams-Webhook-URLs, PagerDuty-Routing-Keys, Pushover-Zugangsdaten, Opsgenie-API-Keys) werden verschlüsselt gespeichert und in API-Antworten unkenntlich gemacht: Der Wert kommt als null zurück, und ein boolesches Flag daneben sagt, ob einer hinterlegt ist (hasSecret, hasWebhookUrl, hasRoutingKey, …). Ein Slack-, Discord- oder Teams-Kanal liest sich deshalb als "config": { "webhookUrl": null, "hasWebhookUrl": true, … }. Lässt du ein solches Feld beim PATCH weg (oder schickst null bzw. einen leeren String), bleibt der gespeicherte Wert erhalten; ein neuer Wert ersetzt ihn. Der generische Typ webhook ist die Ausnahme: Seine url ist die eigene Adresse des Kunden und bleibt sichtbar, nur sein secret wird unkenntlich gemacht.
Webhook-Signaturprüfung
Wenn auf einem Webhook-Kanal ein secret konfiguriert ist, signiert Uptimeify ausgehende Payloads, damit Empfänger die Authentizität verifizieren können.
Algorithmus: HMAC-SHA256
Header: X-Webhook-Signature: hex-kodierter HMAC-SHA256-Digest
Begleitende Header, die mit jedem Webhook gesendet werden:
| Header | Value |
|---|---|
X-Webhook-Signature | Hex-kodierter HMAC-SHA256-Digest |
X-Webhook-Signature-Algorithm | sha256 |
X-Webhook-Timestamp | ISO-8601-Zeitstempel (z. B. 2026-05-05T12:00:00.000Z) |
X-Webhook-Attempt | 1-basierte Retry-Nummer (z. B. 1, 2, 3) |
X-Webhook-Event | Event-Typ: alert, recovery oder dnsbl |
Verifizierungsschritte:
- Lies den rohen Request-Body als String (nicht zuerst als JSON parsen).
- Berechne HMAC-SHA256 mit dem im Kanal konfigurierten
secretals Schlüssel und dem rohen Body-String als Nachricht. - Vergleiche das Ergebnis (hex-kodiert) mit dem Wert des
X-Webhook-Signature-Headers per konstanter Laufzeit-Vergleich (constant-time comparison). - Optional kannst du
X-Webhook-Timestampfür Replay-Schutz prüfen.
// Node.js verification example
const crypto = require('crypto')
function verifySignature(rawBody, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
)
}# Python verification example
import hmac, hashlib
def verify_signature(raw_body, signature, secret):
expected = hmac.new(
secret.encode('utf-8'),
raw_body.encode('utf-8'),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)Scope-Auflösung
Beim Auflisten von Kanälen bestimmt der Scope, welche Kanäle zurückgegeben werden:
- Organisationsebene (nur
organizationId, keincustomerId/websiteId): Standardkanäle für alle Kunden - Kundenebene (
customerIdgesetzt, keinwebsiteId): Kundenspezifische Overrides - Website-Ebene (
websiteIdgesetzt): Overrides pro Monitor