Jèko
Service Providers

Escrow (séquestre opérationnel)

Bloquer un encaissement Partner jusqu'à libération par la clé plateforme du Service Provider

Produit Service Provider

L'escrow n'est pas un encaissement instantané. Seule la clé plateforme (clé API marchand émise par le Service Provider) peut créer un pot, le lier à un collect, et plus tard le libérer ou le rembourser. Le marchand ne peut pas se débloquer lui-même.

crée uniquement un pot en attente. L'encaissement reste sur les endpoints existants (payment_requests / payment_links) via escrowId. Ce n'est pas un séquestre réglementé : Jèko retient le net sur un portefeuille escrow du magasin, invisible dans le solde et dans .

Clés

CléEncaissement instantané/escrows et escrowId
Clé plateforme (émise par le SP pour ce marchand)OuiOui (si le flag est activé)
Clé Owner / Dashboard du marchandOui403
Clé entreprise du SP (/service_providers/*)Non (pas d'argent)403

La clé plateforme est scoped au marchand. Elle ne peut pas toucher les escrows d'un autre marchand (404).

Flux

POST /partner_api/escrows                 { storeId, holdUntil? }  → pending
POST /partner_api/payment_requests        corps habituel + escrowId
  ou POST /partner_api/payment_links      corps habituel + escrowId
  → le client paie (redirect / in-app / soundbox / lien)
  → escrow held ; GET /transactions reste vide pour ce job
GET  /partner_api/escrows/{id}            lifecycle (pending → held)

Sans escrowId, le collect crédite tout de suite le solde opérable — comportement inchangé.

1. Créer le pot

Create escrow (Partner API)
curl -X POST "https://api.jeko.africa/partner_api/escrows" \
  -H "X-API-KEY: platform_key" \
  -H "X-API-KEY-ID: platform_key_id" \
  -H "Content-Type: application/json" \
  -d '{
    "storeId": "59ae202a-f583-4a15-970f-9e99bd1e0baa"
  }'

Corps : uniquement storeId et, optionnellement, holdUntil (ISO 8601 UTC). Pas de paymentDetails, successUrl, deviceId, forceProviderDirect, ni titre de lien.

  • holdUntil omis → expiration à 7 jours.
  • Doit être dans le futur, au plus 30 jours.
  • Un pot = un seul collect. Relier deux fois le même escrowId409.

Réponse (pending) :

{
  "id": "7c2d1a90-0b1e-4c3a-9f11-2e8c4d6a1b20",
  "storeId": "59ae202a-f583-4a15-970f-9e99bd1e0baa",
  "status": "pending",
  "holdUntil": "2026-09-14T20:00:00.000Z",
  "amount": null,
  "paymentRequestId": null,
  "paymentLinkId": null,
  "createdAt": "2026-09-07T20:00:00.000Z"
}

2. Lier le collect existant

Ajoutez escrowId au corps habituel de Paiement en ligne ou de Liens de paiement.

curl -X POST "https://api.jeko.africa/partner_api/payment_requests" \
  -H "X-API-KEY: platform_key" \
  -H "X-API-KEY-ID: platform_key_id" \
  -H "Content-Type: application/json" \
  -d '{
    "storeId": "59ae202a-f583-4a15-970f-9e99bd1e0baa",
    "amountCents": 1000000,
    "currency": "XOF",
    "reference": "ORDER-1042",
    "escrowId": "7c2d1a90-0b1e-4c3a-9f11-2e8c4d6a1b20",
    "paymentDetails": {
      "type": "redirect",
      "data": {
        "paymentMethod": "wave",
        "successUrl": "https://example.com/success",
        "errorUrl": "https://example.com/error"
      }
    }
  }'

Règles au bind :

  • Même storeId que le pot, pot encore pending, flag escrow activé, clé plateforme.
  • Rails v1 : Wave, Orange, Djamo. Autre moyen → 400.
  • allowMultiplePayments: true + escrowId400.
  • Clé Owner / flag off / clé SP entreprise → 403.
  • Pot introuvable ou autre marchand → 404.

Le client paie comme aujourd'hui (redirect, soundbox, lien). Poller ou reste valide.

3. Après le paiement (held)

  • : status: "held", amount renseigné, paymentRequestId (et paymentLinkId si lien).
  • : escrowId présent, pas de transaction — le hold n'est pas dépensable.
  • : vide pour ce job. Le solde magasin () ne change pas.
  • Webhook ESCROW_HELD, pas TRANSACTION_COMPLETED. Ne créditez pas le marchand comme si le paiement était dépensable.

Exemple ESCROW_HELD (enveloppe, walletAvailableBalance = solde opérable) :

{
  "event": "ESCROW_HELD",
  "escrowId": "7c2d1a90-0b1e-4c3a-9f11-2e8c4d6a1b20",
  "storeId": "59ae202a-f583-4a15-970f-9e99bd1e0baa",
  "status": "held",
  "amount": { "amount": 985000, "currency": "XOF" },
  "paymentRequestId": "d22c81f3-ee04-4ec5-8bd2-cd8af5dabcfc",
  "paymentLinkId": null,
  "businessName": "Boutique Example",
  "storeName": "Cocody",
  "walletAvailableBalance": { "amount": 0, "currency": "XOF" }
}

Un abonnement events: ["TRANSACTION_COMPLETED"] ne reçoit pas ESCROW_HELD. events: null (défaut) le reçoit. Parsez event avant de traiter le corps comme une transaction.

/escrows vs /transactions

SurfaceRôle
Lifecycle du hold (pendingheld → plus tard released / refunded / expired)
Portefeuille opérable seulement. Instantané, transferts, retraits. Rien pendant le hold.
Disponible opérable seulement

Erreurs fréquentes

CodeQuand
400holdUntil invalide ; rail non supporté ; lien multi-paiements + escrowId
403Clé Owner / Dashboard, clé entreprise SP, ou flag escrow inactif
404Magasin ou escrow introuvable, ou autre marchand
409L'escrow est déjà lié à un collect

La libération () et le remboursement / timeout arrivent dans les livraisons suivantes. D'ici là, un hold reste held jusqu'à expiration configurée côté Jèko.

On this page