SOLIMI - For Cashless World

API publique de collecte de paiement

Documentation d'integration SOLIMI pour marchands, fintechs et banques

Ce guide explique comment connecter votre application a l'API publique SOLIMI pour initier des paiements, consulter leur statut, lire votre solde, recuperer les moyens de paiement disponibles et recevoir les notifications webhook.

REST JSON HMAC-SHA256 Idempotence Webhooks securises
Authentification Chaque requete est signee avec votre cle secrete API.
Devise Les transactions de collecte sont exprimees en XOF.
Canaux Mobile money, compte SOLIMI et carte SOLIMI.

Environnements et pre-requis

Avant l'integration, l'equipe SOLIMI vous fournit un compte partenaire, une cle API, un secret API et configure les adresses IP autorisees. Le secret API est affiche une seule fois: conservez-le dans un coffre de secrets.

Environnement Base URL Usage
Local developpement http://localhost:8000 Tests internes SOLIMI ou recette locale.
Sandbox https://sandbox-api.solimi.co Integration partenaire avant mise en production.
Production https://api.solimi.co Transactions reelles apres validation SOLIMI.
Les domaines sandbox et production ci-dessus sont les URLs de reference a confirmer avec SOLIMI lors de l'onboarding. Ne partagez jamais votre secret API dans un frontend, une application mobile ou un depot Git.

Authentification HMAC

Toutes les routes publiques securisees utilisent une signature HMAC SHA-256. SOLIMI verifie votre cle API, l'adresse IP source, l'horodatage et la signature calculee a partir du corps exact de la requete.

Headers obligatoires

Header Description
x-api-key Votre cle API publique, par exemple sk_test_... ou sk_live_....
x-timestamp Timestamp Unix en secondes. La tolerance est de 300 secondes.
x-signature HMAC SHA-256 hexadecimal du message raw_body + timestamp.
Idempotency-Key Obligatoire pour POST /v1/payments/request. Doit etre unique par tentative logique.

Algorithme

message = raw_request_body + x_timestamp
x_signature = HMAC_SHA256_HEX(api_secret, message)

Pour une requete GET, le corps est vide. Le message signe est donc uniquement le timestamp.

Paiements

Une demande de paiement cree une intention de collecte. Selon le type de paiement, le client approuve le paiement sur mobile money, via son compte SOLIMI ou via une carte SOLIMI.

Mobile money

payment_type = mobile_money

Requiert provider: mixx, coris_money ou moov_money.

Compte SOLIMI

payment_type = solimi_account

Requiert account_id sur 12 chiffres.

Carte SOLIMI

payment_type = solimi_card

Requiert card_id sur 8 chiffres.

Cycle de vie

Statut Signification
INITIATEDLa demande de paiement est creee.
PENDING_APPROVALLe paiement attend l'approbation du client.
APPROVEDLe client a approuve le paiement.
PROCESSINGLe traitement est en cours.
SUCCESSLe paiement est reussi.
FAILEDLe paiement a echoue.
DECLINEDLe client ou le systeme a refuse le paiement.
EXPIREDLa demande a expire.
CANCELLEDLa demande a ete annulee.

Reference des payloads et validations

Cette section precise le role de chaque champ, son type, son caractere obligatoire, sa taille et le format attendu. Les regex ci-dessous sont les validations recommandees cote integrateur, afin de detecter les erreurs avant l'appel API.

SOLIMI valide strictement les payloads. Si un champ optionnel n'est pas applicable au type de paiement, ne l'envoyez pas. Exemple: n'envoyez pas account_id pour un paiement mobile_money.

Headers de securite

Champ Role Type Obligatoire Taille Regex / Format Exemple
x-api-key Identifie la cle API du partenaire. string Oui Variable ^sk_(test|live)_[A-Za-z0-9]+$ sk_test_abcd...
x-timestamp Protege contre le rejeu de requetes. string numeric Oui 10 chiffres en secondes ^\d{10}$, Unix timestamp, tolerance 300s 1781899200
x-signature Prouve que la requete vient du serveur partenaire. string Oui 64 caracteres ^[a-f0-9]{64}$ 7d9f...a31c
Idempotency-Key Evite la creation de doublons lors des retries. string Oui pour creation paiement Recommande: 1 a 100 ^[A-Za-z0-9._:-]{1,100}$ ORDER-2026-0001

