Intégrez les paiements Mobile Money (Airtel & Moov) avec Kadryza. Créer un compte →
Référence APIPayment Sessions

Payment Sessions

Une payment session assigne un numéro Mobile Money Kadryza vers lequel votre client envoie l’argent. La confirmation est asynchrone : Kadryza reçoit le SMS de crédit, le rapproche de la session, puis la confirme de façon sûre. Écoutez les webhooks payment_session.* ou interrogez GET /v1/payment-sessions/:id.

Tous les endpoints utilisent l’authentification publique :

X-API-Key: <cle_api_kadryza>

L’environnement est déduit de la clé (kadryza_test_... → session test, kadryza_live_... → session live). Ne passez jamais merchant_id, is_test ou environment dans le body — ils sont imposés par la clé.

assigned_collection_number est le numéro à afficher à votre client : c’est là qu’il doit envoyer le paiement.

Créer une payment session

POST/v1/payment-sessions

Payload :

ChampTypeRequisDescription
referencestringOuiVotre identifiant de commande (merchant_order_id), unique par environnement
amountintegerOuiMontant entier en XAF (> 0)
currencystringOuiXAF
operatorstringOuiAIRTEL ou MOOV
customer_phonestringNonTéléphone du payeur
descriptionstringNonDescription courte
metadataobjectNonDonnées arbitraires, stockées mais non renvoyées dans les réponses (voir note)
ttl_minutesintegerNonDurée de vie 1–60 (défaut 10)

reference est votre identifiant de commande (merchant_order_id) : utilisez-le pour rapprocher la session de votre commande. metadata est stockée côté Kadryza mais n’est pas exposée dans les réponses publiques ni les webhooks — ne comptez pas la relire via l’API.

curl -X POST https://api.kadryza.app/v1/payment-sessions \
  -H "X-API-Key: $KADRYZA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reference": "order_2026_001",
    "amount": 5000,
    "currency": "XAF",
    "operator": "AIRTEL"
  }'

Réponse 201 Created :

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "reference": "order_2026_001",
  "ticket": "KDRZ-8F3K2",
  "amount": 5000,
  "currency": "XAF",
  "operator": "AIRTEL",
  "status": "AWAITING_PAYMENT",
  "environment": "live",
  "assigned_collection_number": "074000001",
  "expires_at": "2026-06-05T12:40:00Z",
  "created_at": "2026-06-05T12:30:00Z",
  "instructions": "Envoyez 5000 XAF vers le numéro 074000001 (AIRTEL), puis conservez la référence KDRZ-8F3K2.",
  "checkout_url": "https://dashboard.kadryza.app/pay/payment-sessions/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

checkout_url est l’URL de la page checkout hébergée par Kadryza pour cette session. Elle est optionnelle : utilisez-la comme fallback ou cible de redirection si vous ne voulez pas construire votre propre écran. Les champs POST, GET et cancel renvoient tous le même DTO, donc checkout_url y figure. C’est un lien de commodité (pas un secret).

Erreurs : 400 (paramètres invalides / ttl_minutes hors 1–60), 409 (reference déjà utilisée pour cet environnement), 503 (aucun numéro de collecte disponible ou rail live non prêt).

⚠️

Si une clé live déclenche PROVIDER_RAIL_NOT_READY, ne l’affichez pas comme une erreur technique brute. Expliquez que le rail live n’est pas encore prêt pour l’opérateur demandé, que le mode Test reste disponible, et que l’activation live dépend de la validation opérationnelle Kadryza. La réponse inclut failed_checks pour aider votre équipe à diagnostiquer le rail concerné.

Exemple 503 Service Unavailable :

{
  "error": "payment provider rail is not ready for live payment sessions",
  "code": "PROVIDER_RAIL_NOT_READY",
  "operator": "AIRTEL",
  "environment": "live",
  "failed_checks": [
    {
      "name": "gateway_connected",
      "ready": false,
      "reason": "no matching gateway connected to hub",
      "count": 0
    }
  ]
}

Récupérer une payment session

GET/v1/payment-sessions/:id

