Skip to content

Collect a payment

A charge (charge) is a payment request sent to a SAMA Money customer. The customer confirms it with their secret code in the app or through #600#; you are notified of the result. You never handle the customer’s secret code, and there is no route for it.

  1. Your server creates the charge with POST /v1/charges: it is pending.
  2. The customer receives the request on their phone and confirms or declines it. Until they do one or the other, the charge stays pending.
  3. SAMA Money notifies you of the result: charge.succeeded or charge.failed.
  4. Your server verifies the notification, then fulfills the order.
Field Required Description
client_phone yes Customer number with the country code, 6 to 20 characters (for example 22370000000).
amount_xof yes Amount in CFA francs: an integer greater than 0.
description no Label of the charge.
reference no Your own reference (an order number), stored with the charge and returned in partner_reference.

The Idempotency-Key header is optional for a charge, but recommended: without it, every call creates a new request. The examples use the test number 22370000000.

Terminal window
curl -sS -X POST https://api.sama.money/v1/charges \
-H "Authorization: Bearer $SAMA_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"client_phone": "22370000000",
"amount_xof": 15000,
"description": "Order 1042",
"reference": "ORD-1042"
}'

The API answers 200 with the pending charge:

{
"reference": "chg_8f3a1c9e2b7d4e60a1c3",
"object": "charge",
"mode": "test",
"amount_xof": 15000,
"currency": "XOF",
"client_phone": "22370000000",
"status": "pending",
"description": "Order 1042",
"partner_reference": "ORD-1042",
"account": null,
"error_message": null,
"created": 1790848800
}

Store the reference returned (chg_…) with your order: it is used to read the charge back and it appears in notifications. Your own reference comes back in partner_reference. mode is test with a test key. Other fields may be added to the response; ignore the ones you do not know.

The customer receives the request in the SAMA Money app or, if they have no smartphone, in the #600# menu. They confirm it with their secret code or decline it. Until they do one or the other, the request stays pending. Left unanswered for 90 days, it expires: its state becomes expired.

On your side, show a clear waiting screen, for example “Confirm the payment of 15,000 F on your phone”. Never treat a pending request as paid.

Two ways, to be combined:

  1. Webhook (recommended): SAMA Money sends charge.succeeded or charge.failed to the address you registered. How to set it up is described in the full documentation, reserved for registered developers.
  2. Reading the status with GET /v1/charges/{reference}, without polling it in a loop, to catch up on a missed notification or to confirm the state before an important decision:
Terminal window
curl -sS https://api.sama.money/v1/charges/chg_8f3a1c9e2b7d4e60a1c3 \
-H "Authorization: Bearer $SAMA_API_KEY"
Situation Status or code What to do
The customer confirms succeeded Fulfill the order.
The charge does not go through failed Offer another payment method.
The customer does not answer pending The request stays pending until it is confirmed or declined. Do not fulfill the order. Before offering a new attempt, read the state with GET /v1/charges/{reference}.
Your request was cut off before the response unknown Replay the same request with the same Idempotency-Key.

With a test key, no customer is contacted and the request stays pending. How to simulate the customer’s confirmation is described in the full documentation, reserved for registered developers (see the Reference).

Live keys are activated once the account is approved (Accounts and verification). The fee on a charge is 0.3%, paid by the merchant, never by the customer: see the pricing.