PaymentRequestCreate - Creation d'un paiement

Champ Role metier Type Obligatoire Taille Regex / Valeurs Notes
merchant_reference Reference unique de la transaction dans le systeme du marchand. string Oui 1 a 100 caracteres ^[A-Za-z0-9._:-]{1,100}$ recommande Utilisez la meme valeur comme base de Idempotency-Key.
payment_type Canal de paiement a utiliser. enum string Oui Variable mobile_money, solimi_account, solimi_card Determine les champs conditionnels requis.
amount Montant a collecter. integer Oui Nombre entier positif ^[1-9]\d*$ Montant en XOF, sans decimales.
currency Devise de la transaction. literal string Non 3 caracteres ^XOF$ Facultatif. Si absent, le backend applique XOF.
description Libelle visible pour reconciliation ou support. string Oui Minimum 1 caractere ^.{1,}$ Recommande: inclure le numero de commande.
customer_phone Numero du client payeur. string Oui 8 a 20 caracteres ^\+?[0-9]{8,20}$ recommande Envoyez le numero au format international quand possible.
provider Operateur mobile money a utiliser. enum string Oui si mobile_money Variable mixx, coris_money, moov_money Ne pas envoyer pour solimi_account ou solimi_card.
account_id Identifiant du compte SOLIMI client. string Oui si solimi_account Exactement 12 chiffres ^\d{12}$ Refuse si la longueur est differente de 12.
card_id Identifiant de la carte SOLIMI client. string Oui si solimi_card Exactement 8 chiffres ^\d{8}$ Refuse si la longueur est differente de 8.

Regles conditionnelles par type de paiement

payment_type Champ requis Champs a ne pas envoyer Exemple minimal
mobile_money provider account_id, card_id {"payment_type":"mobile_money","provider":"mixx"}
solimi_account account_id provider, card_id {"payment_type":"solimi_account","account_id":"1234567890"}
solimi_card card_id provider, account_id {"payment_type":"solimi_card","card_id":"12345678"}

PaymentRequestResponse - Reponse de creation

Champ Role Type Format / Valeurs
referenceReference SOLIMI du paiement.stringPAY-..., a conserver pour le suivi.
merchant_referenceReference marchand transmise dans la requete.string1 a 100 caracteres.
payment_typeType de paiement retenu.enummobile_money, solimi_account, solimi_card.
providerOperateur mobile money.enum ou nullmixx, coris_money, moov_money, ou null.
amountMontant demande.integerEntier positif.
currencyDevise.stringXOF.
descriptionLibelle de la demande.stringTexte non vide.
customer_phoneNumero client.string8 a 20 caracteres.
statusEtat initial ou courant.enumVoir la table des statuts.
expires_atDate d'expiration de la demande.datetimeISO 8601, UTC recommande.
created_atDate de creation.datetimeISO 8601.

PaymentStatusResponse - Suivi de paiement

Champ Role Type Format / Valeurs
referenceReference SOLIMI a interroger.stringPAY-....
merchant_referenceReference du marchand.string1 a 100 caracteres.
partner_idIdentifiant technique du partenaire.UUID^[0-9a-fA-F-]{36}$.
payment_typeCanal utilise.enumTypes de paiement supportes.
providerProvider mobile money.enum ou nullNull hors mobile money.
amountMontant.integerEntier positif.
currencyDevise.stringXOF.
statusEtat courant.enumINITIATED, PENDING_APPROVAL, APPROVED, PROCESSING, SUCCESS, FAILED, DECLINED, EXPIRED, CANCELLED.
failure_reasonCause d'echec si disponible.string ou nullRenseigne principalement les statuts non reussis.
expires_atExpiration.datetimeISO 8601.
approved_atDate d'approbation client.datetime ou nullISO 8601.
completed_atDate de succes final.datetime ou nullISO 8601.
failed_atDate d'echec.datetime ou nullISO 8601.
declined_atDate de refus.datetime ou nullISO 8601.

Payloads webhook

