Aller au contenu

Marketplace & Connect

L’API Connect permet à une plateforme (marketplace, place de services, SaaS multi-vendeurs…) de créer un compte Sangho par vendeur et de répartir automatiquement chaque paiement entre la plateforme et ce vendeur. Sangho reste seul dépositaire des fonds et seul responsable du KYC — la plateforme ne collecte ni ne stocke aucune pièce d’identité.

Attention

Connect est réservé aux Apps ayant le statut Partenaire Plateforme, accordé manuellement par Sangho après une demande faite depuis votre dashboard. Une clé secrète valide ne suffit pas : une App marchande ordinaire reçoit 403 PLATFORM_PARTNER_REQUIRED sur toutes les routes ci-dessous. Voir Codes d’erreur — Autorisation.

1. Créer un compte vendeur

La création est idempotente par external_id (l’identifiant du vendeur chez vous) : rappeler la même création renvoie le même compte. Un claim_token n’est renvoyé qu’à la création initiale — transmettez-le au vendeur (lien de réclamation Sangho), sans le stocker ni le journaliser. S’il est perdu ou expiré, réémettez-en un (l’ancien est invalidé).

2. KYC hébergé par Sangho

Une fois le compte réclamé par le vendeur, ouvrez une session d’onboarding hébergée (kyc-session) et redirigez-le vers son url (valable environ une heure). Le compte passe à active et charges_enabled/payouts_enabled une fois le KYC validé côté Sangho — aucune action supplémentaire de la plateforme.

StatutSignification
pending_claimCompte créé, en attente que le vendeur clique son lien de réclamation
linkedRéclamé par le vendeur, KYC pas encore terminé
activeKYC validé — peut encaisser et retirer
restrictedEncaissements/retraits coupés (revue Sangho en cours)
disabledCompte désactivé

3. Répartir un paiement (bloc connect)

Ajoutez un bloc connect à la création d’une Checkout Session classique — pas d’endpoint séparé pour créer un paiement Connect, il naît avec la session.

ChampDescription
accountCompte bénéficiaire (acct_xxx), lié et charges_enabled
modeescrow (fonds bloqués jusqu'à release) ou instant (versés à l'encaissement) — défaut escrow
commissionCommission de la plateforme, retenue à la libération (escrow) ou à l'encaissement (instant)
reserve_ratePart (0–1) des frais de livraison mise en réserve de garantie
external_referenceRéférence de votre commande, recherchable, renvoyée dans connect_payment

La réponse de la session porte connect_payment (id cpay_xxx) : les frais de livraison (shipping_amount) sont disponibles pour le vendeur dès l’encaissement, le reste est bloqué en held jusqu’à la libération (mode escrow).

4. Libérer, rembourser, geler

ActionEffetIdempotency Key
releaseLibère les fonds bloqués vers le disponible du vendeur (retient la commission)Obligatoire
refundRembourse tout ou partie, avant ou après libérationObligatoire
freeze / unfreezeBloque/débloque un paiement en cas de litige — déjà idempotents côté serveurFacultative
Note

release et refund exigent une Idempotency Key stable (ex. release-{order_id}) : un rejeu ne doit jamais dupliquer l’opération financière.

5. Solde et retraits

balance renvoie les buckets available/held/frozen/reserve (montants en chaînes décimales — convertir avec une bibliothèque décimale, jamais parseFloat pour comparer). payouts.create déclenche un retrait vers la destination du vendeur.

6. Flux d’événements durable (reprise après panne)

Les webhooks ne sont qu’une notification best-effort : après une coupure (plateforme hors-ligne, livraison manquée), relisez GET /v1/events/ depuis votre dernier curseur pour rattraper exactement ce qui a été manqué, sans rien perdre ni dupliquer. Chaque événement émis vers vos webhooks y est aussi enregistré durablement, même si aucun webhook n’est actif ou si la livraison a échoué.

ParamètreDescription
sinceCurseur opaque reçu dans next_cursor d'un appel précédent — absent au premier appel
limitNombre maximum d'événements à renvoyer (défaut raisonnable, plafonné)

La réponse porte data (liste d’enveloppes, même format que les webhooks), next_cursor (à renvoyer tel quel à l’appel suivant — un curseur rejoué sans nouvel événement est sans risque) et has_more. Les événements sont conservés selon la fenêtre de rétention configurée côté Sangho, au-delà ils ne sont plus accessibles par ce flux.

7. Types de retrait disponibles

GET /v1/connect/payout-kinds/ renvoie les types de destination de retrait proposés par Sangho (Airtel Money, Moov Money, carte bancaire tokenisée…) et leur disponibilité courante — à utiliser pour construire dynamiquement le formulaire de destination de retrait côté vendeur plutôt que de coder la liste en dur.

Disponibilité par SDK

Connect est disponible dans les SDK Node.js, Python et PHP.

Flux complet

javascript
import Sangho, { SanghoPlatformPartnerRequiredError } from '@sanghosdk/js';
const sangho = new Sangho(process.env.SANGHO_SECRET_KEY);


try {
  // 1. Créer le compte vendeur (idempotent par external_id)
  const account = await sangho.connect.accounts.create(
    { external_id: 'seller-42', email: 'ada@example.com', business_name: 'Boutique Ada' },
    { idempotencyKey: 'connect-account-seller-42' }
  );
  // account.claim_token -> à envoyer au vendeur par e-mail, jamais stocké ni journalisé


  // 2. Une fois réclamé par le vendeur : KYC hébergé
  const session = await sangho.connect.accounts.createKycSession(account.id, {
    return_url: 'https://maplateforme.com/vendeurs/kyc/retour',
  });
  // rediriger le vendeur vers session.url


  // 3. Paiement avec répartition (dans une Checkout Session classique)
  const checkout = await sangho.checkoutSessions.create({
    line_items: [{ price: 'price_xxx', quantity: 1 }],
    connect: {
      account: account.id,
      mode: 'escrow',
      commission: 500,
      reserve_rate: 0.1,
      external_reference: 'order-1042',
    },
  });


  // 4. Après livraison confirmée : libérer les fonds au vendeur
  await sangho.connect.payments.release(checkout.connect_payment, {
    idempotencyKey: 'release-order-1042',
  });
} catch (err) {
  if (err instanceof SanghoPlatformPartnerRequiredError) {
    // Cette App n'a pas (encore) le statut Partenaire Plateforme.
  }
}