Skip to main content
Numero originates every webhook: we decide which events fire, when (including on failure), the exact payload, and the signature. Your integration is a pure receiver — verify the signature, read the fields, branch on status.

Setting up webhooks

For API-issued cards, the Virtual Cards group includes private wallet verification codes (card.code). See Card wallet verification for the payload, source-based delivery routing and sensitive-code handling requirements. Configure your webhook URL in the Merchant Dashboard → Settings → Developer → Webhooks:
  1. Add your webhook endpoint URL
  2. Select the services you want. Each checkbox includes every event in that service; individual-event selection is not offered in the dashboard.
  3. Your signing secret is generated — save it securely (you can view it again anytime via a verification code)
Your signing secret verifies that incoming webhooks are genuinely from Numero. Keep it private and never expose it in client-side code.

How webhooks work

Envelope

Every delivery is a POST of this structure:
The envelope and data use the API’s camelCase field names.

Headers

Event types

¹ An inbound credit has no “merchant failure” to report. ² FX conversion and VA creation are synchronous — a failure is returned in the API response (status: false + a 4xx/503), so there’s nothing to webhook. Branch on the call’s own response for those.
Determine the outcome from data.status (Successful / Unsuccessful / Pending) and data.requestState / data.requestStateDetails — don’t infer it from the event type. A failed outbound transfer/payout fires with status: "Unsuccessful" and requestState: "Failed"; the debit is returned to your wallet through the reversal workflow.

Payloads

Additional subscription events

The dashboard also offers BULK_TRANSFER_NOTIFICATION for terminal bulk-transfer batch outcomes and these WAAS events: These exact, case-sensitive names identify delivered events in both live and test mode. Select WAAS in the dashboard to include every WAAS event. Existing subscriptions retain their selections until you save changes; saving an older individual-event subscription upgrades the selected services to whole groups. Existing API integrations using exact event names or * remain supported. VIRTUAL_ACCOUNT_RETIRED remains reserved and is not currently emitted.

Service groups

The subscription groups are WAAS, VIRTUAL_CARDS, INVOICES, FUNDING, TRANSFERS, BILLS, VERIFICATIONS, VIRTUAL_ACCOUNTS, PAYOUTS and FX. Selecting a group includes its events, including future events in that service. Service availability and access requirements still apply. Virtual Cards includes card.created, card.creation_failed, card.funded, card.funding_failed, card.withdrawn, card.withdrawal_failed, card.frozen, card.unfrozen, card.terminated, card.authorization, card.payment, card.refund, card.reversal and card.declined. Closing a card is termination, not deletion of its transaction history. Invoices includes invoice.created, invoice.updated, invoice.partially_paid, invoice.paid, invoice.cancelled and invoice.expired. These events report recorded lifecycle changes; a due date passing alone is not a payment or a recorded expiry. Card and invoice lifecycle events are queued in the same database transaction as their source changes, then delivered by the background worker (normally on its next minute cycle). Pending card requests do not emit successful creation or funding events. The payload contains customer-facing references, status, currency and relevant amounts or balances—never card credentials. Use data.eventId to deduplicate card and invoice lifecycle events; it stays stable across delivery retries. Delivery is at least once, so a retry may reach an endpoint that previously accepted the event. A test event goes only to test subscriptions, including on retry. The dashboard’s Send test event lets you choose a service. Synthetic non-funding samples carry isSample: true and do not create a real card, invoice or wallet transaction.

TransactionWebhookData — money movement (transfer / funding / payout / internal)

All amounts are in naira.

BillsPurchaseWebhook — VAS

VerificationWebhookData

VirtualAccountCreatedData

CurrencyConversionData

Field casing. The four envelope fields are exactly id, event, created_at and data — note created_at is snake_case. Everything inside data is camelCase, matching the rest of the API.

Retries

  • Respond 2xx to acknowledge. Any non-2xx (or a timeout) is a failed delivery.
  • Every webhook is persisted before delivery, so events are never lost if your endpoint is down.
  • Failed deliveries are retried automatically with exponential backoff for up to 24 hours, and can be re-sent manually from the dashboard. After 10 consecutive failures the subscription is disabled.
  • Webhook delivery never affects the transaction it describes. A failed or refused delivery does not reverse, hold or retry the underlying money movement — treat the webhook as notification, and the transaction status endpoint as the source of truth.