Champ Role Type Obligatoire Format / Regex
urlEndpoint HTTPS du partenaire.URLOui a la creation^https://.+ recommande en production.
secretSecret partage avec SOLIMI pour authentifier les webhooks recus.stringNonMinimum 16 caracteres. Recommande: 32+ caracteres aleatoires.
is_activeActive ou desactive la reception.booleanNon, uniquement updatetrue ou false.

Endpoints publics

Les endpoints ci-dessous sont accessibles sous le prefixe /v1.

GET/v1/health

Public

Verifie la disponibilite de l'API.

Headers

HeaderObligatoireValeur
content-typeNonapplication/json

Payload

Aucun body requis.

Reponses possibles

HTTPCasCorps
200API disponible{"status":"ok","service":"solimi-payment-api"}
5xxService indisponibleErreur serveur ou timeout infrastructure.

Exemples d'appel

cURL
curl -X GET "{{base_url}}/v1/health"
PHP
<?php
echo file_get_contents("{{base_url}}/v1/health");
Node.js
const response = await fetch("{{base_url}}/v1/health");
console.log(await response.json());
Python
import requests

response = requests.get("{{base_url}}/v1/health")
print(response.json())

Exemple de reponse 200

{
  "status": "ok",
  "service": "solimi-payment-api"
}

POST/v1/payments/request

HMAC + Idempotency-Key

Cree une demande de paiement.

Headers obligatoires

HeaderRoleFormat / valeur
content-typeFormat du body.application/json
x-api-keyIdentifie le partenaire.Cle API fournie par SOLIMI.
x-timestampProtection anti-rejeu.Timestamp Unix en secondes, tolerance 300s.
x-signatureAuthentifie la requete.HMAC SHA-256 hex de raw_body + timestamp.
Idempotency-KeyEvite les doublons lors des retries.Unique par tentative logique, ex: ORDER-2026-0001.

Payload et validations

ChampTypeObligatoireValeurs / regexRole
merchant_referencestringOui1-100, ^[A-Za-z0-9._:-]{1,100}$Reference unique cote marchand.
payment_typeenumOuimobile_money, solimi_account, solimi_cardCanal de collecte.
providerenum/nullOui si mobile moneymixx, moov_money, coris_moneyOperateur mobile money.
amountintegerOui^[1-9]\d*$Montant XOF sans decimales.
currencystringNonXOFFacultatif. Devise par defaut appliquee par le backend.
descriptionstringOuiNon videLibelle/reconciliation.
customer_phonestringOui^\+?[0-9]{8,20}$Numero du client payeur.
account_idstring/nullOui si compte SOLIMI^\d{12}$Compte SOLIMI du client.
card_idstring/nullOui si carte SOLIMI^\d{8}$Carte SOLIMI du client.

Exemple de payload

{
  "merchant_reference": "ORDER-2026-0001",
  "payment_type": "mobile_money",
  "provider": "mixx",
  "amount": 25000,
  "description": "Commande ORDER-2026-0001",
  "customer_phone": "22890112233"
}

Reponses possibles

HTTPCode applicatifCas
201-Demande de paiement creee.
400domain_errorRegle metier invalide.
401authentication_failedHeaders HMAC manquants ou invalides.
403authorization_failedIP non autorisee, partenaire inactif ou credentials invalides.
409idempotency_conflict / duplicate_merchant_referenceCle idempotente reutilisee avec un payload different ou reference marchand deja utilisee.
422validation_errorChamp manquant ou format invalide.
500payment_core_sync_failedErreur de synchronisation interne avec le noyau SOLIMI.

Exemples d'appel

cURL
BODY='{"merchant_reference":"ORDER-2026-0001","payment_type":"mobile_money","provider":"mixx","amount":25000,"description":"Commande ORDER-2026-0001","customer_phone":"22890112233"}'
TIMESTAMP=$(date +%s)
SIGNATURE=$(printf "%s%s" "$BODY" "$TIMESTAMP" | openssl dgst -sha256 -hmac "$SOLIMI_API_SECRET" -hex | sed 's/^.* //')

curl -X POST "{{base_url}}/v1/payments/request" \
  -H "content-type: application/json" \
  -H "x-api-key: $SOLIMI_API_KEY" \
  -H "x-timestamp: $TIMESTAMP" \
  -H "x-signature: $SIGNATURE" \
  -H "Idempotency-Key: ORDER-2026-0001" \
  -d "$BODY"
