Skip to main content
POST
Initiate a Mobile Money deposit

How it works

A deposit is collected in one of two modes, returned as collection_mode. The request is the same in both; what you show the player differs. See Deposit collection modes for the full integration guide.
1

Call POST /deposits

Your backend sends the player’s MSISDN, the amount and a unique reference.
2

Payment request sent

winam-payments sends a payment request to the player’s phone.
3

Player confirms

The player confirms with their Mobile Money PIN.
4

Webhook sent

Your callback_url receives payment.succeeded, payment.failed or payment.expired.
The mode is configured per payment channel. Always read collection_mode from the response instead of deriving it from the operator.

Request

Use POST /api/v1/msisdn/detect to detect the player’s operator from their phone number. The deposit endpoint rejects with 422 any request whose msisdn prefix clearly contradicts operator (MTN: 67x/68x/650-654 · Orange: 69x/655-659).
The reference field is your idempotency key. Two calls with the same reference return the same transaction (and the same instructions) without creating a duplicate. Use a different reference for each distinct payment. A reference already used by another application returns 409. See Idempotency.

Response

status after creation

HTTP 200 does not mean the deposit succeeded. A 200 only means the request was processed. A merchant-initiated deposit that the operator rejects at initiation (invalid number, amount below the operator minimum, USSD error…) comes back as 200 with status: "failed"; the reason is in the state_reason field of GET /api/v1/transactions/{winam_tx_id}.
Final outcomes arrive by webhook:

instructions object

Examples

Values are placeholders.

Customer-initiated deposits: what to implement

1

Show the instructions

Display the steps, the code, a Dial button opening dial_uri and a Copy button copying copy_text.
2

Keep the deposit pending

The transaction stays pending until the payment is confirmed.
3

Poll or wait for the webhook

Poll GET /api/v1/transactions/{winam_tx_id}?lang=en every polling_interval_seconds (the response carries the same collection_mode and instructions while pending), or wait for payment.succeeded on your callback_url.
iOS: a tel: URI containing * or # may not open the dialer. Always offer the Copy button so the player can paste the code into the Phone app.
  • The player must pay from the number sent in msisdn and must not change the amount in the code. See the matching rules.
  • The player’s Mobile Money secret code is typed on their phone only. Never ask for it, transmit it or store it.
  • A customer-initiated deposit that expired can still end succeeded if the player paid late: you receive payment.expired, then payment.succeeded for the same winam_tx_id. See Webhooks.

503 — channel temporarily unavailable

A customer-initiated deposit is refused with 503, and no transaction is created, when the channel cannot confirm payments at the moment. Retry later or offer another payment method. GET /api/v1/{country}/providers/status then reports the provider as degraded or unavailable. The detail is a fixed message:

Authorizations

X-API-Key
string
header
required

Body

application/json
player_id
string<uuid>
required

Player UUID on the sportsbook side

msisdn
string
required

Player MoMo number (E.164)

Example:

"+237670123456"

amount_xaf
integer
required

Amount in XAF (min 100). XAF has no sub-unit.

Required range: x >= 100
operator
string
required

MoMo operator

Examples:

"mtn"

"orange"

reference
string
required

Unique sportsbook reference (idempotency key). Same reference = same transaction returned.

Required string length: 1 - 128
callback_url
string | null

POST URL for notification when payment is confirmed or fails.

Example:

"https://sportsbook.example.com/webhooks/payments"

lang
enum<string>
default:fr

Language of the player-facing instructions.steps texts (customer-initiated collection only).

Available options:
fr,
en

Response

Successful Response

winam_tx_id
string<uuid>
required

Winam internal transaction UUID. Use this with GET /api/v1/transactions/{id}.

reference
string
required

Your idempotency key, echoed back from the request

status
string
required

Initial state. Typically provider_acknowledged (USSD sent to player) or pending (being sent). Terminal states arrive via webhook.

Example:

"provider_acknowledged"

amount_xaf
integer
required

Amount in XAF

Example:

5000

operator
string
required

"mtn" or "orange"

Example:

"mtn"

expires_at
string<date-time> | null

USSD confirmation deadline (typically +10 minutes from creation). The transaction transitions to expired if the player does not confirm before this time.

collection_mode
enum<string>
default:merchant_initiated

merchant_initiated: the merchant SIM sends the payment request to the player. customer_initiated: the player dials instructions.ussd_string from their own phone.

Available options:
merchant_initiated,
customer_initiated
instructions
DepositInstructions · object | null

Player instructions for a customer-initiated collection while the deposit is pending. Null for merchant-initiated collections.