Webhooks
Ereignisse empfangen, Signaturen prüfen, Wiederholungen verstehen.
Endpunkt anlegen
Unter Entwickler → Webhooks oder per API:
curl https://api.freika.com/v1/webhook_endpoints \
-H "Authorization: Bearer $FREIKA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://deinshop.ch/webhooks/freika",
"events": ["payment.succeeded", "payment.failed", "refund.succeeded", "payout.paid"]
}'Die Antwort enthält das secret (beginnt mit whsec_). Es wird nur einmal angezeigt.
Ereignisse
| Ereignis | Wann |
|---|---|
payment.created | Zahlung erstellt |
payment.authorized | Betrag reserviert |
payment.succeeded | Zahlung erfolgreich |
payment.failed | Zahlung abgelehnt oder fehlgeschlagen |
payment.canceled | Zahlung abgebrochen oder abgelaufen |
refund.succeeded, refund.failed | Rückerstattung ausgeführt oder gescheitert |
payout.paid | Auszahlung überwiesen |
chargeback.created | Rückbuchung eingegangen |
terminal.online, terminal.offline | Terminalstatus geändert |
Aufbau
{
"id": "evt_01J9X3B7",
"type": "payment.succeeded",
"created_at": "2026-09-10T09:01:12Z",
"environment": "live",
"data": { "id": "pay_01J9X3A4Q6", "status": "succeeded", "amount": 8900 }
}Signatur prüfen
Jede Zustellung trägt den Header Freika-Signature:
Freika-Signature: t=1757494872,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bdPrüfe so:
- Nimm den Rohtext des Bodys (nicht neu serialisieren).
- Bilde
t + "." + bodyund berechne HMAC-SHA256 mit deinemsecret. - Vergleiche mit
v1in konstanter Zeit. - Lehne Ereignisse ab, deren
tälter als 5 Minuten ist.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(secret: string, header: string, rawBody: string): boolean {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const expected = createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
return fresh && timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}Antworten und Wiederholungen
Antworte innert 10 Sekunden mit 2xx. Alles andere gilt als Fehlschlag. Wir wiederholen mit wachsendem Abstand bis zu 3 Tage lang: nach 1, 5, 30 Minuten, dann stündlich, dann alle 6 Stunden. Ereignisse können mehrfach ankommen; verarbeite sie idempotent anhand von id.
Zustellprotokoll
Unter Entwickler → Webhooks → Zustellungen siehst du jede Zustellung mit Antwortcode und kannst sie erneut senden. Per API: POST /v1/events/{id}/resend.
Testen
Testereignis senden im Dashboard schickt ein payment.succeeded mit Beispieldaten an deinen Endpunkt. In der Sandbox kannst du Zahlungen durchspielen und die echten Ereignisse empfangen.