Skip to main content
Your webhook URL is a public endpoint. Anything on the internet can POST to it, so verify before you credit a balance or release goods.

The flick-signature header

Every delivery carries your webhook secret in a header:
Compare it against the secret stored for your account. Use a constant-time comparison so a wrong value cannot be guessed a byte at a time.
flick-signature is a shared secret presented verbatim, not a signature computed over the request body. Two consequences you must design around:
  • It does not prove the body is unmodified, so trust the amount in the body only after you have re-read the transaction with Transaction status.
  • It contains no timestamp, so a captured delivery can be replayed indefinitely. Deduplicate on data.Id and ignore an Id you have already settled.

Also restrict by transport

Because the header alone is replayable, pair it with at least one of:
  • a long, unguessable path on your webhook URL
  • an allowlist of Flick’s egress addresses, if your infrastructure supports it
  • mutual TLS, if you operate your own ingress

HMAC-signed events

Some newer event types are signed properly rather than carrying the secret:
The signature is HMAC-SHA512(secret, timestamp + "." + rawBody), hex encoded. Verify over the raw request body, before any JSON parsing or re-serialisation — re-encoding changes the bytes and the signature will not match. Reject a timestamp that is more than a few minutes old to stop replays.
If a delivery carries x-flick-signature, prefer it — it is strictly stronger than flick-signature. Accept either, and record which one you verified.