Skip to main content
A deposit is collected in one of two modes. The mode depends on the payment channel behind the operator and is returned in every deposit response as collection_mode.

Mode per operator (Cameroon)

The mode is configured by Winam per payment channel and can change without an API change. Always branch on collection_mode from the response, never on the operator name. An integration that handles both modes keeps working whatever the configuration.
The request is identical in both modes: same endpoint, same fields. Only the response and the player experience differ. Collection modes apply to deposits only; withdrawals work the same way for every operator.

Side by side

Merchant-initiated flow

1

Create the deposit

Call POST /api/v1/deposits. The response has collection_mode: "merchant_initiated" and instructions: null.
2

The player receives a payment request

winam-payments sends the request to the number given in msisdn. Tell the player to check their phone and enter their Mobile Money PIN.
3

Wait for the outcome

Wait for the webhook on your callback_url, or poll GET /api/v1/transactions/{winam_tx_id}.
If the response already has status: "failed", the operator rejected the request at initiation (invalid number, amount below the operator minimum…). Read state_reason from GET /api/v1/transactions/{winam_tx_id} and let the player retry with a new reference.

Customer-initiated flow

1

Create the deposit

Call POST /api/v1/deposits, optionally with lang (fr default, or en). The response has collection_mode: "customer_initiated", status: "pending" and an instructions object.
2

Display the instructions

Show instructions.steps in order, the code instructions.ussd_string, a Dial button that opens instructions.dial_uri and a Copy button that copies instructions.copy_text.
3

The player pays from their phone

The player dials the code from the number given in msisdn and confirms with their Mobile Money secret code. Nothing is sent to their phone by winam-payments.
4

Wait for the outcome

Poll GET /api/v1/transactions/{winam_tx_id} every instructions.polling_interval_seconds seconds, or wait for the webhook. The deposit stays pending until the payment is confirmed.

What to display

iOS: a tel: link containing * or # may not open the dialer. Always offer the Copy button so the player can paste the code into the Phone app.

Rules that decide whether a payment is credited

The payment is matched to the deposit using the paying number and the exact amount.
  • Paying number. The player must pay from the number sent in msisdn. A payment made from another number is not matched to this deposit.
  • Exact amount. The player must not change the amount in the code. A payment of a different amount is not matched.
  • One player per number and amount. If deposits from two different player_id values are open (or expired recently) for the same number and the same amount, an incoming payment is not credited automatically.
  • Several deposits from the same player. One payment completes exactly one deposit. Prefer returning the existing pending deposit to the player over creating a new one for the same number and amount.
A payment that cannot be matched automatically is not lost: it is held for review by a Winam operator. To have it resolved, contact support with the paying number, the amount and the time of payment.
The player’s Mobile Money secret code is typed on their phone only. Never ask for it, transmit it or store it.

Late payments

The player can pay after expires_at. You then receive payment.expired, and later payment.succeeded for the same winam_tx_id when the payment arrives within the late-payment window (24 hours by default) and matches the deposit. Your webhook handler must accept payment.succeeded on a transaction it already saw as expired, and credit the player.

When the channel is unavailable

POST /api/v1/deposits answers 503 and creates no transaction when the channel cannot confirm payments at the moment. Offer another payment method or let the player retry later. GET /api/v1/{country}/providers/status reports the provider as degraded or unavailable.

Handling both modes

In both branches the final outcome is the same: a payment.succeeded, payment.failed or payment.expired webhook, and the state returned by GET /api/v1/transactions/{winam_tx_id}.

Integration checklist

  • Branch on collection_mode, not on operator.
  • Render instructions when present: code, Dial, Copy, steps.
  • Tell the player to pay from the number they entered and not to change the amount.
  • Keep the deposit screen open while pending and poll, or rely on the webhook.
  • Accept payment.succeeded after payment.expired for the same winam_tx_id.
  • Handle 503 on creation by offering another payment method.
  • Reuse the same reference when retrying the same payment: the same transaction and instructions are returned.