Skip to content

Flutterwave Webhook Checker

Paste the body Flutterwave sent to your webhook URL. You'll see what the event means, whether the verif-hash matches, the exact request that confirms it, and what your code should do next. Nothing leaves your browser.

Webhook body

Try a sample:
Check the verif-hash (optional)

Compared in your browser. Nothing is sent or saved. Never paste your secret API key.

Compare with your order (optional, recommended)

If these don't match, the tool tells you not to fulfil the order.

Result

What your handler should do

    Confirm it with Flutterwave

      Fields in this webhook
      FieldValueMeaning

      Safe webhook handler

      Checks verif-hash in constant time, reads only data.id, verifies with Flutterwave, and never fulfils an order twice.

      How Flutterwave webhooks work

      When a payment finishes, Flutterwave sends a POST to the webhook URL in your dashboard. For a payment the body looks like{"event": "charge.completed", "data": {"id", "tx_ref", "flw_ref", "amount", "currency", "status", ...}}.tx_ref is the reference you chose when you created the charge; id is Flutterwave's transaction id.

      Every request carries a verif-hash header. It is not a signature you compute: it is the secret hash you typed into the dashboard, sent back to you. Compare it with your copy using a constant-time comparison (timingSafeEqual,hash_equals, hmac.compare_digest).

      Five rules for a safe handler

      1. Check verif-hash first. Refuse the request (401) if it is missing or different.
      2. Don't trust the body. Read only data.id, then call GET /v3/transactions/{id}/verify with your secret key.
      3. Check the verified transaction. Its tx_ref must be yours, status must be successful, the currency must match, and the amount must be at least the order total.
      4. Answer 200 within 60 seconds. Anything else, including a redirect, is a failed delivery. Turn on retries in the dashboard so failures are retried.
      5. Be idempotent. Events can repeat. Record event type, transaction id and status, and skip what you've already handled.

      Don't rely on webhooks alone: Flutterwave recommends checking pending transactions from a scheduled job. You can verify by your own reference with GET /v3/transactions/verify_by_reference?tx_ref=....

      Facts from Flutterwave's public v3 documentation (Webhooks and Transaction verification), checked October 2026. The samples are illustrative. Transfer (payout) events are covered more lightly: confirm them with the get-transfer endpoint before you act.

      Frequently asked questions

      How do I verify a Flutterwave webhook signature?

      In the v3 API there is no HMAC to compute. You choose a secret hash in the dashboard's webhook settings, and Flutterwave sends that same value in the verif-hash header. Compare the header with your secret hash using a constant-time comparison, and refuse the request if they differ.

      Can I give value as soon as the webhook says "successful"?

      No. Flutterwave recommends verifying first: call GET /v3/transactions/{id}/verify with the id from the webhook, and give value only if the tx_ref is yours, status is successful, the currency matches, and the amount is at least what you expected.

      What should my webhook endpoint return?

      HTTP 200. Flutterwave treats any other status, including 3xx redirects, as a failure, and times out after 60 seconds. If you turn on retries in the dashboard, it retries a failed delivery 3 times, 30 minutes apart.

      Why does the same Flutterwave webhook arrive twice?

      Retries, and network issues, can deliver an event more than once. Record what you have processed, for example event type plus transaction id plus status, and skip events you have already handled.

      Is it safe to paste my secret hash here?

      The comparison runs in your browser; the page never sends or stores what you type. If you would rather not paste it, leave it empty: the rest of the checks still work. Never paste your secret API key anywhere.

      Related

      Need this built for you?

      I integrate MTN MoMo, M-Pesa and Airtel Money into Laravel / PHP, Python / Django, Node.js / Next.js apps: payments, callbacks, payouts and go-live, with tests.