Webhooks empfangen
Webhooks schicken dir Ereignisse in Echtzeit, statt dass du sie abfragen musst. Trage eine URL ein, wähle die Ereignisse aus, die dich interessieren, und prüfe jede Zustellung anhand ihrer HMAC-Signatur.
Abonnieren
Erstelle über die Webhooks-API ein Abonnement mit deiner Endpunkt-URL und den gewünschten eventTypes. Zurück kommt ein Signing-Secret. Bewahre es auf, damit prüfst du jede Zustellung.
curl -H "Authorization: Bearer vokse_sk_…" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -X POST https://api.vokse.ai/households/current/webhooks/subscriptions \ -d '{"url":"https://example.com/hooks/vokse","eventTypes":["transaction.created","budget.overrun"]}'Ereignistypen
Die vollständige, aktuelle Liste der Ereignistypen wird unter /meta/webhook-events bereitgestellt. Der Katalog umfasst derzeit:
- transaction.created · eine Transaktion wurde erfasst.
- recurrence.materialised · ein Dauerauftrag hat seine geplante Transaktion erzeugt.
- bank.sync.completed · eine Bankverbindung hat ihre Synchronisierung abgeschlossen.
- budget.overrun · eine Kategorie hat ihr Monatsbudget überschritten.
- spending.anomaly · eine ungewöhnliche Ausgabe wurde erkannt.
- goal.reached · ein Ziel hat seinen Zielbetrag erreicht.
- insight.generated · ein neuer KI-Einblick steht bereit.
Die Signatur verifizieren
Jede Zustellung trägt einen X-Vokse-Signature-Header der Form t=<Timestamp>,v1=<Signatur>. Die Signatur ist ein HMAC-SHA256 mit deinem Signing-Secret als Schlüssel, berechnet über den Timestamp, einen Punkt und den rohen Request-Body. Baue diese Zeichenkette aus genau den empfangenen Bytes nach, berechne den HMAC neu, vergleiche ihn in konstanter Zeit mit v1 und lehne zu alte Timestamps ab.
import crypto from 'node:crypto';// X-Vokse-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256>function verify(rawBody, signatureHeader, signingSecret) { const parts = new Map( signatureHeader.split(',').map((kv) => kv.split('=')), ); const t = parts.get('t'); const v1 = parts.get('v1'); const expected = crypto .createHmac('sha256', signingSecret) .update(`${t}.${rawBody}`) // timestamp, a dot, the exact bytes received .digest('hex'); if (!t || !v1 || v1.length !== expected.length) return false; // freshness: reject stale timestamps to block replays if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false; return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));}Wiederholungen & Zustellung
Antworte innerhalb weniger Sekunden mit 2xx, um den Empfang zu bestätigen. 5xx-Antworten und Timeouts werden mit exponentiellem Backoff wiederholt, bis zu fünf Versuche; eine 4xx-Antwort gilt als endgültig und wird nie wiederholt. Nach mehreren Fehlschlägen in Folge wird das Abonnement automatisch pausiert und der Eigentümer des Haushalts benachrichtigt.