PHP
<?php
$apiKey = getenv("SOLIMI_API_KEY");
$apiSecret = getenv("SOLIMI_API_SECRET");
$timestamp = (string) time();
$body = json_encode([
  "merchant_reference" => "ORDER-2026-0001",
  "payment_type" => "mobile_money",
  "provider" => "mixx",
  "amount" => 25000,
  "description" => "Commande ORDER-2026-0001",
  "customer_phone" => "22890112233"
], JSON_UNESCAPED_SLASHES);
$signature = hash_hmac("sha256", $body . $timestamp, $apiSecret);

$ch = curl_init("{{base_url}}/v1/payments/request");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POSTFIELDS => $body,
  CURLOPT_HTTPHEADER => [
    "content-type: application/json",
    "x-api-key: $apiKey",
    "x-timestamp: $timestamp",
    "x-signature: $signature",
    "Idempotency-Key: ORDER-2026-0001"
  ]
]);
echo curl_exec($ch);
Node.js
import crypto from "node:crypto";

const body = JSON.stringify({
  merchant_reference: "ORDER-2026-0001",
  payment_type: "mobile_money",
  provider: "mixx",
  amount: 25000,
  description: "Commande ORDER-2026-0001",
  customer_phone: "22890112233"
});
const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = crypto.createHmac("sha256", process.env.SOLIMI_API_SECRET).update(body + timestamp).digest("hex");

const response = await fetch("{{base_url}}/v1/payments/request", {
  method: "POST",
  headers: {
    "content-type": "application/json",
    "x-api-key": process.env.SOLIMI_API_KEY,
    "x-timestamp": timestamp,
    "x-signature": signature,
    "Idempotency-Key": "ORDER-2026-0001"
  },
  body
});
console.log(await response.json());
Python
import hashlib
import hmac
import json
import os
import time
import requests

payload = {
    "merchant_reference": "ORDER-2026-0001",
    "payment_type": "mobile_money",
    "provider": "mixx",
    "amount": 25000,
    "description": "Commande ORDER-2026-0001",
    "customer_phone": "22890112233",
}
body = json.dumps(payload, separators=(",", ":"), ensure_ascii=False)
timestamp = str(int(time.time()))
signature = hmac.new(os.environ["SOLIMI_API_SECRET"].encode(), (body + timestamp).encode(), hashlib.sha256).hexdigest()

response = requests.post(
    "{{base_url}}/v1/payments/request",
    data=body.encode(),
    headers={
        "content-type": "application/json",
        "x-api-key": os.environ["SOLIMI_API_KEY"],
        "x-timestamp": timestamp,
        "x-signature": signature,
        "Idempotency-Key": "ORDER-2026-0001",
    },
)
print(response.json())

Exemple de reponse 201

{
  "reference": "PAY-8C7F36A1B2",
  "merchant_reference": "ORDER-2026-0001",
  "payment_type": "mobile_money",
  "provider": "mixx",
  "amount": 25000,
  "currency": "XOF",
  "description": "Commande ORDER-2026-0001",
  "customer_phone": "22890112233",
  "status": "PENDING_APPROVAL",
  "expires_at": "2026-06-19T21:00:00Z",
  "created_at": "2026-06-19T20:45:00Z"
}

GET/v1/payments/status/{reference}

HMAC

Retourne l'etat courant d'un paiement.

Headers obligatoires

HeaderRoleFormat / valeur
x-api-keyIdentifie le partenaire.Cle API fournie par SOLIMI.
x-timestampProtection anti-rejeu.Timestamp Unix en secondes.
x-signatureAuthentifie la requete GET.HMAC SHA-256 hex du timestamp.

Parametres

ParametreTypeObligatoireFormatRole
referencepath stringOuiPAY-... ou SOLPAY...Reference SOLIMI retournee a la creation.

Reponses possibles

HTTPCode applicatifCas
200-Statut retourne.
401authentication_failedSignature invalide.
403authorization_failedPartenaire non autorise.
404not_foundReference inconnue pour ce partenaire.

Exemples d'appel

