Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.nexapay.ng/llms.txt

Use this file to discover all available pages before exploring further.

Webhooks

NexaPay sends signed outbound webhooks to the merchant webhookUrl whenever merchant account events complete.

How Signing Works

  • NexaPay signs each webhook payload with the merchant’s webhookSecret
  • Merchants verify the signature before trusting the payload
  • Signature verification should happen in your backend, not in browser code

Headers

NexaPay includes headers similar to:
  • x-nexapay-signature
  • x-nexapay-timestamp
  • x-nexapay-event
  • x-nexapay-event-id
  • x-nexapay-business-id

Signature Scheme

The signature is computed over the raw body plus timestamp using HMAC SHA-256.

Webhook Events

deposit.received

Sent when money is credited to a merchant virtual account or business account.
{
  "event": "deposit.received",
  "eventId": "evt_01JABC123XYZ",
  "businessId": "66f1234567890abcde123456",
  "businessName": "Acme Stores",
  "environment": "prod",
  "occurredAt": "2026-05-07T10:15:30.000Z",
  "data": {
    "transactionId": "20260507101530abc",
    "reference": "PAY_20260507_001",
    "accountNumber": "9123456789",
    "amount": 50000,
    "senderName": "John Doe",
    "senderAccount": "0123456789",
    "senderBank": "GTBank",
    "balanceAfter": 125000,
    "status": "successful",
    "merchantCustomerId": "cust_12345",
    "merchantReference": "order_90881",
    "metadata": {
      "purpose": "wallet_topup",
      "source": "checkout"
    }
  }
}

withdrawal.completed

Sent when a merchant withdrawal settles successfully.
{
  "event": "withdrawal.completed",
  "eventId": "evt_01JWXYZ456ABC",
  "businessId": "66f1234567890abcde123456",
  "businessName": "Acme Stores",
  "environment": "prod",
  "occurredAt": "2026-05-07T12:00:00.000Z",
  "data": {
    "transactionId": "20260507115959xyz",
    "reference": "20260507115959xyz",
    "amount": 100000,
    "fee": 2050,
    "totalDebit": 102050,
    "bankAccount": "0123456789",
    "bankName": "GTBank",
    "providerReference": "090110260507120000123456789012",
    "status": "successful",
    "metadata": {
      "purpose": "payout",
      "batchId": "batch_7781"
    }
  }
}

withdrawal.failed

Sent when a merchant withdrawal does not complete.
{
  "event": "withdrawal.failed",
  "eventId": "evt_01JWXYZ789DEF",
  "businessId": "66f1234567890abcde123456",
  "businessName": "Acme Stores",
  "environment": "prod",
  "occurredAt": "2026-05-07T12:05:00.000Z",
  "data": {
    "transactionId": "20260507120459uvw",
    "reference": "20260507120459uvw",
    "amount": 100000,
    "fee": 2050,
    "totalDebit": 102050,
    "bankAccount": "0123456789",
    "bankName": "GTBank",
    "providerReference": null,
    "status": "failed",
    "failureReason": "Insufficient beneficiary balance",
    "metadata": {
      "purpose": "payout",
      "batchId": "batch_7781"
    }
  }
}

Merchant Webhook Secret

NexaPay exposes the merchant webhook secret from the dashboard for authenticated users.

Reveal Secret

GET /business/webhook-secret Returns the current webhook secret so the merchant can verify signatures.

Regenerate Secret

POST /business/webhook-secret/regenerate Rotates the secret and returns the new value. Merchants should update their backend immediately after regenerating.

Delivery Rules

  • Webhooks are sent after the relevant transaction is committed.
  • Delivery is best-effort with retries.
  • Merchants should deduplicate using eventId.
  • Merchants should verify the signature before processing the payload.