Skip to content

Collection flows

Collecting a payment always has the same shape: authenticate, initiate, sometimes confirm, then check status. The only thing that changes between providers is the middle step — and it’s decided by the method’s flow, which you read from GET /v1/payment-methods rather than hard-coding.

ProviderflowThe steps
EcoCash, OneMoneypushInitiate → Check status
InnBuckscodeInitiate (returns a code) → Check status
O’mariotpInitiate → Confirm OTP → Check status

Step 0 — Authenticate (every call)

One base URL for test and live — your key decides which. Send it as a bearer token, and put an Idempotency-Key on every POST so a retry can never charge twice.

Terminal window
# sk_test_… = sandbox (no real money) · sk_live_… = real money
-H "Authorization: Bearer sk_test_YOUR_KEY"
-H "Idempotency-Key: a-unique-id-per-charge"

Amounts are always in minor units (1000 = USD 10.00). Numbers like phone numbers go in as 263771234567.

Push — EcoCash, OneMoney

A prompt is pushed to the customer’s phone and they approve it there. You never touch their PIN.

  1. Initiate. The prompt lands on the phone; the payment comes back awaiting_customer.

    Terminal window
    curl https://api.lango.co.zw/v1/payments \
    -H "Authorization: Bearer sk_test_YOUR_KEY" \
    -H "Idempotency-Key: order-4417" \
    -H "Content-Type: application/json" \
    -d '{
    "amount": 1000,
    "currency": "USD",
    "method": "ecocash",
    "reference": "ORD-4417",
    "customer": { "msisdn": "263771234567" }
    }'
  2. Check status. Prefer the payment.* webhook; polling is fine at low volume (back off to a few seconds).

    Terminal window
    curl https://api.lango.co.zw/v1/payments/pay_123 \
    -H "Authorization: Bearer sk_test_YOUR_KEY"

Code — InnBucks

A code is issued and the customer approves it in the InnBucks app or by *569#. USD only.

  1. Initiate. The response is awaiting_code_use and carries a next_action block: the code to show, an expires_at, the instructions, the InnBucks logo_url, and poll_interval_seconds (30). Show the code and instructions to the customer, under the InnBucks logo.

    Terminal window
    curl https://api.lango.co.zw/v1/payments \
    -H "Authorization: Bearer sk_test_YOUR_KEY" \
    -H "Idempotency-Key: order-4418" \
    -H "Content-Type: application/json" \
    -d '{
    "amount": 1000,
    "currency": "USD",
    "method": "innbucks",
    "reference": "ORD-4418",
    "customer": { "msisdn": "263771234567" }
    }'
  2. Check status — at most once every 30 seconds. Poll GET /v1/payments/{id} until it reads succeeded. Polling faster than once per 30s is refused with a 429 (Retry-After) — an InnBucks rule, enforced by the API.

OTP — O’mari

The customer is sent a one-time PIN and enters it to confirm — a two-step rail.

  1. Initiate. The OTP is sent to the phone; the payment comes back awaiting_otp and a checkout_token — you need that token for the next step.

    Terminal window
    curl https://api.lango.co.zw/v1/payments \
    -H "Authorization: Bearer sk_test_YOUR_KEY" \
    -H "Idempotency-Key: order-4419" \
    -H "Content-Type: application/json" \
    -d '{
    "amount": 1000,
    "currency": "USD",
    "method": "omari",
    "reference": "ORD-4419",
    "customer": { "msisdn": "263771234567" }
    }'
  2. Confirm the OTP. The checkout_token is the credential here (no API key). A successful confirm is the real debit.

    Terminal window
    curl https://api.lango.co.zw/v1/checkout/CHECKOUT_TOKEN/otp \
    -H "Content-Type: application/json" \
    -d '{ "otp": "123456" }'
  3. Check status. GET /v1/payments/{id} should now read succeeded.

Where next