cURL
TIMESTAMP=$(date +%s)
SIGNATURE=$(printf "%s" "$TIMESTAMP" | openssl dgst -sha256 -hmac "$SOLIMI_API_SECRET" -hex | sed 's/^.* //')
curl -X GET "{{base_url}}/v1/payments/status/PAY-8C7F36A1B2" \
  -H "x-api-key: $SOLIMI_API_KEY" \
  -H "x-timestamp: $TIMESTAMP" \
  -H "x-signature: $SIGNATURE"
PHP
<?php
$timestamp = (string) time();
$signature = hash_hmac("sha256", $timestamp, getenv("SOLIMI_API_SECRET"));
$opts = ["http" => ["header" => "x-api-key: ".getenv("SOLIMI_API_KEY")."\r\nx-timestamp: $timestamp\r\nx-signature: $signature\r\n"]];
echo file_get_contents("{{base_url}}/v1/payments/status/PAY-8C7F36A1B2", false, stream_context_create($opts));
Node.js
import crypto from "node:crypto";

const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = crypto.createHmac("sha256", process.env.SOLIMI_API_SECRET).update(timestamp).digest("hex");
const response = await fetch("{{base_url}}/v1/payments/status/PAY-8C7F36A1B2", {
  headers: {"x-api-key": process.env.SOLIMI_API_KEY, "x-timestamp": timestamp, "x-signature": signature}
});
console.log(await response.json());
Python
import hashlib, hmac, os, time, requests

timestamp = str(int(time.time()))
signature = hmac.new(os.environ["SOLIMI_API_SECRET"].encode(), timestamp.encode(), hashlib.sha256).hexdigest()
response = requests.get(
    "{{base_url}}/v1/payments/status/PAY-8C7F36A1B2",
    headers={"x-api-key": os.environ["SOLIMI_API_KEY"], "x-timestamp": timestamp, "x-signature": signature},
)
print(response.json())

Exemple de reponse 200

{
  "reference": "PAY-8C7F36A1B2",
  "merchant_reference": "ORDER-2026-0001",
  "partner_id": "945adbc3-1e63-46da-8128-8ef790b50714",
  "payment_type": "mobile_money",
  "provider": "mixx",
  "amount": 25000,
  "currency": "XOF",
  "status": "SUCCESS",
  "failure_reason": null,
  "expires_at": "2026-06-19T21:00:00Z",
  "approved_at": "2026-06-19T20:46:11Z",
  "completed_at": "2026-06-19T20:46:18Z",
  "failed_at": null,
  "declined_at": null
}

GET/v1/account/balance

HMAC

Retourne le solde disponible et le solde reserve du partenaire.

Headers obligatoires

HeaderRoleFormat / valeur
x-api-keyIdentifie le partenaire.Cle API fournie par SOLIMI.
x-timestampProtection anti-rejeu.Timestamp Unix en secondes.
x-signatureAuthentifie la requete GET.HMAC SHA-256 hex du timestamp.

Payload

Aucun body requis.

Reponses possibles

HTTPCode applicatifCas
200-Solde retourne.
401authentication_failedSignature invalide.
403authorization_failedPartenaire non autorise.

Exemples d'appel

cURL
TIMESTAMP=$(date +%s)
SIGNATURE=$(printf "%s" "$TIMESTAMP" | openssl dgst -sha256 -hmac "$SOLIMI_API_SECRET" -hex | sed 's/^.* //')
curl -X GET "{{base_url}}/v1/account/balance" \
  -H "x-api-key: $SOLIMI_API_KEY" \
  -H "x-timestamp: $TIMESTAMP" \
  -H "x-signature: $SIGNATURE"
PHP
<?php
$timestamp = (string) time();
$signature = hash_hmac("sha256", $timestamp, getenv("SOLIMI_API_SECRET"));
$opts = ["http" => ["header" => "x-api-key: ".getenv("SOLIMI_API_KEY")."\r\nx-timestamp: $timestamp\r\nx-signature: $signature\r\n"]];
echo file_get_contents("{{base_url}}/v1/account/balance", false, stream_context_create($opts));
Node.js
import crypto from "node:crypto";

