Encaisser un paiement
Un encaissement (charge) est une demande de paiement adressée à un client SAMA Money. Le client la confirme avec son code secret dans l’application ou par #600# ; vous êtes notifié du résultat. Vous ne manipulez jamais le code secret du client, et il n’existe aucune route pour cela.
Le parcours
Section intitulée « Le parcours »- Votre serveur crée l’encaissement avec
POST /v1/charges: il estpending. - Le client reçoit la demande sur son téléphone et la confirme ou la refuse. Tant qu’il ne l’a fait ni l’un ni l’autre, l’encaissement reste
pending. - SAMA Money vous notifie du résultat :
charge.succeededoucharge.failed. - Votre serveur vérifie la notification, puis valide la commande.
1. Créer l’encaissement
Section intitulée « 1. Créer l’encaissement »| Champ | Obligatoire | Description |
|---|---|---|
client_phone |
oui | Numéro du client avec l’indicatif du pays, de 6 à 20 caractères (par exemple 22370000000). |
amount_xof |
oui | Montant en francs CFA : entier supérieur à 0. |
description |
non | Libellé de l’encaissement. |
reference |
non | Votre référence interne (numéro de commande), conservée avec l’encaissement et renvoyée dans partner_reference. |
L’en-tête Idempotency-Key est facultatif pour un encaissement, mais recommandé : sans lui, chaque appel crée une nouvelle demande. Les exemples utilisent le numéro de test 22370000000.
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": "Commande 1042", "reference": "CMD-1042" }'import { randomUUID } from "node:crypto";
const response = await fetch("https://api.sama.money/v1/charges", { method: "POST", headers: { Authorization: `Bearer ${process.env.SAMA_API_KEY}`, "Idempotency-Key": randomUUID(), "Content-Type": "application/json", }, body: JSON.stringify({ client_phone: "22370000000", amount_xof: 15000, description: "Commande 1042", reference: "CMD-1042", }),});const data = await response.json();if (!response.ok) throw new Error(`${data.error?.code} (requête ${data.error?.request_id})`);console.log(data.reference, data.status);import osimport uuid
import requests
response = requests.post( "https://api.sama.money/v1/charges", headers={ "Authorization": f"Bearer {os.environ['SAMA_API_KEY']}", "Idempotency-Key": str(uuid.uuid4()), }, json={ "client_phone": "22370000000", "amount_xof": 15000, "description": "Commande 1042", "reference": "CMD-1042", }, timeout=30,)data = response.json()if not response.ok: raise SystemExit(f"{data['error']['code']} (requête {data['error']['request_id']})")print(data["reference"], data["status"])<?phpfunction uuid_v4(): string { $b = random_bytes(16); $b[6] = chr((ord($b[6]) & 0x0f) | 0x40); $b[8] = chr((ord($b[8]) & 0x3f) | 0x80); return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($b), 4));}
$ch = curl_init("https://api.sama.money/v1/charges");curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer " . getenv("SAMA_API_KEY"), "Idempotency-Key: " . uuid_v4(), "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "client_phone" => "22370000000", "amount_xof" => 15000, "description" => "Commande 1042", "reference" => "CMD-1042", ]),]);$body = curl_exec($ch);$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);curl_close($ch);$data = json_decode($body, true);if ($status !== 200) { exit("Erreur {$status} : " . ($data["error"]["code"] ?? "inconnue") . " (requête " . ($data["error"]["request_id"] ?? "?") . ")\n");}echo $data["reference"], " ", $data["status"], PHP_EOL;L’API répond 200 avec l’encaissement en attente :
{ "reference": "chg_8f3a1c9e2b7d4e60a1c3", "object": "charge", "mode": "test", "amount_xof": 15000, "currency": "XOF", "client_phone": "22370000000", "status": "pending", "description": "Commande 1042", "partner_reference": "CMD-1042", "account": null, "error_message": null, "created": 1790848800}Enregistrez la reference renvoyée (chg_…) avec votre commande : elle sert à relire l’encaissement et figure dans les notifications. Votre propre référence revient dans partner_reference. mode vaut test avec une clé d’essai. D’autres champs peuvent s’ajouter à la réponse ; ignorez ceux que vous ne connaissez pas.
2. Le client confirme
Section intitulée « 2. Le client confirme »Le client reçoit la demande dans l’application SAMA Money ou, s’il n’a pas de smartphone, dans le menu #600#. Il la confirme avec son code secret ou la refuse. Tant qu’il ne l’a fait ni l’un ni l’autre, la demande reste pending. Sans réponse au bout de 90 jours, elle expire : son état devient expired.
Affichez de votre côté un écran d’attente clair, par exemple « Confirmez le paiement de 15 000 F sur votre téléphone ». Ne considérez jamais une demande pending comme payée.
3. Recevoir le résultat
Section intitulée « 3. Recevoir le résultat »Deux moyens, à combiner :
- Notification (recommandée) : SAMA Money envoie
charge.succeededoucharge.failedà l’adresse que vous avez enregistrée. La mise en place est décrite dans la documentation complète, réservée aux développeurs inscrits. - Lecture du statut avec
GET /v1/charges/{reference}, sans l’interroger en boucle, pour rattraper une notification manquée ou confirmer l’état avant une décision importante :
curl -sS https://api.sama.money/v1/charges/chg_8f3a1c9e2b7d4e60a1c3 \ -H "Authorization: Bearer $SAMA_API_KEY"const reference = "chg_8f3a1c9e2b7d4e60a1c3";const response = await fetch(`https://api.sama.money/v1/charges/${reference}`, { headers: { Authorization: `Bearer ${process.env.SAMA_API_KEY}` },});const data = await response.json();console.log(response.status, data.status);import os
import requests
reference = "chg_8f3a1c9e2b7d4e60a1c3"response = requests.get( f"https://api.sama.money/v1/charges/{reference}", headers={"Authorization": f"Bearer {os.environ['SAMA_API_KEY']}"}, timeout=30,)print(response.status_code, response.json().get("status"))<?php$reference = "chg_8f3a1c9e2b7d4e60a1c3";$ch = curl_init("https://api.sama.money/v1/charges/" . rawurlencode($reference));curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("SAMA_API_KEY")],]);$body = curl_exec($ch);$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);curl_close($ch);$data = json_decode($body, true);echo $status, " ", $data["status"] ?? "?", PHP_EOL;4. Gérer les cas particuliers
Section intitulée « 4. Gérer les cas particuliers »| Situation | Statut ou code | Que faire |
|---|---|---|
| Le client confirme | succeeded |
Validez la commande. |
| L’encaissement n’aboutit pas | failed |
Proposez un autre moyen de paiement. |
| Le client ne répond pas | pending |
La demande reste en attente jusqu’à sa confirmation ou son refus. Ne validez pas la commande. Avant de proposer un nouvel essai, relisez l’état avec GET /v1/charges/{reference}. |
| Votre requête a été coupée avant la réponse | inconnu | Rejouez la même requête avec la même Idempotency-Key. |
5. Tester en bac à sable
Section intitulée « 5. Tester en bac à sable »Avec une clé d’essai, aucun client n’est sollicité et la demande reste pending. La façon de simuler la confirmation du client est décrite dans la documentation complète, réservée aux développeurs inscrits (voir la Référence).
6. Passer en production
Section intitulée « 6. Passer en production »Les clés de production sont activées après l’approbation du compte (Comptes et vérification). Les frais d’un encaissement sont de 0,3 % à la charge du marchand, jamais du client : voir les tarifs.

