curl --request POST \
--url https://api.alphapay.me/api/v1/payments/softpay/ \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"amount": "2500.00",
"currency": "XOF",
"country": "BJ",
"description": "Abonnement mensuel",
"customer": {
"email": "client@example.com",
"first_name": "Awa",
"last_name": "Sossou",
"phone": "+22997505050"
},
"network": "mtn_bj"
}
'import requests
url = "https://api.alphapay.me/api/v1/payments/softpay/"
payload = {
"amount": "2500.00",
"currency": "XOF",
"country": "BJ",
"description": "Abonnement mensuel",
"customer": {
"email": "client@example.com",
"first_name": "Awa",
"last_name": "Sossou",
"phone": "+22997505050"
},
"network": "mtn_bj"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
amount: '2500.00',
currency: 'XOF',
country: 'BJ',
description: 'Abonnement mensuel',
customer: {
email: 'client@example.com',
first_name: 'Awa',
last_name: 'Sossou',
phone: '+22997505050'
},
network: 'mtn_bj'
})
};
fetch('https://api.alphapay.me/api/v1/payments/softpay/', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.alphapay.me/api/v1/payments/softpay/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'amount' => '2500.00',
'currency' => 'XOF',
'country' => 'BJ',
'description' => 'Abonnement mensuel',
'customer' => [
'email' => 'client@example.com',
'first_name' => 'Awa',
'last_name' => 'Sossou',
'phone' => '+22997505050'
],
'network' => 'mtn_bj'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.alphapay.me/api/v1/payments/softpay/"
payload := strings.NewReader("{\n \"amount\": \"2500.00\",\n \"currency\": \"XOF\",\n \"country\": \"BJ\",\n \"description\": \"Abonnement mensuel\",\n \"customer\": {\n \"email\": \"client@example.com\",\n \"first_name\": \"Awa\",\n \"last_name\": \"Sossou\",\n \"phone\": \"+22997505050\"\n },\n \"network\": \"mtn_bj\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.alphapay.me/api/v1/payments/softpay/")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"amount\": \"2500.00\",\n \"currency\": \"XOF\",\n \"country\": \"BJ\",\n \"description\": \"Abonnement mensuel\",\n \"customer\": {\n \"email\": \"client@example.com\",\n \"first_name\": \"Awa\",\n \"last_name\": \"Sossou\",\n \"phone\": \"+22997505050\"\n },\n \"network\": \"mtn_bj\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.alphapay.me/api/v1/payments/softpay/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount\": \"2500.00\",\n \"currency\": \"XOF\",\n \"country\": \"BJ\",\n \"description\": \"Abonnement mensuel\",\n \"customer\": {\n \"email\": \"client@example.com\",\n \"first_name\": \"Awa\",\n \"last_name\": \"Sossou\",\n \"phone\": \"+22997505050\"\n },\n \"network\": \"mtn_bj\"\n}"
response = http.request(request)
puts response.read_body{
"message": "Payment pushed successfully",
"id": "9c3f2a10-4b7e-4f1a-9d2e-9b6a7c1e4a02",
"status": "PENDING",
"checkout_url": ""
}{
"message": "Cette clé API n'est pas autorisée pour les opérations payin (scope actuel : Payout).",
"code": "api_key_scope_forbidden"
}{
"message": "Réseau inconnu ou inactif : 'mtn_xx'.",
"code": "invalid_method"
}Initier un paiement softpay
Push sur le téléphone du client, ou redirection vers une page de paiement selon l’opérateur
curl --request POST \
--url https://api.alphapay.me/api/v1/payments/softpay/ \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"amount": "2500.00",
"currency": "XOF",
"country": "BJ",
"description": "Abonnement mensuel",
"customer": {
"email": "client@example.com",
"first_name": "Awa",
"last_name": "Sossou",
"phone": "+22997505050"
},
"network": "mtn_bj"
}
'import requests
url = "https://api.alphapay.me/api/v1/payments/softpay/"
payload = {
"amount": "2500.00",
"currency": "XOF",
"country": "BJ",
"description": "Abonnement mensuel",
"customer": {
"email": "client@example.com",
"first_name": "Awa",
"last_name": "Sossou",
"phone": "+22997505050"
},
"network": "mtn_bj"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
amount: '2500.00',
currency: 'XOF',
country: 'BJ',
description: 'Abonnement mensuel',
customer: {
email: 'client@example.com',
first_name: 'Awa',
last_name: 'Sossou',
phone: '+22997505050'
},
network: 'mtn_bj'
})
};
fetch('https://api.alphapay.me/api/v1/payments/softpay/', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.alphapay.me/api/v1/payments/softpay/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'amount' => '2500.00',
'currency' => 'XOF',
'country' => 'BJ',
'description' => 'Abonnement mensuel',
'customer' => [
'email' => 'client@example.com',
'first_name' => 'Awa',
'last_name' => 'Sossou',
'phone' => '+22997505050'
],
'network' => 'mtn_bj'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.alphapay.me/api/v1/payments/softpay/"
payload := strings.NewReader("{\n \"amount\": \"2500.00\",\n \"currency\": \"XOF\",\n \"country\": \"BJ\",\n \"description\": \"Abonnement mensuel\",\n \"customer\": {\n \"email\": \"client@example.com\",\n \"first_name\": \"Awa\",\n \"last_name\": \"Sossou\",\n \"phone\": \"+22997505050\"\n },\n \"network\": \"mtn_bj\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.alphapay.me/api/v1/payments/softpay/")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"amount\": \"2500.00\",\n \"currency\": \"XOF\",\n \"country\": \"BJ\",\n \"description\": \"Abonnement mensuel\",\n \"customer\": {\n \"email\": \"client@example.com\",\n \"first_name\": \"Awa\",\n \"last_name\": \"Sossou\",\n \"phone\": \"+22997505050\"\n },\n \"network\": \"mtn_bj\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.alphapay.me/api/v1/payments/softpay/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount\": \"2500.00\",\n \"currency\": \"XOF\",\n \"country\": \"BJ\",\n \"description\": \"Abonnement mensuel\",\n \"customer\": {\n \"email\": \"client@example.com\",\n \"first_name\": \"Awa\",\n \"last_name\": \"Sossou\",\n \"phone\": \"+22997505050\"\n },\n \"network\": \"mtn_bj\"\n}"
response = http.request(request)
puts response.read_body{
"message": "Payment pushed successfully",
"id": "9c3f2a10-4b7e-4f1a-9d2e-9b6a7c1e4a02",
"status": "PENDING",
"checkout_url": ""
}{
"message": "Cette clé API n'est pas autorisée pour les opérations payin (scope actuel : Payout).",
"code": "api_key_scope_forbidden"
}{
"message": "Réseau inconnu ou inactif : 'mtn_xx'.",
"code": "invalid_method"
}checkout_url. Quand elle est non vide, votre client ne recevra AUCUNE demande sur son téléphone : vous devez le rediriger vers cette URL, sinon le paiement n’aura jamais lieu.Ce n’est pas un cas marginal — c’est le fonctionnement normal de Wave, Orange Money, Djamo et des cartes bancaires. Un même réseau peut d’ailleurs basculer d’un mode à l’autre sans préavis, selon la route choisie par notre moteur de routage.const res = await fetch('https://api.alphapay.me/api/v1/payments/softpay/', { /* … */ })
const { data } = await res.json()
if (data.checkout_url) {
// Le paiement se règle sur une page hébergée : redirigez le client.
window.location.href = data.checkout_url
} else {
// Push direct : une demande arrive sur son téléphone, affichez `instructions`
// et sondez GET /payments/{id}/ jusqu'au statut final.
}
return_url sert précisément à ce cas : après paiement sur la page hébergée, votre client y est ramené automatiquement. Sans lui, il reste sur la page du fournisseur.Optionnel pour la quasi-totalité des réseaux (push USSD, pas de page hébergée). Obligatoire pour card/crypto — sans lui, 422 immédiat (return_url manquant), aucun paiement initié. Ces deux réseaux n’ont que la page hébergée, jamais de push : sans URL de retour, votre client n’aurait aucun moyen de revenir chez vous après avoir payé.network valides par pays et le format attendu de customer.phone.
Éviter un doublon en cas de coupure réseau
Le headerIdempotency-Key est optionnel : sans lui, chaque appel crée un paiement — un simple retry réseau en pousse donc un second sur le téléphone du client. Avec lui, renvoyer la même clé après un timeout vous renvoie la réponse d’origine au lieu de rejouer l’opération.
Un timeout n’est jamais la preuve qu’une requête a échoué : elle a pu aboutir côté serveur. C’est précisément ce cas que la clé couvre.
curl -X POST https://api.alphapay.me/api/v1/payments/softpay/ \
-H "Authorization: Bearer sk_live_..." \
-H "Idempotency-Key: 3fa85f64-5717-4562-b3fc-2c963f66afa6" \
-H "Content-Type: application/json" \
-d '{ ... }'
409. Détails : Idempotence.Authorizations
Clé API secrète du marchand — header Authorization: Bearer sk_live_xxx (ou sk_test_xxx en environnement de test).
Headers
Identifiant unique que vous générez pour cette tentative (un UUID par exemple). Optionnel : sans lui, chaque appel est traité comme une nouvelle demande. Avec lui, si vous renvoyez la même clé — après un timeout ou une coupure réseau — AlphaPay renvoie la réponse d'origine au lieu de créer un second paiement. Réutilisez la même clé pour les retrys d'une même tentative, changez-en pour toute nouvelle intention. La même clé avec un corps de requête différent renvoie une erreur 409. Voir Idempotence.
255Body
"2500.00"
3"XOF"
2"BJ"
Show child attributes
Show child attributes
Code réseau, cf. référentiel pays/réseaux
"mtn_bj"
UUID du marchand visé. Ignoré pour une clé API (toujours vous-même) ; pour un token dashboard gérant plusieurs marchands, résout la boutique visée si le header X-Merchant-Id n'est pas fourni.
"Abonnement mensuel"
ADD_ON : les frais s'ajoutent au montant débité au client. DEDUCTED : les frais sont déduits du montant net reversé au marchand. Défaut : configuration du marchand.
ADD_ON, DEDUCTED Code gateway à privilégier si plusieurs sont éligibles pour ce réseau
Response
Paiement poussé avec succès