Skip to main content
Card and transfer cover most payments. Two further channels reach customers who prefer to authorise from their banking app or to pay from a basic phone. Both channels appear on hosted checkout when they are enabled for your account. Initialise lists the channels available for each payment in its channels array. If you build a custom pay screen, drive them with the access code in the x-access-code header.

Pay with bank

Pay with bank asks the customer’s bank to authorise the debit. It is a two-call flow: list the banks, then start the charge for the one the customer picks.
1

List the banks

The country query parameter defaults to NG. Show the returned banks in a picker and keep the bank code of the customer’s choice.
2

Start the charge

The 057 shown is an example bank code. Always send the code from the banks list.
3

Send the customer to their bank

The charge response returns data.status of processing, with a redirectUrl and the bank name. Send the customer to that URL so they can approve the debit in their banking app. While they are there, the checkout event stream may emit checkout.awaiting_bank_authorization. Keep the pay screen in a waiting state until the payment completes or fails.
4

Confirm

Wait for the payment.completed webhook, then verify before fulfilling.
If you omit the bank code, the call fails with bank_payment.bank_required. If the bank cannot be reached, you receive bank_payment.failed, and the customer can pick another bank or switch channel.

USSD

USSD works on any phone, with no data connection or app. Vestrapay returns a code, the customer dials it, and the payment is authorised through their bank’s USSD menu.
1

Start the charge

2

Show the code

The response contains the string to dial:
Display data.ussdCode clearly, ideally as a tap-to-dial link on mobile, with a note that the customer should dial it from the phone number they entered.
3

Confirm

Wait for the payment.completed webhook, then verify before fulfilling.
Without a phone number the call fails with ussd.phone_required. If the request cannot be started, ussd.failed tells you to check the number and try again.

Design guidance

  • Treat both as asynchronous. The charge call tells you the payment has started, not that it has succeeded. Do not fulfil on the charge response.
  • Offer a way out. A customer waiting on a bank prompt that never arrives should be able to switch to card or transfer without losing the order. Keep the same payment while the access code is valid, and initialise a new one when it expires.
  • Respect attempt limits. Repeated failures on a payment end with payment.max_attempts_exceeded. Start a fresh payment from your server when that happens.
  • Listen for events. If your pay screen updates live, subscribe to GET /v1/payment/checkout/events and move on as soon as checkout.completed arrives. Still verify from your server.

Failure modes

See Errors for the full code list.