Documentation Intégrateur
Encaissez (collect) et envoyez (payout) de l'argent par Mobile Money ou en crypto depuis vos applications, via une API REST JSON, avec un mode test complet et des webhooks signés.
Démarrage rapide
- Dans l'espace partenaire, page Clés API : créez une clé test (
tc_test_…). Copiez-la : elle n'est affichée qu'une fois. - Page Développeurs : enregistrez l'URL de votre webhook et cliquez « Envoyer un événement test » pour vérifier la réception et la signature.
- Lancez un premier
collectavec l'en-têteX-Api-Key: en mode test, la réponse de l'opérateur est simulée en quelques secondes et votre webhook est appelé. - Quand tout fonctionne, créez une clé live (
tc_live_…) : même API, vraies opérations.
URL de base et format
Tous les endpoints sont préfixés par /api/Integrator. Les réponses ont toujours la même enveloppe :
{
"data": { ... },
"message": "Message lisible (à afficher ou journaliser)",
"statut": "success" | "error",
"statusCode": 200 | 400 | 401 | 404 | 409 | 500
}
| Code HTTP | Signification |
|---|---|
200 / 202 | Succès / demande acceptée (le résultat final arrive par webhook) |
400 | Requête refusée (montant hors bornes, opérateur indisponible, solde insuffisant…) : voir message |
401 | Clé API absente, invalide, révoquée ou IP non autorisée |
404 | Transaction introuvable |
409 | Référence externe déjà utilisée : rien n'a été créé ni envoyé |
1. Authentification
Chaque appel serveur à serveur porte votre clé API dans l'en-tête X-Api-Key :
X-Api-Key: tc_test_ab12cd34ef_9f8e7d6c5b4a39281706f5e4d3c2b1a0918273645f6e7d8c
tc_test_…: mode test (compte fictif, opérations simulées).tc_live_…: mode live (vrais paiements).- Une clé peut être limitée à des adresses IP ; elle se révoque à tout moment depuis l'espace partenaire (effet en moins d'une minute).
- Conservez vos clés côté serveur uniquement (jamais dans une application mobile ou un site web).
POST /api/Integrator/login (e-mail + mot de passe) est réservé à l'espace partenaire.
Pour vos serveurs, utilisez toujours une clé API.
2. Mode test
Avec une clé tc_test_…, vous disposez d'un compte test de 10 000 000 FCFA (rechargeable depuis l'espace partenaire).
Aucun opérateur ni aucune blockchain n'est appelé ; les frais affichés sont les vrais frais. Les webhooks sont réellement
envoyés à votre serveur, avec "test": true et l'en-tête X-TC-Test: true.
| Numéro de téléphone (Mobile Money) | Résultat simulé |
|---|---|
se termine par 0001 | Échec (collect refusé, payout non abouti et remboursé) |
se termine par 0002 | Reste en attente (jamais confirmé, expire au bout de 7 jours) |
| tout autre numéro | Succès environ 5 secondes après la demande |
Crypto : un collect reçoit un dépôt simulé du montant attendu après 15 secondes ; un payout est envoyé de façon fictive.
3. Devis
Calcule frais, net et total avant de lancer une opération (mêmes règles que l'exécution).
{
"type": "PAYOUT", // COLLECT | PAYOUT
"paymentMethod": "MOBILE_MONEY", // MOBILE_MONEY | CRYPTO
"paymentCode": "OM_CM",
"amount": 25000
}
Réponse (200)
{
"data": {
"type": "PAYOUT", "paymentMethod": "MOBILE_MONEY",
"amount": 25000, "fees": 375, "netAmount": 25000, "total": 25375,
"currencyCode": "XAF", "sufficientBalance": true,
"quotedAt": "2026-10-01T10:00:00Z"
}
}
netAmount = ce qui sera crédité sur votre compte, total = ce que paie le client.
Payout : netAmount = ce que reçoit le bénéficiaire, total = ce qui sera débité de votre compte.
Pour la crypto, montants indicatifs au cours actuel.
4. Collect (encaissement)
Demande un paiement à un client ; le montant net est crédité sur votre compte à la confirmation.
Mobile Money
{
"paymentMethod": "MOBILE_MONEY",
"paymentCode": "OM_CM", // voir GET /operators
"phoneNumber": "699000000", // numéro national, sans indicatif
"amount": 5000, // entier, dans la devise de l'opérateur
"externalReference": "order-42", // votre référence, unique
"callbackUrl": "https://monapp.com/webhooks/trustchange", // facultatif si URL par défaut
"metadata": "{\"userId\":\"usr_123\"}" // texte libre (JSON conseillé), renvoyé dans le webhook
}
Le client paie amount et valide sur son téléphone ; vous recevez amount − fees.
Crypto
{
"paymentMethod": "CRYPTO",
"cryptoSymbol": "USDT",
"network": "TRC20",
"amount": 25, // montant attendu EN CRYPTO
"externalReference": "order-43"
}
La réponse contient une depositAddress dédiée, valable 24 heures. À la réception des fonds, votre compte (FCFA)
est crédité de la contre-valeur réelle de ce qui est arrivé, au cours du moment, frais déduits.
Réponse (202)
{
"data": {
"transactionId": "TC-INT-7K2M9QXA",
"status": "PROCESSING",
"phoneNumber": "699000000",
"depositAddress": null, // crypto : adresse où envoyer les fonds
"amount": 5000,
"fees": 75,
"netAmount": 4925,
"currencyCode": "XAF",
"amountCrypto": null, // crypto : montant attendu
"expiresAt": null, // crypto : fin de surveillance de l'adresse
"externalReference": "order-42"
}
}
5. Payout (décaissement)
Envoie de l'argent depuis votre compte. Le montant et les frais sont débités immédiatement (uniquement si le solde les couvre), puis l'envoi est traité ; le résultat final arrive par webhook. En cas d'échec, montant et frais sont recrédités.
Mobile Money
{
"paymentMethod": "MOBILE_MONEY",
"paymentCode": "MTN_CM",
"phoneNumber": "670000000",
"amount": 2000, // reçu par le bénéficiaire
"externalReference": "payout-12" // fortement recommandé : protège des doubles envois
}
Crypto
{
"paymentMethod": "CRYPTO",
"cryptoSymbol": "USDT",
"network": "TRC20",
"cryptoAddress": "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"amount": 10, // montant à envoyer EN CRYPTO
"externalReference": "payout-13"
}
Crypto : votre compte est débité de la contre-valeur au cours actuel (amount) et des frais réseau (fees).
Réponse (202)
{
"data": {
"transactionId": "TC-INT-P4R8WZ2C",
"status": "PENDING",
"amount": 2000,
"fees": 30,
"netAmount": 2000,
"currencyCode": "XAF",
"amountCrypto": null,
"externalReference": "payout-12"
}
}
6. Statuts et références
| Statut | Signification |
|---|---|
PENDING | Créée, pas encore transmise à l'opérateur |
PROCESSING | En cours chez l'opérateur (ou en attente du dépôt crypto) |
COMPLETED | Terminée avec succès (statut final) |
FAILED | Échouée ; un payout est intégralement remboursé (statut final) |
EXPIRED | Collect jamais payé : 24 h pour la crypto, 7 jours pour le Mobile Money (statut final) |
- Référence externe : unique pour votre compte. Une deuxième requête avec la même référence renvoie
409sans rien créer ni envoyer, vous pouvez donc rejouer une requête sans risque de double paiement. - Une transaction se consulte par son
transactionIdou par votre référence externe :GET /api/Integrator/transaction/order-42.
7. Webhooks
À chaque statut final, TrustChange envoie un POST JSON vers la callbackUrl de la transaction
(ou votre URL par défaut). URL en https, sur un serveur public.
Corps
{
"event": "transaction.completed", // .completed | .failed | .expired
"id": "TC-INT-7K2M9QXA",
"test": false,
"type": "COLLECT", // COLLECT | PAYOUT
"status": "COMPLETED",
"amount": 5000,
"fees": 75,
"net_amount": 4925,
"currency": "XAF",
"payment_method": "MOBILE_MONEY",
"amount_crypto": null,
"crypto_symbol": null,
"network": null,
"external_reference": "order-42",
"blockchain_tx_id": null,
"failure_reason": null,
"created_at": "2026-10-01T10:00:00Z",
"completed_at": "2026-10-01T10:00:42Z",
"metadata": "{\"userId\":\"usr_123\"}"
}
En-têtes
| En-tête | Contenu |
|---|---|
X-TC-Event | transaction.completed, transaction.failed, transaction.expired ou ping |
X-TC-Event-Id | Identifiant stable de l'événement : ignorez un événement déjà traité |
X-TC-PublicId | Identifiant de la transaction |
X-TC-Test | true pour le mode test |
X-TC-Timestamp | Horodatage Unix (secondes) de l'envoi |
X-TC-Signature | HMAC-SHA256 hexadécimal de timestamp + "." + corps brut, avec votre secret |
Vérifier la signature
Utilisez le corps brut reçu (avant toute désérialisation) et refusez un horodatage de plus de 5 minutes.
// C#
var expected = Convert.ToHexString(
new HMACSHA256(Encoding.UTF8.GetBytes(secret))
.ComputeHash(Encoding.UTF8.GetBytes($"{timestamp}.{rawBody}"))).ToLowerInvariant();
var valid = CryptographicOperations.FixedTimeEquals(
Encoding.UTF8.GetBytes(expected), Encoding.UTF8.GetBytes(signatureHeader));
// Node.js
const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
const valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));
# Python
expected = hmac.new(secret.encode(), f"{timestamp}.{raw_body}".encode(), hashlib.sha256).hexdigest()
valid = hmac.compare_digest(expected, signature_header)
Accusé de réception et nouvelles tentatives
- Répondez en
2xxen moins de 10 secondes (traitez le reste de façon asynchrone). - Sinon, nouvelles tentatives après 1 min, 5 min, 30 min, 2 h, 6 h et 12 h (environ 21 h au total).
- Chaque envoi est visible dans l'espace partenaire (code HTTP, réponse de votre serveur, durée) ; vous pouvez renvoyer un webhook depuis le détail d'une transaction ou par l'API.
- Les redirections ne sont pas suivies.
8. Relevé, rapprochement et reversements
Chaque mouvement de votre solde (encaissement, payout, remboursement d'un payout échoué, reversement…) est inscrit au relevé avec le solde après opération : vous pouvez rapprocher votre comptabilité ligne à ligne.
GET /api/Integrator/statement?from=2026-10-01&to=2026-10-31: solde d'ouverture, crédits, débits, solde de clôture et mouvements paginés (dates à l'heure de Douala,toinclus).GET /api/Integrator/statement/exportetGET /api/Integrator/transactions/export: mêmes filtres, fichier CSV (séparateur;, UTF-8).GET /api/Integrator/transactions/search: recherche par période, type, statut, moyen et texte libre, avec le nombre total et les totaux des transactions réussies.
Pour récupérer votre solde, demandez un reversement vers votre Mobile Money ou votre compte bancaire depuis
l'espace partenaire (ou POST /api/Integrator/withdrawals). Le montant est réservé immédiatement, annulable tant que
TrustChange ne l'a pas traité, et vous recevez la référence du virement par e-mail. En mode test, il est validé immédiatement.
9. Tous les endpoints
| Méthode | URL | Description |
|---|---|---|
| POST | /api/Integrator/quote | Devis (frais, net, total) |
| POST | /api/Integrator/collect | Encaissement Mobile Money ou crypto |
| POST | /api/Integrator/payout | Envoi Mobile Money ou crypto |
| GET | /api/Integrator/transaction/{id} | Détail par transactionId ou référence externe |
| GET | /api/Integrator/transactions | Liste (?page=1&pageSize=25&type=COLLECT&status=COMPLETED&externalReference=…) |
| POST | /api/Integrator/transaction/{id}/callback/resend | Renvoyer le webhook d'une transaction terminée |
| GET | /api/Integrator/transaction/{id}/webhooks | Historique des envois de son webhook |
| GET | /api/Integrator/webhooks/deliveries | Derniers envois de webhooks (?failedOnly=true) |
| POST | /api/Integrator/webhook/test | Envoyer un événement ping à votre URL par défaut |
| GET | /api/Integrator/balance | Soldes de vos comptes (du mode de la clé) |
| GET | /api/Integrator/operators | Opérateurs Mobile Money : code, pays, devise, bornes, format du numéro |
| GET | /api/Integrator/cryptos | Cryptos et réseaux disponibles, bornes |
| GET | /api/Integrator/transactions/search | Recherche (?from=&to=&q=&type=&status=&paymentMethod=&page=) avec total |
| GET | /api/Integrator/transactions/export | Export CSV des transactions (mêmes filtres) |
| GET | /api/Integrator/statement | Relevé du compte sur une période (?from=&to=&page=) |
| GET | /api/Integrator/statement/export | Relevé au format CSV |
| GET | /api/Integrator/withdrawals | Vos reversements |
| POST | /api/Integrator/withdrawals | Demander un reversement (amount, method, destination, destinationName, paymentCode | bankName) |
| POST | /api/Integrator/withdrawals/{id}/cancel | Annuler un reversement en attente (montant recrédité) |
Support
Pour toute question technique ou pour ouvrir un compte marchand :
support@trustchange.fr.
Indiquez toujours le transactionId ou votre référence externe.