Ir al contenido

Marketplace y Connect

La API Connect permite a una plataforma (marketplace, plaza de servicios, SaaS multivendedor…) crear una cuenta de Sangho por cada vendedor y repartir automáticamente cada pago entre la plataforma y ese vendedor. Sangho sigue siendo el único depositario de los fondos y el único responsable del KYC: la plataforma no recopila ni almacena ningún documento de identidad.

Attention

Connect está reservado a las Apps con el estado de Socio de Plataforma, concedido manualmente por Sangho tras una solicitud realizada desde su panel. Una clave secreta válida no basta: una App de comerciante ordinaria recibe 403 PLATFORM_PARTNER_REQUIRED en todas las rutas siguientes. Véase Códigos de error — Autorización.

1. Crear una cuenta de vendedor

La creación es idempotente por external_id (el identificador del vendedor en su sistema): repetir la misma creación devuelve la misma cuenta. Un claim_token solo se devuelve en la creación inicial: transmítaselo al vendedor (enlace de reclamación de Sangho), sin almacenarlo ni registrarlo en logs. Si se pierde o caduca, emita otro (el anterior queda invalidado).

2. KYC alojado por Sangho

Una vez que el vendedor ha reclamado la cuenta, abra una sesión de incorporación alojada (kyc-session) y redirija al vendedor a su url (válida durante aproximadamente una hora). La cuenta pasa a active y charges_enabled/payouts_enabled una vez validado el KYC por parte de Sangho, sin ninguna acción adicional de la plataforma.

EstadoSignificado
pending_claimCuenta creada, a la espera de que el vendedor haga clic en su enlace de reclamación
linkedReclamada por el vendedor, KYC aún sin completar
activeKYC validado: puede cobrar y retirar
restrictedCobros/retiradas suspendidos (revisión de Sangho en curso)
disabledCuenta desactivada

3. Repartir un pago (bloque connect)

Añada un bloque connect al crear una Checkout Session normal: no hay un endpoint distinto para crear un pago de Connect, nace con la sesión.

CampoDescripción
accountCuenta beneficiaria (acct_xxx), vinculada y con charges_enabled
modeescrow (fondos bloqueados hasta el release) o instant (abonados al cobrar) — por defecto escrow
commissionComisión de la plataforma, retenida en la liberación (escrow) o en el cobro (instant)
reserve_rateParte (0–1) de los gastos de envío que se destina a la reserva de garantía
external_referenceReferencia de su pedido, consultable, devuelta en connect_payment

La respuesta de la sesión incluye connect_payment (id cpay_xxx): los gastos de envío (shipping_amount) están disponibles para el vendedor desde el cobro; el resto queda bloqueado en held hasta la liberación (modo escrow).

4. Liberar, reembolsar, congelar

AcciónEfectoIdempotency Key
releaseLibera los fondos bloqueados hacia el saldo disponible del vendedor (retiene la comisión)Obligatoria
refundReembolsa todo o parte, antes o después de la liberaciónObligatoria
freeze / unfreezeBloquea/desbloquea un pago en caso de disputa — ya son idempotentes en el servidorOpcional
Note

release y refund exigen una Idempotency Key estable (p. ej. release-{order_id}): una repetición nunca debe duplicar la operación financiera.

5. Saldo y retiradas

balance devuelve los buckets available/held/frozen/reserve (importes en cadenas decimales: conviértalos con una biblioteca decimal, nunca use parseFloat para comparar). payouts.create activa una retirada hacia el destino del vendedor.

6. Flujo de eventos duradero (recuperación tras una caída)

Los webhooks son solo una notificación de mejor esfuerzo (best-effort): tras una interrupción (plataforma fuera de línea, entrega perdida), vuelva a leer GET /v1/events/ desde su último cursor para recuperar exactamente lo que se perdió, sin perder ni duplicar nada. Cada evento emitido hacia sus webhooks también se registra ahí de forma duradera, aunque no haya ningún webhook activo o la entrega haya fallado.

ParámetroDescripción
sinceCursor opaco recibido en next_cursor de una llamada anterior — ausente en la primera llamada
limitNúmero máximo de eventos que se devuelven (valor por defecto razonable, con límite superior)

La respuesta incluye data (lista de envoltorios, con el mismo formato que los webhooks), next_cursor (que debe devolver tal cual en la siguiente llamada; repetir un cursor sin nuevos eventos no entraña ningún riesgo) y has_more. Los eventos se conservan según la ventana de retención configurada en Sangho; pasada esa ventana, ya no son accesibles mediante este flujo.

7. Tipos de retirada disponibles

GET /v1/connect/payout-kinds/ devuelve los tipos de destino de retirada que ofrece Sangho (Airtel Money, Moov Money, tarjeta bancaria tokenizada…) y su disponibilidad actual. Utilícelo para construir dinámicamente el formulario del destino de retirada en el lado del vendedor en lugar de escribir la lista a mano.

Disponibilidad por SDK

Connect está disponible en los SDK de Node.js, Python y PHP.

Flujo completo

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.
  }
}