Skip to main content

Flows

Last updated: 2026-05-22

Use this page as an integration playbook for pay-ins and pay-outs.

When to use H2P vs H2H

Use H2P (host-to-page) when:

  • You want the customer to complete payment on a hosted payment page (paymentUrl when returned).
  • You want minimal payment UI logic on your side.

Use H2H (host-to-host) when:

  • You orchestrate payment steps directly from your application.
  • You need method-specific experiences (bank transfer instructions, mobile money OTP flow) and handle any returned payment URL or method-specific instructions in your application.

H2P pay-in flow

  1. Call GET /merchant/api/v1/catalog and choose the market (countryCode, currencyCode) for the payment flow you are implementing. Use methodsIn as the enabled inbound method families for that market.
  2. For mobile-money pay-ins, call GET /merchant/api/v1/payins/mmo for the selected market and request context.
  3. Call POST /merchant/api/v1/payins/initialize with the selected market, the matching PAYMENT_METHOD_* enum value, and the request context you will use operationally. Send the selected market countryCode from /catalog; it is required for mobile-money pay-ins and country-scoped currencies such as NGN, KES, GHS, ZAR, XAF, and XOF. For operator-aware mobile money flows, include the returned operator exactly as returned in mobileMoneyOperator.
  4. Save paymentOrder.id and your merchantReference.
  5. If paymentOrder.paymentUrl is returned, redirect customer there.
  6. Customer may return to your redirectUrl.
  7. Use webhook or GET /merchant/api/v1/payment/{id} to reconcile the latest payment status.
warning

Redirect return is informational. It is not a final success signal.

H2H pay-in flow

  1. Call GET /merchant/api/v1/catalog and choose the market (countryCode, currencyCode) for the payment flow you are implementing. Use methodsIn as the enabled inbound method families for that market.
  2. If the selected inbound method needs bank detail, call GET /merchant/api/v1/payins/banks for the selected market and request context.
  3. For mobile-money pay-ins, call GET /merchant/api/v1/payins/mmo for the selected market and request context.
  4. Call POST /merchant/api/v1/payins/create with the selected market, the matching PAYMENT_METHOD_* enum value, and the request context you will use operationally. Send the selected market countryCode from /catalog; it is required for mobile-money pay-ins and country-scoped currencies such as NGN, KES, GHS, ZAR, XAF, and XOF. For operator-aware mobile money flows, include the returned operator exactly as returned in mobileMoneyDetails.operator. For voucher-based mobile-money pay-ins, also include mobileMoneyDetails.voucherPin.
  5. Process any returned paymentUrl or method-specific instructions:
    • bankAccountDetails.redirectUrl for authorization redirect,
    • bankTransferDetails account details for bank transfer,
    • mobileMoneyDetails instructions for mobile money.
  6. If mobileMoneyDetails.isOtpAuthRequired = true, call POST /merchant/api/v1/payins/authorize-otp.
  7. Wait for webhook updates and/or poll GET /merchant/api/v1/payment/{id} until you have the latest outcome to reconcile.

For mobile-money examples and operator handling, see Mobile money, Vouchers, and Mobile money operators.

Pay-out flow

  1. Call GET /merchant/api/v1/catalog and choose the market (countryCode, currencyCode) for the payout flow you are implementing. Use methodsOut as the enabled outbound method families for that market.
  2. If your flow requires pre-funding checks, read GET /merchant/api/v1/balances and enforce your own pre-checks.
  3. If the selected outbound method needs bank or operator detail, call:
    • GET /merchant/api/v1/payouts/banks
    • GET /merchant/api/v1/payouts/mmo
  4. For mobile-money pay-out, reuse the operator returned by GET /merchant/api/v1/payouts/mmo exactly as returned in mobileMoneyDetails.operator. Include mobileMoneyDetails.accountName when the selected route requires a beneficiary account name.
  5. Call POST /merchant/api/v1/payouts/create with the selected market, the matching PAYMENT_METHOD_* enum value, and the request context for your payout flow. Send the selected market countryCode from /catalog; it is required for country-scoped currencies such as NGN, KES, GHS, ZAR, XAF, and XOF, and it must stay the same across discovery and payout creation.
  6. Track status through webhook and/or GET /merchant/api/v1/payment/{id}.
  7. Finalize only after processing the latest webhook or poll status for that payment.

For operator-aware mobile-money pay-ins, retrieve the operator with GET /merchant/api/v1/payins/mmo before creating or initializing the payment. For mobile-money payouts, retrieve the operator with GET /merchant/api/v1/payouts/mmo before creating the payout. See Mobile money for request examples.

Payment status state machine

stateDiagram-v2
[*] --> CREATED
CREATED --> PENDING
CREATED --> COMPLETED
CREATED --> FAILED
CREATED --> CANCELLED
CREATED --> EXPIRED

PENDING --> PENDING
PENDING --> COMPLETED
PENDING --> FAILED
PENDING --> CANCELLED
PENDING --> EXPIRED

FAILED --> COMPLETED: late provider success

COMPLETED --> [*]
CANCELLED --> [*]
EXPIRED --> [*]

Integration rules

warning

HTTP 200 from your webhook handler means delivery accepted. It does not mean payment success.

  • Use paymentOrder.status as the business outcome.
  • Treat webhooks as primary asynchronous signal.
  • Use GET /merchant/api/v1/payment/{id} for reconciliation, retries, and post-redirect verification.
  • Handle repeated or corrective status updates idempotently. For example, PENDING -> PENDING can repeat, and a late provider confirmation can correct FAILED to COMPLETED.