Kadryza Pay est en preview privée au Tchad. Demander un accès anticipé →
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://app.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).

Récupérer une payment session

GET /v1/payment-sessions/:id

Retourne la vue merchant-safe. La session est filtrée par votre merchant et votre environnement : une session d’un autre merchant 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 merchant

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.