Retourne la vue côté marchand. La session est filtrée par votre compte et votre environnement : une session d’un autre marchand ou d’un autre environnement renvoie 404.

curl https://api.kadryza.app/v1/payment-sessions/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "X-API-Key: $KADRYZA_API_KEY"

Annuler une payment session

POST/v1/payment-sessions/:id/cancel

Autorisé uniquement tant que status = AWAITING_PAYMENT. Une session déjà SUCCESS, UNDER_REVIEW, EXPIRED, FAILED ou CANCELLED renvoie 409.

⚠️

Un paiement qui arriverait après l’annulation n’est jamais confirmé automatiquement.

curl -X POST https://api.kadryza.app/v1/payment-sessions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/cancel \
  -H "X-API-Key: $KADRYZA_API_KEY"

SDK Node / TypeScript

import Kadryza from '@kadryza/sdk'
 
const kadryza = new Kadryza({ apiKey: process.env.KADRYZA_API_KEY! })
 
// Créer
const session = await kadryza.paymentSessions.create({
  reference: 'order_2026_001',
  amount: 5000,
  currency: 'XAF',
  operator: 'AIRTEL',
  ttl_minutes: 15,
})
// Affichez session.assigned_collection_number à votre client.
 
// Récupérer
const fresh = await kadryza.paymentSessions.retrieve(session.id)
 
// Annuler (si AWAITING_PAYMENT)
const cancelled = await kadryza.paymentSessions.cancel(session.id)

Custom Checkout (votre propre UI)

Vous pouvez garder votre propre interface et ne pas afficher la page hébergée. Dans ce mode, affichez vous-même les champs de la réponse :

  • amount + currency, operator ;
  • assigned_collection_number — le numéro Mobile Money vers lequel le client paie ;
  • ticket (référence Kadryza), expires_at (compte à rebours), status.

Kadryza reste le moteur de paiement derrière votre UI : réception du SMS de crédit, rapprochement et confirmation sûre côté serveur. Vous n’avez rien à confirmer manuellement.

Suivi du statut — bonnes pratiques :

  1. Les webhooks d’abord : abonnez-vous à payment_session.succeeded / payment_session.under_review / payment_session.expired (voir Webhooks). C’est la source de vérité.
  2. Polling en complément : si vous interrogez GET /v1/payment-sessions/:id, limitez-vous à une fois toutes les 5 secondes maximum pendant AWAITING_PAYMENT.
  3. Arrêtez ou ralentissez le polling dès un état terminal (SUCCESS, EXPIRED, FAILED, CANCELLED) ou UNDER_REVIEW — n’interrogez plus en boucle.

checkout_url reste disponible comme fallback (lien de secours / redirection) si vous voulez basculer ponctuellement sur la page hébergée.

Statuts

StatutSignification
AWAITING_PAYMENTEn attente du paiement du client
SUCCESSPaiement reçu et confirmé
UNDER_REVIEWPaiement reçu hors délai / à vérifier — jamais confirmé automatiquement
EXPIREDExpirée sans paiement
FAILEDÉchec
CANCELLEDAnnulée par le marchand

Webhooks

Kadryza envoie, après décision sûre :

  • payment_session.succeeded — la session est passée en SUCCESS ;
  • payment_session.under_review — paiement à vérifier (jamais transformé en succès) ;
  • payment_session.expired — la session AWAITING_PAYMENT a dépassé sa fenêtre d’expiration + grâce backend sans paiement confirmé (aucun ledger créé).

Le payload inclut environment. Pour un événement test, l’en-tête X-Kadryza-Test: true est ajouté. Voir Webhooks.

Test vs Live

  • Clé test (kadryza_test_...) → session test (environment: "test").
  • Clé live (kadryza_live_...) → session live (environment: "live").
  • Le champ environment de la réponse reflète l’environnement.
  • Les webhooks d’événements test portent l’en-tête X-Kadryza-Test: true.
  • Une session test peut atteindre SUCCESS mais n’affecte jamais votre solde, vos settlements ni vos rapports financiers live.