OuiPay
Webhooks

Webhook Events

The full event catalogue, payload shapes, and when each event fires.

Every event delivers the same envelope:

{
  "id": "01M2S18...",
  "event_type": "payment.completed",
  "event_key": "payment.completed:<transaction_id>",
  "occurred_at": "2026-09-18T01:13:59Z",
  "data": {}
}

event_key is unique per event: dedupe on it, not id. data carries the transaction payload at event time.

Event catalogue

EventFires whenKey data fields
payment.completedA payment settlestransaction_id, amount_minor, currency, method, status
payment.failedA payment fails+ failure.code, failure.stage
transfer.completedA payout settlestransaction_id, amount_minor, currency, beneficiary_id, status
transfer.failedA payout fails+ failure.code, failure.stage
exchange.completedAn exchange settlestransaction_id, from_amount_minor, to_amount_minor, from_currency, to_currency
wallet.fundedAn inbound funding credit posts to a wallettransaction_id, wallet_id, amount_minor, currency, method
transaction.updatedAny status transition on a transactiontransaction_id, status, previous_status

Subscribing to events

Pass events when creating the subscription: an array of event types. transaction.updated subscribes you to all transitions; the typed events (payment.completed, transfer.failed, etc.) subscribe you to specific outcomes.

Success payload

{
  "id": "01M2S18...",
  "event_type": "payment.completed",
  "event_key": "payment.completed:01M2S17G4A0N9MDMXYSCCX8SPS",
  "occurred_at": "2026-09-18T01:13:59Z",
  "data": {
    "transaction_id": "01M2S17G4A0N9MDMXYSCCX8SPS",
    "status": "completed",
    "amount_minor": 101000,
    "currency": "NGN",
    "method": "card",
    "reference": "order-8842"
  }
}

Failure payload

Failed events include the failure details:

{
  "id": "01M2S18...",
  "event_type": "transfer.failed",
  "event_key": "transfer.failed:01M2S18...",
  "occurred_at": "2026-09-18T01:15:00Z",
  "data": {
    "transaction_id": "01M2S18...",
    "status": "failed",
    "failure": {
      "code": "COMPLIANCE_DENIED",
      "message": "This transfer is not permitted.",
      "stage": "compliance"
    }
  }
}

failure.code is machine-readable and stable. failure.stage tells you where in the pipeline the transaction stopped.

On this page