const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = crypto.createHmac("sha256", process.env.SOLIMI_API_SECRET).update(timestamp).digest("hex");
const response = await fetch("{{base_url}}/v1/account/balance", {
  headers: {"x-api-key": process.env.SOLIMI_API_KEY, "x-timestamp": timestamp, "x-signature": signature}
});
console.log(await response.json());
Python
import hashlib, hmac, os, time, requests

timestamp = str(int(time.time()))
signature = hmac.new(os.environ["SOLIMI_API_SECRET"].encode(), timestamp.encode(), hashlib.sha256).hexdigest()
response = requests.get(
    "{{base_url}}/v1/account/balance",
    headers={"x-api-key": os.environ["SOLIMI_API_KEY"], "x-timestamp": timestamp, "x-signature": signature},
)
print(response.json())

Exemple de reponse 200

{
  "partner_reference": "PART-637C64AC5B75",
  "currency": "XOF",
  "available_balance": 1250000,
  "reserved_balance": 50000,
  "environment": "sandbox"
}

GET/v1/payment-methods

HMAC

Liste les moyens de paiement actifs.

Headers obligatoires

HeaderRoleFormat / valeur
x-api-keyIdentifie le partenaire.Cle API fournie par SOLIMI.
x-timestampProtection anti-rejeu.Timestamp Unix en secondes.
x-signatureAuthentifie la requete GET.HMAC SHA-256 hex du timestamp.

Payload

Aucun body requis.

Champs de reponse

ChampTypeValeurs possiblesRole
codestringmixx, moov_money, solimi_accountCode technique a envoyer dans provider si applicable.
namestringLibelle humainNom affichable.
providerstring/nullProvider mobile money ou nullOperateur associe.
is_activebooleantrue/falseDisponibilite du moyen.

Reponses possibles

HTTPCode applicatifCas
200-Liste retournee.
401authentication_failedSignature invalide.
403authorization_failedPartenaire non autorise.

Exemples d'appel

cURL
TIMESTAMP=$(date +%s)
SIGNATURE=$(printf "%s" "$TIMESTAMP" | openssl dgst -sha256 -hmac "$SOLIMI_API_SECRET" -hex | sed 's/^.* //')
curl -X GET "{{base_url}}/v1/payment-methods" \
  -H "x-api-key: $SOLIMI_API_KEY" \
  -H "x-timestamp: $TIMESTAMP" \
  -H "x-signature: $SIGNATURE"
PHP
<?php
$timestamp = (string) time();
$signature = hash_hmac("sha256", $timestamp, getenv("SOLIMI_API_SECRET"));
$opts = ["http" => ["header" => "x-api-key: ".getenv("SOLIMI_API_KEY")."\r\nx-timestamp: $timestamp\r\nx-signature: $signature\r\n"]];
echo file_get_contents("{{base_url}}/v1/payment-methods", false, stream_context_create($opts));
Node.js
import crypto from "node:crypto";

const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = crypto.createHmac("sha256", process.env.SOLIMI_API_SECRET).update(timestamp).digest("hex");
const response = await fetch("{{base_url}}/v1/payment-methods", {
  headers: {"x-api-key": process.env.SOLIMI_API_KEY, "x-timestamp": timestamp, "x-signature": signature}
});
console.log(await response.json());
Python
import hashlib, hmac, os, time, requests

timestamp = str(int(time.time()))
signature = hmac.new(os.environ["SOLIMI_API_SECRET"].encode(), timestamp.encode(), hashlib.sha256).hexdigest()
response = requests.get(
    "{{base_url}}/v1/payment-methods",
    headers={"x-api-key": os.environ["SOLIMI_API_KEY"], "x-timestamp": timestamp, "x-signature": signature},
)
print(response.json())

Exemple de reponse 200

[
  {
    "code": "mixx",
    "name": "Mixx by Yas",
    "provider": "mixx",
    "is_active": true
  },
  {
    "code": "moov_money",
    "name": "Moov Money",
    "provider": "moov_money",
    "is_active": true
  }
]
L'URL webhook du partenaire est configuree par l'equipe SOLIMI dans la plateforme interne. Il n'existe plus d'endpoint public permettant au partenaire de creer ou modifier lui-meme son webhook.

Collection Postman

