Webhooks-API
Webhooks ermöglichen es deiner Anwendung, Echtzeit-HTTP-Callbacks zu empfangen, wenn Ereignisse in Auris auftreten. Wenn ein abonniertes Ereignis ausgelöst wird (z.B. ein Benutzer meldet sich an, eine Rolle wird zugewiesen, ein Konto wird gesperrt), sendet Auris eine POST-Anforderung an deine konfigurierte URL mit einem JSON-Payload, der das Ereignis beschreibt.
Jede Webhook-Zustellung wird mit HMAC-SHA256 unter Verwendung eines pro-Webhook-Signing-Secrets signiert. Dies ermöglicht es deinem Server zu verifizieren, dass der Payload von Auris stammt und während der Übertragung nicht manipuliert wurde.
Alle Webhook-Verwaltungsendpunkte erfordern die manage:webhooks-Berechtigung und den x-tenant-Header.
Webhook-CRUD
Webhooks auflisten
/api/webhooksRequires: manage:webhooksAlle für den Tenant konfigurierten Webhook-Endpunkte auflisten. Gibt Webhook-Metadaten zurück, einschließlich der abonnierten Ereignisse, des aktiven Status und der Fehlerstatistiken. Das Signing-Secret wird in Listenantworten nie zurückgegeben.
Abfrageparameter
| Parameter | Typ | Beschreibung |
|---|---|---|
page | integer | Seitennummer (Standard: 1) |
limit | integer | Elemente pro Seite (Standard: 20) |
Erfolgsantwort
{
"ok": true,
"data": {
"data": [
{
"id": "whk_abc123",
"name": "Produktions-Ereignishandler",
"url": "https://api.ihreapp.de/webhooks/auris",
"events": ["user.created", "user.updated", "login.success", "login.failed"],
"isActive": true,
"lastDeliveryAt": "2025-02-18T09:45:00Z",
"failureCount": 0,
"createdAt": "2025-01-15T10:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 3,
"totalPages": 1
}
}
}Webhook erstellen
/api/webhooksRequires: manage:webhooksEinen neuen Webhook-Endpunkt erstellen. Ein Signing-Secret wird automatisch mit dem Präfix
whsec_ generiert. Das Secret wird nur in der Erstellungsantwort zurückgegeben — speichere
es sicher, da es später nicht abgerufen werden kann (nur rotiert).
Anforderungs-Body
{
"name": "Produktions-Ereignishandler",
"url": "https://api.ihreapp.de/webhooks/auris",
"events": ["user.created", "user.updated", "user.deleted", "login.success"]
}| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
name | string | Ja | Menschenlesbarer Name für diesen Webhook |
url | string | Ja | HTTPS-Endpunkt-URL, die POST-Anforderungen empfängt |
events | string[] | Ja | Array von Ereignistypen, die abonniert werden sollen (siehe Ereignistypen) |
Webhook-URLs müssen HTTPS verwenden. HTTP-URLs werden abgelehnt, um zu verhindern, dass Secrets und Benutzerdaten im Klartext übertragen werden.
Erfolgsantwort
{
"ok": true,
"data": {
"id": "whk_def456",
"name": "Produktions-Ereignishandler",
"url": "https://api.ihreapp.de/webhooks/auris",
"events": ["user.created", "user.updated", "user.deleted", "login.success"],
"secret": "whsec_7f3a8b2c4d5e6f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f",
"isActive": true,
"createdAt": "2025-02-18T10:00:00Z"
}
}Das secret-Feld wird nur in der Erstellungsantwort und nach der Secret-Rotation zurückgegeben. Kopiere und speichere es sofort an einem sicheren Ort (z.B. Umgebungsvariable oder Secrets-Manager). Es kann nicht erneut abgerufen werden.
Fehlercodes
| Code | HTTP | Beschreibung |
|---|---|---|
VALIDATION_ERROR | 400 | Fehlende Pflichtfelder oder ungültige Ereignistypen |
INVALID_URL | 400 | URL ist kein gültiger HTTPS-Endpunkt |
INVALID_EVENTS | 400 | Eine oder mehrere Ereignistyp-Zeichenketten werden nicht erkannt |
Webhook abrufen
/api/webhooks/[id]Requires: manage:webhooksEinen einzelnen Webhook anhand seiner ID abrufen. Gibt vollständige Webhook-Details ohne das Signing-Secret zurück.
Erfolgsantwort
{
"ok": true,
"data": {
"id": "whk_abc123",
"name": "Produktions-Ereignishandler",
"url": "https://api.ihreapp.de/webhooks/auris",
"events": ["user.created", "user.updated", "login.success", "login.failed"],
"isActive": true,
"failureCount": 0,
"lastDeliveryAt": "2025-02-18T09:45:00Z",
"createdAt": "2025-01-15T10:00:00Z",
"updatedAt": "2025-02-10T14:00:00Z"
}
}Webhook aktualisieren
/api/webhooks/[id]Requires: manage:webhooksDen Namen, die URL, die abonnierten Ereignisse oder den aktiven Status eines Webhooks aktualisieren. Alle Felder sind optional — nur bereitgestellte Felder werden aktualisiert.
Anforderungs-Body
{
"name": "Produktions-Ereignishandler v2",
"events": ["user.created", "user.updated", "user.deleted", "login.success", "login.failed", "role.assigned"],
"isActive": true
}Erfolgsantwort
{
"ok": true,
"data": {
"id": "whk_abc123",
"name": "Produktions-Ereignishandler v2",
"url": "https://api.ihreapp.de/webhooks/auris",
"events": ["user.created", "user.updated", "user.deleted", "login.success", "login.failed", "role.assigned"],
"isActive": true,
"updatedAt": "2025-02-18T11:00:00Z"
}
}Webhook löschen
/api/webhooks/[id]Requires: manage:webhooksEinen Webhook-Endpunkt löschen. Ausstehende Zustellungen für diesen Webhook werden abgebrochen. Der Zustellungsverlauf wird für Audit-Zwecke aufbewahrt.
Erfolgsantwort
{
"ok": true,
"data": { "deleted": true }
}Secret-Rotation
/api/webhooks/[id]/rotate-secretRequires: manage:webhooksEin neues Signing-Secret für den Webhook generieren. Das alte Secret wird sofort ungültig. Das neue Secret wird in der Antwort zurückgegeben. Alle nachfolgenden Zustellungen werden mit dem neuen Secret signiert.
Anforderung: Kein Body erforderlich.
Erfolgsantwort
{
"ok": true,
"data": {
"secret": "whsec_9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a"
}
}Aktualisiere nach der Rotation eines Secrets deinen Webhook-Handler sofort, um das neue Secret zu verwenden. Zustellungen, die zum Zeitpunkt der Rotation unterwegs sind, können noch das alte Secret verwenden. Best Practice: Unterstütze die Verifizierung gegen beide Secrets (alt und neu) für eine kurze Übergangsperiode während der Rotation.
Testen
/api/webhooks/[id]/testRequires: manage:webhooksEine Testzustellung an die Webhook-URL senden. Auris sendet ein webhook.test-Ereignis mit
einem Beispiel-Payload. Die Zustellung wird im Zustellungsprotokoll aufgezeichnet. Verwende
dies, um zu überprüfen, ob dein Endpunkt erreichbar ist und Signaturen korrekt verifiziert.
Anforderung: Kein Body erforderlich.
Erfolgsantwort
{
"ok": true,
"data": {
"deliveryId": "del_xyz789",
"statusCode": 200,
"success": true,
"responseTime": 142
}
}Test-Ereignis-Payload (was dein Endpunkt empfängt)
{
"event": "webhook.test",
"timestamp": "2025-02-18T10:30:00Z",
"tenant": "acme-gmbh",
"data": {
"message": "Dies ist eine Testzustellung von Auris.",
"webhookId": "whk_abc123"
}
}Fehlercodes
| Code | HTTP | Beschreibung |
|---|---|---|
DELIVERY_FAILED | 502 | Der Webhook-Endpunkt gab einen Nicht-2xx-Statuscode zurück |
ENDPOINT_UNREACHABLE | 502 | Verbindung zur Webhook-URL konnte nicht hergestellt werden (DNS-Fehler, Timeout, etc.) |
Zustellungsprotokoll
Zustellungen auflisten
/api/webhooks/[id]/deliveriesRequires: manage:webhooksZustellversuche für einen Webhook auflisten, nach Zeitstempel absteigend geordnet. Jede Zustellung enthält den Ereignistyp, den HTTP-Statuscode, die Antwortzeit und ob die Zustellung erfolgreich war. Wiederholte Zustellungen sind separate Einträge, die mit demselben Ereignis verknüpft sind.
Abfrageparameter
| Parameter | Typ | Beschreibung |
|---|---|---|
page | integer | Seitennummer (Standard: 1) |
limit | integer | Elemente pro Seite (Standard: 20) |
Erfolgsantwort
{
"ok": true,
"data": {
"data": [
{
"id": "del_abc123",
"event": "user.created",
"statusCode": 200,
"success": true,
"responseTime": 89,
"attempts": 1,
"payload": {
"event": "user.created",
"timestamp": "2025-02-18T09:45:00Z",
"tenant": "acme-gmbh",
"data": {
"userId": "usr_abc123",
"email": "[email protected]"
}
},
"createdAt": "2025-02-18T09:45:00Z",
"completedAt": "2025-02-18T09:45:01Z"
},
{
"id": "del_def456",
"event": "login.failed",
"statusCode": 500,
"success": false,
"responseTime": 2034,
"attempts": 3,
"error": "Server returned 500 Internal Server Error",
"payload": {
"event": "login.failed",
"timestamp": "2025-02-18T09:30:00Z",
"tenant": "acme-gmbh",
"data": {
"email": "[email protected]",
"reason": "INVALID_CREDENTIALS",
"ipAddress": "203.0.113.50"
}
},
"createdAt": "2025-02-18T09:30:00Z",
"completedAt": "2025-02-18T09:35:12Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 156,
"totalPages": 8
}
}
}Zustellung wiederholen
/api/webhooks/[id]/deliveries/[deliveryId]/retryRequires: manage:webhooksEine fehlgeschlagene Zustellung manuell wiederholen. Der ursprüngliche Payload wird mit einer neuen Signatur erneut gesendet. Erstellt einen neuen Zustellungseintrag, der mit demselben Ereignis verknüpft ist.
Anforderung: Kein Body erforderlich.
Erfolgsantwort
{
"ok": true,
"data": {
"deliveryId": "del_ghi789",
"statusCode": 200,
"success": true,
"responseTime": 95
}
}Fehlercodes
| Code | HTTP | Beschreibung |
|---|---|---|
NOT_FOUND | 404 | Zustellung existiert nicht |
ALREADY_SUCCESSFUL | 400 | Die Zustellung war bereits erfolgreich und muss nicht wiederholt werden |
Ereignistypen
Auris sendet folgende Webhook-Ereignisse. Abonniere die für deinen Anwendungsfall relevanten Ereignisse.
Authentifizierungsereignisse
| Ereignis | Beschreibung |
|---|---|
login.success | Benutzer hat sich erfolgreich authentifiziert (jede Methode) |
login.failed | Authentifizierungsversuch fehlgeschlagen (falsche Anmeldedaten, gesperrtes Konto, etc.) |
signup.completed | Neues Benutzerkonto registriert |
logout.completed | Benutzer abgemeldet (Sitzung ungültig gemacht) |
token.refreshed | Zugriffs-Token wurde erneuert |
password.changed | Benutzer hat sein Passwort geändert |
password.reset_requested | Passwort-Reset-E-Mail wurde gesendet |
magic_link.sent | Magic-Link-E-Mail wurde gesendet |
magic_link.verified | Magic Link wurde zur Authentifizierung verwendet |
Benutzerverwaltungsereignisse
| Ereignis | Beschreibung |
|---|---|
user.created | Neues Benutzerkonto erstellt (über Admin-API oder Registrierung) |
user.updated | Benutzerprofilfelder wurden geändert |
user.deleted | Benutzerkonto wurde soft-gelöscht |
user.enabled | Zuvor deaktivierter Benutzer wurde wieder aktiviert |
user.disabled | Benutzerkonto wurde deaktiviert |
user.email_verified | Benutzer hat seine E-Mail-Adresse verifiziert |
Rollen- und Berechtigungsereignisse
| Ereignis | Beschreibung |
|---|---|
role.created | Neue Rolle erstellt |
role.updated | Rollenmetadaten oder -berechtigungen geändert |
role.deleted | Rolle gelöscht |
role.assigned | Rolle einem Benutzer zugewiesen |
role.unassigned | Rolle von einem Benutzer entfernt |
Sicherheitsereignisse
| Ereignis | Beschreibung |
|---|---|
mfa.enabled | Benutzer hat eine 2FA-Methode aktiviert (TOTP, SMS oder WebAuthn) |
mfa.disabled | Benutzer hat eine 2FA-Methode deaktiviert |
account.locked | Konto wurde aufgrund von Brute-Force-Erkennung gesperrt |
account.unlocked | Kontosperre wurde aufgehoben |
suspicious_login.detected | Verdächtige Anmeldeaktivität erkannt (neues Gerät, unmögliche Reise, etc.) |
Organisationsereignisse
| Ereignis | Beschreibung |
|---|---|
organization.created | Neue Organisation erstellt |
organization.updated | Organisationsmetadaten geändert |
organization.member_added | Benutzer zu einer Organisation hinzugefügt |
organization.member_removed | Benutzer aus einer Organisation entfernt |
organization.invitation_sent | Einladungs-E-Mail gesendet |
Systemereignisse
| Ereignis | Beschreibung |
|---|---|
webhook.test | Testzustellung über die Konsole oder API ausgelöst |
Webhook-Payload-Format
Jede Webhook-Zustellung sendet eine POST-Anforderung mit einem JSON-Body:
{
"event": "user.created",
"timestamp": "2025-02-18T10:00:00Z",
"tenant": "acme-gmbh",
"data": {
"userId": "usr_abc123",
"email": "[email protected]",
"firstName": "Alice",
"lastName": "Müller"
}
}| Feld | Typ | Beschreibung |
|---|---|---|
event | string | Der Ereignistyp (z.B. user.created) |
timestamp | string | ISO 8601-Zeitstempel des Ereignisses |
tenant | string | Tenant-Bezeichner, in dem das Ereignis aufgetreten ist |
data | object | Ereignisspezifische Payload-Daten |
Die Form von data variiert je nach Ereignistyp. Benutzerereignisse enthalten Benutzerfelder, Rollenereignisse enthalten Rollendetails und Anmeldeereignisse enthalten die E-Mail und IP-Adresse.
Signaturverifizierung
Jede Zustellung enthält zwei Header für die Signaturverifizierung:
| Header | Beschreibung |
|---|---|
X-Webhook-Signature | HMAC-SHA256-Signatur des Anforderungs-Bodys |
X-Webhook-Timestamp | Unix-Zeitstempel (Sekunden), wann die Signatur generiert wurde |
Verifizierungsalgorithmus
- Lies den rohen Anforderungs-Body als UTF-8-Zeichenkette (nicht zuerst als JSON parsen).
- Lies den
X-Webhook-Timestamp-Header. - Verketten:
timestamp + "." + body - Berechne HMAC-SHA256 der verketteten Zeichenkette mit dem Signing-Secret deines Webhooks.
- Vergleiche das hexadezimal kodierte Ergebnis mit dem
X-Webhook-Signature-Header mit einem zeitkonstanten Vergleich. - Optional: Zustellungen ablehnen, bei denen der Zeitstempel mehr als 5 Minuten alt ist (zum Schutz vor Replay-Angriffen).
Node.js-Verifizierungsbeispiel
import crypto from 'crypto';
function verifyWebhookSignature(rawBody, signature, timestamp, secret) {
// 1. Zeitstempel-Aktualität prüfen (optional, aber empfohlen)
const currentTime = Math.floor(Date.now() / 1000);
if (Math.abs(currentTime - parseInt(timestamp)) > 300) {
throw new Error('Webhook-Zeitstempel ist zu alt');
}
// 2. Erwartete Signatur berechnen
const signedPayload = `${timestamp}.${rawBody}`;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
// 3. Zeitkonstanter Vergleich
const expected = Buffer.from(expectedSignature, 'hex');
const received = Buffer.from(signature, 'hex');
if (expected.length !== received.length) {
return false;
}
return crypto.timingSafeEqual(expected, received);
}
// Express.js-Handler
app.post('/webhooks/auris', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-webhook-signature'];
const timestamp = req.headers['x-webhook-timestamp'];
const rawBody = req.body.toString('utf-8');
if (!verifyWebhookSignature(rawBody, signature, timestamp, process.env.AURIS_WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Ungültige Signatur' });
}
const event = JSON.parse(rawBody);
console.log(`Received ${event.event}:`, event.data);
// Ereignis verarbeiten...
res.status(200).json({ received: true });
});Python-Verifizierungsbeispiel
import hmac
import hashlib
import time
def verify_webhook_signature(raw_body: bytes, signature: str, timestamp: str, secret: str) -> bool:
# Zeitstempel-Aktualität prüfen
current_time = int(time.time())
if abs(current_time - int(timestamp)) > 300:
return False
# Erwartete Signatur berechnen
signed_payload = f"{timestamp}.{raw_body.decode('utf-8')}"
expected = hmac.new(
secret.encode('utf-8'),
signed_payload.encode('utf-8'),
hashlib.sha256
).hexdigest()
# Zeitkonstanter Vergleich
return hmac.compare_digest(expected, signature)Das @auris/js-SDK enthält ein integriertes Webhook-Verifizierungsdienstprogramm: import { verifyWebhookSignature } from '@auris/js'. Es handhabt Zeitstempel-Validierung, HMAC-Berechnung und zeitkonstanten Vergleich. Weitere Details in der SDK-Dokumentation.
Zustellungsverhalten
Timeouts
Auris wartet bis zu 30 Sekunden auf eine Antwort von deinem Webhook-Endpunkt. Wenn dein Endpunkt innerhalb dieses Zeitfensters nicht antwortet, wird die Zustellung als fehlgeschlagen markiert.
Wiederholungsrichtlinie
Fehlgeschlagene Zustellungen werden mit exponentiellem Backoff wiederholt:
| Versuch | Verzögerung |
|---|---|
| 1. Wiederholung | 1 Minute |
| 2. Wiederholung | 5 Minuten |
| 3. Wiederholung | 30 Minuten |
Nach 3 fehlgeschlagenen Wiederholungsversuchen wird die Zustellung als dauerhaft fehlgeschlagen markiert. Sie kann weiterhin manuell über die API oder Konsole wiederholt werden.
Automatische Deaktivierung
Wenn ein Webhook 10 aufeinanderfolgende Fehler akkumuliert (über alle Zustellungen), wird er automatisch deaktiviert (isActive: false). Du musst den Endpunkt reparieren und den Webhook manuell über PATCH /api/webhooks/[id] mit { "isActive": true } wieder aktivieren.
Idempotenz
Dein Webhook-Handler sollte idempotent sein. In seltenen Fällen (Netzwerkprobleme, Wiederholungen) kann dasselbe Ereignis mehr als einmal zugestellt werden. Verwende die Felder timestamp und event, um bei Bedarf zu deduplizieren.
Best Practices
- Schnell antworten: Gib so schnell wie möglich einen
2xx-Statuscode zurück. Verarbeite das Ereignis asynchron (z.B. in einer Queue), anstatt schwere Arbeit im Anforderungshandler zu erledigen. - Signaturen verifizieren: Verifiziere immer die HMAC-SHA256-Signatur, bevor du den Payload verarbeitest. Vertraue niemals einem Webhook-Payload ohne Verifizierung.
- HTTPS verwenden: Auris lehnt Nicht-HTTPS-Webhook-URLs ab. Verwende ein gültiges TLS-Zertifikat.
- Wiederholungen handhaben: Gestalte deinen Handler idempotent. Dasselbe Ereignis kann mehr als einmal zugestellt werden.
- Secrets regelmäßig rotieren: Verwende den Rotate-Secret-Endpunkt, um regelmäßig ein neues Signing-Secret zu generieren (z.B. vierteljährlich).
- Zustellungen überwachen: Prüfe das Zustellungsprotokoll in der Konsole oder über die API, um sicherzustellen, dass dein Endpunkt gesund ist.
Zugehörige Referenzen
- Webhooks einrichten — Schritt-für-Schritt-Anleitung zur Erstellung von Webhook-Empfängern
- Webhooks verwalten — Webhooks über die Konsole konfigurieren
- Actions-Engine-API — Benutzerdefinierte Logik-Hooks, die Webhooks ergänzen
- JavaScript SDK —
verifyWebhookSignature()für Signaturverifizierung