Skip to content

Payment Lifecycle

This page describes the complete flow from session creation to payment confirmation.

Flow overview

Your Server                    ZevPay API                  Customer
    │                              │                          │
    │  POST /initialize            │                          │
    │─────────────────────────────▶│                          │
    │  { session_id, checkout_url }│                          │
    │◀─────────────────────────────│                          │
    │                              │                          │
    │  Return checkout_url or      │                          │
    │  pass public key to SDK      │                          │
    │─────────────────────────────────────────────────────────▶│
    │                              │                          │
    │                              │  POST /payment-method    │
    │                              │◀─────────────────────────│
    │                              │  { account_number, ... } │
    │                              │─────────────────────────▶│
    │                              │                          │
    │                              │      Customer pays       │
    │                              │◀─────────────────────────│
    │                              │                          │
    │  Webhook: charge.success     │                          │
    │◀─────────────────────────────│                          │
    │                              │                          │
    │  GET /verify (optional)      │                          │
    │─────────────────────────────▶│                          │
    │  { status: "completed" }     │                          │
    │◀─────────────────────────────│                          │

Step-by-step

1. Initialize session

Your server calls POST /v1/checkout/session/initialize with your secret key, the amount, and customer email.

2. Customer selects payment method

The checkout UI (inline modal or standard page) presents the available payment methods. When the customer selects one, the SDK calls POST /v1/checkout/session/:id/payment-method.

For bank transfer, this returns a virtual account number. For PayID, this returns a dynamic PayID.

3. Customer completes payment

The customer transfers money (via bank or ZevPay app). We detect the transfer automatically.

4. Payment confirmed

We:

  • Mark the session as completed
  • Send a charge.success webhook to your server
  • The checkout UI detects the completion via polling and shows a success screen

5. You verify and fulfill

Your server verifies the payment via the webhook or the /verify endpoint, then fulfills the order.

Polling

Both the inline and standard checkout SDKs poll the /verify endpoint every 5 seconds after the customer selects a payment method. When the status changes to completed, the success screen is shown automatically.

Idempotency

  • Each session can only be completed once
  • Duplicate bank transfers to the same virtual account are rejected
  • The reference parameter on initialization helps you prevent duplicate sessions

Refunds

A payment can be returned to the payer while it is still pending settlement, meaning before it is picked up by a payout batch. Request it from the transaction page in your dashboard: the Refund button is active only while the payment still qualifies.

What happens next:

  1. The payment is immediately held out of your next settlement, so the money stops on its way to you.
  2. ZevPay returns it to the payer, through the provider where that is supported and by transfer otherwise.
  3. You receive charge.refunded and the transaction shows as refunded.

If the request is declined, the payment goes back into your next settlement and nothing changes for you.

Bank transfer, card, PalmPay and Static NGN Account payments can be refunded this way. ZevPay ID and crypto payments are returned by support instead. Once a payment has been paid out to you, a refund is handled with support, not from the dashboard. Static NGN Account payments can also be refunded through the API.

Error handling

ScenarioWhat happens
Session expires (30 min)Status set to expired, customer shown expiry screen
Transfer amount mismatchTransfer may not be matched to the session
Network error during pollingSDK retries silently on next poll interval
Webhook delivery failsLogged in dashboard, you should poll /verify as backup

ZevPay Checkout Developer Documentation