Zum Hauptinhalt springen

Ausgehende Webhooks

Pay4Feedback sendet HTTP-POST-Anfragen an Ihren Endpunkt, wenn Ereignisse in Ihrem Konto eintreten. Damit synchronisieren Sie Feedback in Ihr Data Warehouse, stoßen nachgelagerte Automatisierungen an oder pingen Ihre eigenen Monitoring-Systeme.

Ereignisse

EreignisAuslöser
feedback_submittedTeilnehmer sendet Feedback ab und besteht das KI-Scoring
reward_approvedReviewer gibt die Belohnung frei (Manual-Review-Modus)
reward_rejectedReviewer lehnt die Belohnung ab
payout_completedTremendous bestätigt die Auszahlung (oder App-Discount-Code wurde erstellt)
campaign_activatedKampagne wechselt nach Stripe-Zahlung von PENDING_PAYMENT auf ACTIVE

Ein Endpunkt kann alle Ereignisse (*) abonnieren oder nur eine Auswahl.

Payload-Struktur

Alle Ereignisse teilen sich dieselbe Hülle:

{
"event": "reward_approved",
"timestamp": "2026-04-19T14:22:51Z",
"data": {
"responseId": "f3a7e1b2-...",
"rewardId": "bcd8e4f0-...",
"campaignId": "7e1c2d3a-...",
"amount": 12.50,
"currency": "EUR"
}
}

Die Felder in data variieren je Ereignis. Parsen Sie defensiv — zusätzliche Felder können ohne Versionswechsel hinzukommen.

Jede Anfrage enthält:

HeaderWert
Content-Typeapplication/json
User-AgentPay4Feedback-Webhook/1.0
X-Pay4Feedback-TimestampUnix-Sekunden zum Signierzeitpunkt
X-Pay4Feedback-Signaturesha256=<hex> — HMAC-SHA256 über timestamp + "." + rawBody mit Ihrem Shared Secret

Signatur prüfen

Wenn Sie beim Anlegen ein Signing-Secret hinterlegt haben, verifizieren Sie jede Lieferung, bevor Sie reagieren. Signiert wird der Timestamp, ein wörtlicher ., dann der rohe JSON-Body — ohne zusätzliche Whitespaces.

Node.js

import crypto from 'node:crypto';

function verify(req, secret) {
const ts = req.headers['x-pay4feedback-timestamp'];
const sig = req.headers['x-pay4feedback-signature']; // "sha256=abc..."
if (!ts || !sig) return false;

// Replays älter als 5 Min. verwerfen.
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;

const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(`${ts}.${req.rawBody}`) // req.rawBody muss der unparsed body sein
.digest('hex');

return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}

Python

import hmac, hashlib, time

def verify(timestamp: str, signature: str, raw_body: bytes, secret: str) -> bool:
if not timestamp or not signature:
return False
if abs(time.time() - int(timestamp)) > 300:
return False
expected = "sha256=" + hmac.new(
secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)

PHP

function verify(string $timestamp, string $signature, string $rawBody, string $secret): bool {
if (!$timestamp || !$signature) return false;
if (abs(time() - (int)$timestamp) > 300) return false;
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);
return hash_equals($expected, $signature);
}
Rohen Body verwenden

Parsen Sie den JSON-Body nicht neu — JSON.stringify in Node sortiert Keys um, ändert Whitespace oder Unicode-Escapes und das HMAC schlägt fehl. Fangen Sie den Raw-Body ab, bevor ein Parser ihn berührt.

Retry-Verhalten

Antwortet Ihr Endpunkt nicht innerhalb von 10 Sekunden mit 2xx (oder verbindet gar nicht), wiederholen wir mit exponentiellem Backoff:

VersuchWartezeit
1 (initial)
21 Minute
35 Minuten
430 Minuten
52 Stunden
66 Stunden

Nach 5 Retries wird die Zustellung als FAILED markiert und verworfen. 4xx zählt wie 5xx — beide werden retried. Antworten Sie deshalb 2xx, sobald das Ereignis dauerhaft in Ihrer Queue liegt, auch wenn die nachgelagerte Verarbeitung später fehlschlägt.

Jeder Versuch wird protokolliert. Unter Einstellungen → Webhooks → Lieferungen sehen Sie die letzten 50 Versuche pro Endpunkt: Status, HTTP-Code, Fehlermeldung, Versuchszähler. Einträge werden nach 30 Tagen gelöscht.

Best Practices

  • Schnell antworten. Ereignis einfügen, 2xx zurück, dann asynchron verarbeiten. 10 s Timeout plus Transatlantik-Latenz lassen wenig Spielraum.
  • Idempotent bleiben. Ein Retry kann Minuten nach dem ersten Versuch ankommen; gelingen beide, erhält Ihr Endpunkt das Ereignis zweimal. Deduplizieren Sie über data.responseId / data.rewardId / data.claimId.
  • Timestamp prüfen. Verwerfen Sie Lieferungen, die älter als ein paar Minuten sind — verhindert Replay-Angriffe mit abgefangenen Payloads.
  • Secret rotieren Sie, indem Sie einen zweiten Webhook mit neuem Secret anlegen, Ihren Consumer auf beide umschalten und dann den alten löschen.

Einrichtung

  1. Einstellungen → Webhooks → Add Endpoint.
  2. HTTPS-URL einfügen. Non-HTTPS-Endpunkte werden abgelehnt — Signing ersetzt keine Transportverschlüsselung.
  3. Signing Secret setzen. Jeder undurchsichtige String ≥ 32 Zeichen reicht; wir empfehlen kryptografisch zufällig. In Ihrem Secret Manager ablegen.
  4. Ereignisse auswählen — Standard ist "All events".
  5. Add Endpoint klicken.
  6. Send test auf der neuen Zeile klicken. Ein { "event": "test", ... }-Payload wird sofort gesendet; Response-Code bzw. Fehler erscheinen inline. Bei Nicht-2xx korrigieren und erneut testen.
  7. Deliveries öffnen, um Live-Events mitzulesen.

Fehlersuche

"Endpoint responded with HTTP 401 / 403"

Ihr Endpunkt lehnt unauthentifizierte Requests ab, bevor die Signatur geprüft wird. Legen Sie eine Ausnahme für den Webhook-Pfad an oder verifizieren Sie die Signatur statt Bearer-Token-Auth.

"Endpoint responded with HTTP 308"

Redirects werden nicht gefolgt. Tragen Sie die finale URL direkt ein (mit/ohne www., passender TLS-Host, keine Slash-Unterschiede).

Signatur-Mismatch auf Ihrer Seite

In 99 % der Fälle: Sie haben den JSON neu serialisiert. Raw-Body fangen. In Express: app.use(express.json({ verify: (req, _, buf) => { req.rawBody = buf.toString(); } })).

Deliveries zeigt SUCCESS, aber Ihr Downstream sieht nichts

Sie haben 2xx geantwortet, bevor Ihre eigene Queue das Ereignis aufgenommen hat. Prüfen Sie die Lücke zwischen 2xx und den Verarbeitungs-Logs.

Ich brauche ein Ereignis, das nicht gelistet ist

Mail an sales@pay4feedback.com mit dem Use Case. Für konkrete Integrationen haben wir schon Ereignisse ergänzt.

Verwandt