API Partenaire

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.

Espace partenaire : vos clés API, webhooks, transactions et soldes se gèrent sur partner.trustchange.fr. Pas encore de compte ? Écrivez à support@trustchange.fr.

Démarrage rapide

  1. 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.
  2. 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.
  3. Lancez un premier collect avec l'en-tête X-Api-Key : en mode test, la réponse de l'opérateur est simulée en quelques secondes et votre webhook est appelé.
  4. Quand tout fonctionne, créez une clé live (tc_live_…) : même API, vraies opérations.

URL de base et format

https://api.trustchange.fr

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 HTTPSignification
200 / 202Succès / demande acceptée (le résultat final arrive par webhook)
400Requête refusée (montant hors bornes, opérateur indisponible, solde insuffisant…) : voir message
401Clé API absente, invalide, révoquée ou IP non autorisée
404Transaction introuvable
409Ré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).
Le jeton obtenu par 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 0002Reste en attente (jamais confirmé, expire au bout de 7 jours)
tout autre numéroSuccè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).

POST /api/Integrator/quote X-Api-Key
{
  "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"
  }
}
Collect : 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.

POST /api/Integrator/collect X-Api-Key

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.

POST /api/Integrator/payout X-Api-Key

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

StatutSignification
PENDINGCréée, pas encore transmise à l'opérateur
PROCESSINGEn cours chez l'opérateur (ou en attente du dépôt crypto)
COMPLETEDTerminée avec succès (statut final)
FAILEDÉchouée ; un payout est intégralement remboursé (statut final)
EXPIREDCollect 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 409 sans rien créer ni envoyer, vous pouvez donc rejouer une requête sans risque de double paiement.
  • Une transaction se consulte par son transactionId ou 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êteContenu
X-TC-Eventtransaction.completed, transaction.failed, transaction.expired ou ping
X-TC-Event-IdIdentifiant stable de l'événement : ignorez un événement déjà traité
X-TC-PublicIdIdentifiant de la transaction
X-TC-Testtrue pour le mode test
X-TC-TimestampHorodatage Unix (secondes) de l'envoi
X-TC-SignatureHMAC-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 2xx en 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, to inclus).
  • GET /api/Integrator/statement/export et GET /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éthodeURLDescription
POST/api/Integrator/quoteDevis (frais, net, total)
POST/api/Integrator/collectEncaissement Mobile Money ou crypto
POST/api/Integrator/payoutEnvoi Mobile Money ou crypto
GET/api/Integrator/transaction/{id}Détail par transactionId ou référence externe
GET/api/Integrator/transactionsListe (?page=1&pageSize=25&type=COLLECT&status=COMPLETED&externalReference=…)
POST/api/Integrator/transaction/{id}/callback/resendRenvoyer le webhook d'une transaction terminée
GET/api/Integrator/transaction/{id}/webhooksHistorique des envois de son webhook
GET/api/Integrator/webhooks/deliveriesDerniers envois de webhooks (?failedOnly=true)
POST/api/Integrator/webhook/testEnvoyer un événement ping à votre URL par défaut
GET/api/Integrator/balanceSoldes de vos comptes (du mode de la clé)
GET/api/Integrator/operatorsOpérateurs Mobile Money : code, pays, devise, bornes, format du numéro
GET/api/Integrator/cryptosCryptos et réseaux disponibles, bornes
GET/api/Integrator/transactions/searchRecherche (?from=&to=&q=&type=&status=&paymentMethod=&page=) avec total
GET/api/Integrator/transactions/exportExport CSV des transactions (mêmes filtres)
GET/api/Integrator/statementRelevé du compte sur une période (?from=&to=&page=)
GET/api/Integrator/statement/exportRelevé au format CSV
GET/api/Integrator/withdrawalsVos reversements
POST/api/Integrator/withdrawalsDemander un reversement (amount, method, destination, destinationName, paymentCode | bankName)
POST/api/Integrator/withdrawals/{id}/cancelAnnuler 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.