La collection Postman SOLIMI regroupe les requetes pretes a tester pour les endpoints publics: creation de paiement, consultation de statut, solde du partenaire et moyens de paiement disponibles. Elle aide les equipes techniques a demarrer rapidement sans reconstruire les headers et payloads depuis zero.

Comment l'utiliser

  1. Telechargez le fichier JSON de collection.
  2. Dans Postman, cliquez sur Import, puis selectionnez le fichier telecharge.
  3. Renseignez les variables base_url, api_key, api_secret et les valeurs de test.
  4. Lancez les requetes de la section 03 - Payments pour valider l'integration.

Fichier disponible

Format JSON compatible avec Postman. Le fichier contient les scripts necessaires pour calculer les headers HMAC et ajouter automatiquement l'idempotency key sur les paiements.

Telecharger la collection Postman
La collection ne contient pas vos secrets. Les valeurs sensibles doivent etre renseignees dans vos variables d'environnement Postman et ne doivent pas etre partagees publiquement.

Webhooks

SOLIMI appelle votre endpoint webhook lorsqu'un paiement change d'etat. Votre serveur doit repondre avec un statut HTTP 2xx. En cas d'echec, SOLIMI relance selon les delais: 30s, 60s, 300s, 900s.

Header SOLIMI Description
x-solimi-signatureSecret webhook partage avec SOLIMI. Comparez cette valeur au secret configure.
x-solimi-timestampTimestamp Unix en secondes, utile pour refuser les notifications trop anciennes.
x-solimi-eventNom de l'evenement, par exemple payment.success.

Evenements

payment.initiated, payment.pending_approval, payment.success, payment.failed, payment.declined, payment.expired.

Verification webhook FastAPI

import time

from fastapi import APIRouter, Header, HTTPException, Request

router = APIRouter()

SOLIMI_WEBHOOK_SECRET = "secret_fourni_par_solimi"
SIGNATURE_TOLERANCE_SECONDS = 300


@router.post("/webhooks/solimi/payments")
async def solimi_payment_webhook(
    request: Request,
    x_solimi_signature: str = Header(...),
    x_solimi_timestamp: str = Header(...),
    x_solimi_event: str = Header(...),
):
    if x_solimi_signature != SOLIMI_WEBHOOK_SECRET:
        raise HTTPException(status_code=401, detail="Invalid webhook signature")

    try:
        timestamp = int(x_solimi_timestamp)
    except ValueError:
        raise HTTPException(status_code=400, detail="Invalid timestamp")

    if abs(int(time.time()) - timestamp) > SIGNATURE_TOLERANCE_SECONDS:
        raise HTTPException(status_code=400, detail="Expired webhook timestamp")

    payload = await request.json()
    payment = payload.get("payment", {})

    # Mettre a jour la commande/facture du partenaire ici.
    # Exemple: payment.success => commande payee.

    return {
        "received": True,
        "event": x_solimi_event,
        "merchant_reference": payment.get("merchant_reference"),
        "solimi_reference": payment.get("reference"),
        "status": payment.get("status"),
    }
La verification est volontairement simple: le header x-solimi-signature contient directement le secret webhook. Gardez ce secret cote serveur uniquement.

Erreurs

Les erreurs sont retournees au format JSON suivant.

{
  "code": "authentication_failed",
  "message": "Missing authentication headers",
  "details": null
}
HTTP Code Action recommandee
401authentication_failedVerifier les headers HMAC, le timestamp et la signature.
403authorization_failedVerifier l'IP autorisee, l'etat de la cle API et du partenaire.
404not_foundVerifier la reference de paiement ou la route appelee.
409idempotency_conflictReutiliser une meme cle uniquement pour la meme requete logique.
422validation_errorCorriger les champs invalides dans le payload.

Checklist de mise en production

  • Stocker la cle API et le secret API dans un coffre de secrets cote serveur.
  • Signer toutes les requetes avec le corps exact envoye a SOLIMI.
  • Utiliser une cle d'idempotence unique pour chaque paiement marchand.
  • Verifier les webhooks en comparant x-solimi-signature au secret webhook configure.
  • Prevoir le polling de statut en secours si un webhook est indisponible.
  • Fournir a SOLIMI les adresses IP publiques de vos serveurs.
  • Tester les cas succes, echec, refus, expiration et retry webhook en sandbox.