paybondpaybond
Sign in

Integration · Flutterwave

Configure Flutterwave settlement

Tenant-admin guide: save BYO Flutterwave secret key and webhook secret per market (NGN, GHS) in Console Settlement, register Paybond Gateway webhook URLs, and enable the flutterwave_virtual_account rail.

  • BYO secret key
  • VA and Transfers
  • NGN / GHS
  1. 01Connect
  2. 02Configure
  3. 03Verify
  4. 04Go live

Before intents can settle against Flutterwave, a tenant admin configures a Bring-Your-Own (BYO) Flutterwave merchant and the flutterwave_virtual_account rail. Paybond resolves the secret key and webhook secret server-side from this configuration — agents and SDK clients never supply Flutterwave credentials.

The rail funds through Virtual Accounts (VA): a payer sends a bank transfer into a tenant-owned VA, a verified webhook drives the funding gate, and Harbor executes a Transfer payout (or refund/reversal) after evidence evaluation. This guide is analogous to Configure Adyen settlement and Configure settlement rails.

Console workspace

Open Configuration → Settlement (/console/configuration/settlement) as a tenant admin.

From here you should be able to:

  • Save a Flutterwave destination (environment sandbox or live, currency NGN or GHS, label)
  • Enter a write-only secret key and webhook secret (never redisplayed after save)
  • Copy the Gateway webhook URL (carries an unguessable per-destination token) into the Flutterwave dashboard
  • Confirm readiness (secret key ready / webhook secret ready / environment and currency badges)
  • Enable the flutterwave_virtual_account rail once prerequisites are satisfied

Supported Flutterwave rail

RailWhat it settlesRequirement
flutterwave_virtual_accountVA credit funds the intent; Harbor pays out via Transfer or refunds/reverses after evidence evaluationActive Flutterwave destination with secret key and webhook secret for the destination currency (NGN or GHS)

Step 1 — Collect Flutterwave credentials

In the Flutterwave dashboard for your merchant:

  1. Confirm the environment. Sandbox uses the base https://developersandbox-api.flutterwave.com; production uses https://api.flutterwave.com. Do not assume the sandbox and production hosts are the same.
  2. Copy the secret key for the target corridor. V1 uses the v3 secret-key bearer (Authorization: Bearer <SECRET_KEY>). (Flutterwave v4 OAuth2 client-credentials is a future path; V1 stays on BYO secret key for parity with other rails.)
  3. Configure a webhook secret in the dashboard and copy it. This is the value Paybond uses to verify inbound webhook signatures — it is not the same as the secret key.
  4. Note the currency of the corridor (NGN or GHS). The intent budget currency must match the destination currency.

Save a separate destination for each (environment, currency) you operate — for example a sandbox NGN destination and a sandbox GHS destination.

Step 2 — Register the Gateway webhook URL

Register the Paybond Gateway webhook URLs in the Flutterwave dashboard so VA credit and transfer lifecycle events reach Paybond:

  • Live: https://api.paybond.ai/webhooks/live/flutterwave (or the compatibility path /webhooks/flutterwave)
  • Sandbox tenant test traffic: https://api.paybond.ai/webhooks/sandbox/flutterwave

The Console shows the exact URL to copy, including the unguessable per-destination token used to bind the delivery to your tenant. Register the environment-matching URL — sandbox events on the sandbox path, live events on the live path.

Step 3 — Save the destination in Console

In Configuration → Settlement:

  1. Choose sandbox or live environment. Sandbox tenants are restricted to sandbox.
  2. Choose the currency (NGN or GHS) matching the corridor.
  3. Paste the secret key and webhook secret, add a label, then save.

Secrets are write-only. After save, the Console shows the destination environment, currency, label, and ready badges only — never decrypted secrets.

After you rotate the secret key or webhook secret in the Flutterwave dashboard, re-save the destination in Console Settlement immediately so outbound Transfer calls and inbound webhook verification stay aligned.

CLI readiness (paybond flutterwave)

After paybond login, use the Kit CLI to read settlement-config readiness (no secret upsert via CLI):

Terminal
Terminal commandSwipe to inspect long lines
paybond flutterwave ready
paybond flutterwave doctor
paybond flutterwave doctor --format json
  • flutterwave ready checks flutterwave_virtual_account in allowed_rails, destination present, secret key and webhook secret configured, and surfaces the paid-plan gate message when live destinations are blocked.
  • flutterwave doctor expands ready with expected webhook URLs (/webhooks/live/flutterwave and /webhooks/sandbox/flutterwave), the Console-issued per-destination webhook URL when saved, sandbox/live mismatch hints against the signed-in principal, and a pointer to Console destination upsert.
  • Never pass --secret-key, --webhook-secret, --client-id, --client-secret, or --environment on paybond flutterwave argv (rejected; visible in process listings). Upsert those in Console → Settlement write-only fields.

Step 4 — Enable flutterwave_virtual_account

Once readiness reports an active destination with the secret key and webhook secret configured:

  1. Enable Flutterwave virtual account in allowed rails.
  2. Optionally set it as the default rail for the matching currency.
  3. Save routing.

Harbor rejects creates on this rail when no active Flutterwave destination exists for the tenant and destination currency.

Step 5 — Async terminal settlement

VA credit and Transfer payout are asynchronous:

  1. A payer sends a bank transfer into the VA. Flutterwave emits a VA credit / charge.completed webhook. Paybond verifies the signature, binds tx_ref / virtual_account_id / meta_data to your tenant, and moves the intent to funded.
  2. Evidence evaluation moves the intent to evidence_submitted.
  3. Settlement confirm requests a Flutterwave Transfer (on evidence pass) or a refund/reversal (on evidence fail) and waits for confirmation.
  4. The intent stays pending until Paybond receives the terminal webhook — transfer.success finalizes to released; transfer_failed / refund webhooks finalize to refunded.

Treat create-transfer and refund API responses as request-accepted only. A 2xx from the Transfer API is not a terminal state — wait for the webhook.

Operational notes

Misconfigured or missing webhook secret

If the webhook secret in Console does not match the value configured in the Flutterwave dashboard, verification fails and Paybond rejects the deliveries. Symptoms: VA credits do not fund the intent, and Gateway logs record verification rejections. Re-copy the webhook secret from the dashboard into Console Settlement and confirm the signature header (flutterwave-signature preferred, verif-hash legacy) is being sent.

Unbound or unattributable webhooks

Money-state webhooks must carry binding metadata (tx_ref / meta_data with paybond_intent_id and paybond_tenant_id, or a resolvable virtual_account_id) that agrees with the per-destination URL token. Events that cannot be attributed to a tenant are held for manual review and never auto-fund an intent. If VA numbers are provisioned outside Paybond, ensure the binding metadata is stamped at create time.

Stuck or pending transfers

When a Transfer payout webhook lags, the intent stays in its pending terminal state rather than flipping to released/refunded on the API response alone. Paybond re-queries the provider transfer status to converge. Do not patch intent rows to fake a terminal state — preserve the stored provider ids and let recovery reconcile.

Where to go next