Skip to main content

Webhook Signature Verification

Every webhook delivery from FYATU includes an X-Fyatu-Signature header. Verify this signature before processing any event — it proves the request originated from FYATU and the body has not been tampered with.

Delivery Headers

Every webhook delivery includes these headers:
Event names use UPPERCASE_SNAKE format: CARD_ISSUED, TRANSACTION_PROCESSED, CARDHOLDER_KYC_APPROVED. Earlier docs may reference dot-notation names such as card.issued — those are deprecated. Always use the header value as the canonical event name.

Webhook Payload Envelope

All events share the same outer envelope:

The Signing Algorithm

FYATU signs every webhook using a two-step process. Step 1 — Derive the signing key Your raw webhook secret (whsec_...) is never used directly as the HMAC key. Instead, FYATU computes:
Step 2 — Sign the message The signed message is {timestamp}.{fullRequestBody}:
Where timestamp is the Unix timestamp from the t= field in X-Fyatu-Signature, and body is the raw request body bytes before any JSON parsing. Step 3 — Compare Extract v1 from the header and compare with your computed signature using a constant-time comparison function to prevent timing attacks.

Verification Examples

Replay Attack Prevention

The t= timestamp in the signature header lets you reject stale requests. Reject any delivery where the timestamp is more than 5 minutes old:
Always enforce the 5-minute window. Without it, an attacker who captures a delivery can replay it hours or days later.

Idempotency — Deduplicating Retries

FYATU retries failed deliveries up to 5 times. The same event may arrive more than once. Use X-Fyatu-Event-ID (also available as eventId in the body) to deduplicate:

Retry Schedule

FYATU retries failed deliveries (any response other than 2xx) on this schedule: After 5 failed attempts the delivery is marked FAILED permanently. You can view and manually replay failed deliveries from the portal under Developer → Webhooks.
Respond 200 OK within 30 seconds — process events asynchronously using a queue. Long-running handlers that time out are treated as failures and trigger a retry.

Best Practices

Use raw body

Always capture the raw request body bytes before JSON parsing. Re-serializing parsed JSON can change whitespace or key order, breaking the signature.

Respond quickly

Return 200 within 30 seconds. Queue events for async processing if your handler does database writes or external API calls.

Reject stale timestamps

Enforce a 5-minute window on t= to prevent replay attacks where captured requests are redelivered later.

Deduplicate with Event-ID

Store processed X-Fyatu-Event-ID values. A retry arriving after your handler already ran should return 200 immediately without re-processing.

Rotate secrets safely

If your webhook secret is compromised, delete the webhook endpoint and create a new one. The old secret stops working immediately.

Test with SANDBOX first

Use the portal’s Send Test Event feature to fire a sample payload to your endpoint before going live.