Documentation/Le paiement direct
openapi.jsonOuvrir mon espace

Le paiement direct

Votre formulaire, votre écran : votre serveur envoie le numéro du payeur, Payiz lance la demande, le payeur valide sur son téléphone. Personne ne quitte votre application.

Quand le choisir

La page de paiementPayiz dessine tout.Le widgetLa fenêtre de Payiz, dans votre page.
Le paiement directVous dessinez tout ; le payeur valide sur son téléphone.

Les trois créent le même paiement : mêmes frais, mêmes webhooks, même reçu. Vous pouvez les mêler — le lien pour vos ventes sur les réseaux, le direct dans votre application.

Le parcours

  1. 1Votre écran recueille le numéro et l’opérateur
  2. 2Votre serveur appelle Payiz avec sa clé secrète
  3. 3Le payeur valide sur son téléphone, avec son code
  4. 4Le webhook vous dit que c’est payé, ou pourquoi non

Lancer la demande

Un seul appel : le paiement, et le numéro qui le paie. La clé porte le geste Paiements · lancer, et l’appel un en-tête Idempotency-Key, obligatoire : tirez-le de votre commande, deux clics donnent alors un seul paiement.

bash
curl https://api.payiz.app/v1/payments \
  -H "Authorization: Bearer sk_test_…" \
  -H "Idempotency-Key: cmd-42" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 10000,
    "currency": "XOF",
    "reference": "cmd-42",
    "payer": {
      "phone": "+2290197000000",
      "operator": "mtn"
    }
  }'

La réponse arrive tout de suite ; en voici l’essentiel. Le paiement est processing : la demande est partie, le payeur ne l’a pas encore validée.

json
{
  "object": "payment",
  "id": "pay_01j9x3kq7m4tzv8qhw2n",
  "amount": 10000,
  "currency": "XOF",
  "status": "processing",
  "reference": "cmd-42",
  "latest_attempt": {
    "object": "payment_attempt",
    "id": "tnt_01j9x4a2b7c5d8e3f6g1h0jk",
    "status": "pending",
    "source": "api",
    "phone": "+229 01 •• •• 34 56",
    "operator": "mtn",
    "failure_code": null,
    "payer_message": "Validez le paiement de 10 000 F CFA sur votre téléphone. Si rien n’arrive, vérifiez votre solde et votre réseau, puis réessayez."
  },
  "payment_url": "https://pay.payiz.app/pay_01j9x3kq7m4tzv8qhw2n",
  "livemode": false
}
Sans operator, Payiz le déduit du numéro. Quand plusieurs opérateurs sont possibles, l’appel échoue avec operator_required et la liste des candidats dans details.operators : proposez-les au payeur. GET /v1/payment_methods vous donne les opérateurs, leurs logos et leurs bornes.

Afficher la consigne

Pendant l’attente, dites au payeur quoi faire, et laissez-lui changer de numéro.

Votre écran, pendant l’attente
Validez sur votre téléphoneValidez le paiement de 10 000 F CFA sur votre téléphone.
Changer de numéro
payer_message est écrit pour le payeur : la consigne pendant l’attente, puis l’issue. Vous pouvez aussi écrire le vôtre à partir de failure_code.

Attendre l’issue

Le webhook fait foi. payment.succeeded dit que l’argent est arrivé ; payment.attempt_failed dit pourquoi la demande n’a pas abouti. Ne concluez jamais sur la réponse immédiate.

json
{
  "id": "evt_01j9x3p5hd2m8nq6tb0c",
  "type": "payment.attempt_failed",
  "livemode": false,
  "data": {
    "object": {
      "object": "payment",
      "id": "pay_01j9x3kq7m4tzv8qhw2n",
      "status": "requires_payment",
      "latest_attempt": {
        "status": "failed",
        "failure_code": "insufficient_funds",
        "payer_message": "Le solde ne suffit pas. Rechargez, ou payez avec un autre numéro."
      }
    }
  }
}

Sans webhook, relisez le paiement avec GET /v1/payments/{id} : latest_attempt y porte la même raison.

Relancer

Après un échec, le paiement reste payable jusqu’à expires_at. Relancez sur le même paiement, avec le même numéro ou un autre : jamais deux demandes à la fois — une demande qui attend encore répond attempt_in_progress.

bash
curl https://api.payiz.app/v1/payments/pay_01j9x3kq7m4tzv8qhw2n/attempts \
  -H "Authorization: Bearer sk_test_…" \
  -H "Idempotency-Key: cmd-42-relance-1" \
  -H "Content-Type: application/json" \
  -d '{"phone":"+2290196000000","operator":"moov"}'

Les raisons d’un échec

Un code stable dans failure_code, et une phrase prête dans payer_message.

failure_codeCe qui s’est passéCe que votre écran propose
insufficient_fundsSolde insuffisantUn autre numéro, ou relancer plus tard
payer_declinedLe payeur refuseRelancer s’il le demande
timeoutPas de validation à tempsRelancer
invalid_phoneNuméro inconnuCorriger le numéro
operator_limitPlafond de l’opérateurUn autre numéro ou un autre montant
operator_unavailableOpérateur injoignableRéessayer plus tard, ou un autre opérateur
declinedRefuséNe pas insister
unknownAutre réponseRelancer

Bonnes habitudes

  • La clé secrète vit sur votre serveur. Votre application parle à votre serveur, jamais à Payiz.
  • Restreignez la clé aux adresses IP de vos serveurs.
  • Une Idempotency-Key tirée de la commande : un rejeu ne relance jamais le téléphone.
  • Livrez sur payment.succeeded, et sur rien d’autre.
  • Une demande à la fois : attendez son issue avant de relancer.

Passer au réel

En test, tous les espaces peuvent lancer des demandes : les deux derniers chiffres du numéro choisissent l’issue (voir Tester). En réel, le direct s’ouvre avec votre palier, et votre espace vous dit s’il l’est ; Passer au réel dit le reste.

© 2026 PayizUne question ? L’aide est dans le rond, en bas à droite.

Le paiement direct

Votre formulaire, votre écran : votre serveur envoie le numéro du payeur, Payiz lance la demande, le payeur valide sur son téléphone. Personne ne quitte votre application.

Quand le choisir

La page de paiementPayiz dessine tout.Le widgetLa fenêtre de Payiz, dans votre page.
Le paiement directVous dessinez tout ; le payeur valide sur son téléphone.

Les trois créent le même paiement : mêmes frais, mêmes webhooks, même reçu. Vous pouvez les mêler — le lien pour vos ventes sur les réseaux, le direct dans votre application.

Le parcours

  1. 1Votre écran recueille le numéro et l’opérateur
  2. 2Votre serveur appelle Payiz avec sa clé secrète
  3. 3Le payeur valide sur son téléphone, avec son code
  4. 4Le webhook vous dit que c’est payé, ou pourquoi non

Lancer la demande

Un seul appel : le paiement, et le numéro qui le paie. La clé porte le geste Paiements · lancer, et l’appel un en-tête Idempotency-Key, obligatoire : tirez-le de votre commande, deux clics donnent alors un seul paiement.

bash
curl https://api.payiz.app/v1/payments \
  -H "Authorization: Bearer sk_test_…" \
  -H "Idempotency-Key: cmd-42" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 10000,
    "currency": "XOF",
    "reference": "cmd-42",
    "payer": {
      "phone": "+2290197000000",
      "operator": "mtn"
    }
  }'

La réponse arrive tout de suite ; en voici l’essentiel. Le paiement est processing : la demande est partie, le payeur ne l’a pas encore validée.

json
{
  "object": "payment",
  "id": "pay_01j9x3kq7m4tzv8qhw2n",
  "amount": 10000,
  "currency": "XOF",
  "status": "processing",
  "reference": "cmd-42",
  "latest_attempt": {
    "object": "payment_attempt",
    "id": "tnt_01j9x4a2b7c5d8e3f6g1h0jk",
    "status": "pending",
    "source": "api",
    "phone": "+229 01 •• •• 34 56",
    "operator": "mtn",
    "failure_code": null,
    "payer_message": "Validez le paiement de 10 000 F CFA sur votre téléphone. Si rien n’arrive, vérifiez votre solde et votre réseau, puis réessayez."
  },
  "payment_url": "https://pay.payiz.app/pay_01j9x3kq7m4tzv8qhw2n",
  "livemode": false
}
Sans operator, Payiz le déduit du numéro. Quand plusieurs opérateurs sont possibles, l’appel échoue avec operator_required et la liste des candidats dans details.operators : proposez-les au payeur. GET /v1/payment_methods vous donne les opérateurs, leurs logos et leurs bornes.

Afficher la consigne

Pendant l’attente, dites au payeur quoi faire, et laissez-lui changer de numéro.

Votre écran, pendant l’attente
Validez sur votre téléphoneValidez le paiement de 10 000 F CFA sur votre téléphone.
Changer de numéro
payer_message est écrit pour le payeur : la consigne pendant l’attente, puis l’issue. Vous pouvez aussi écrire le vôtre à partir de failure_code.

Attendre l’issue

Le webhook fait foi. payment.succeeded dit que l’argent est arrivé ; payment.attempt_failed dit pourquoi la demande n’a pas abouti. Ne concluez jamais sur la réponse immédiate.

json
{
  "id": "evt_01j9x3p5hd2m8nq6tb0c",
  "type": "payment.attempt_failed",
  "livemode": false,
  "data": {
    "object": {
      "object": "payment",
      "id": "pay_01j9x3kq7m4tzv8qhw2n",
      "status": "requires_payment",
      "latest_attempt": {
        "status": "failed",
        "failure_code": "insufficient_funds",
        "payer_message": "Le solde ne suffit pas. Rechargez, ou payez avec un autre numéro."
      }
    }
  }
}

Sans webhook, relisez le paiement avec GET /v1/payments/{id} : latest_attempt y porte la même raison.

Relancer

Après un échec, le paiement reste payable jusqu’à expires_at. Relancez sur le même paiement, avec le même numéro ou un autre : jamais deux demandes à la fois — une demande qui attend encore répond attempt_in_progress.

bash
curl https://api.payiz.app/v1/payments/pay_01j9x3kq7m4tzv8qhw2n/attempts \
  -H "Authorization: Bearer sk_test_…" \
  -H "Idempotency-Key: cmd-42-relance-1" \
  -H "Content-Type: application/json" \
  -d '{"phone":"+2290196000000","operator":"moov"}'

Les raisons d’un échec

Un code stable dans failure_code, et une phrase prête dans payer_message.

failure_codeCe qui s’est passéCe que votre écran propose
insufficient_fundsSolde insuffisantUn autre numéro, ou relancer plus tard
payer_declinedLe payeur refuseRelancer s’il le demande
timeoutPas de validation à tempsRelancer
invalid_phoneNuméro inconnuCorriger le numéro
operator_limitPlafond de l’opérateurUn autre numéro ou un autre montant
operator_unavailableOpérateur injoignableRéessayer plus tard, ou un autre opérateur
declinedRefuséNe pas insister
unknownAutre réponseRelancer

Bonnes habitudes

  • La clé secrète vit sur votre serveur. Votre application parle à votre serveur, jamais à Payiz.
  • Restreignez la clé aux adresses IP de vos serveurs.
  • Une Idempotency-Key tirée de la commande : un rejeu ne relance jamais le téléphone.
  • Livrez sur payment.succeeded, et sur rien d’autre.
  • Une demande à la fois : attendez son issue avant de relancer.

Passer au réel

En test, tous les espaces peuvent lancer des demandes : les deux derniers chiffres du numéro choisissent l’issue (voir Tester). En réel, le direct s’ouvre avec votre palier, et votre espace vous dit s’il l’est ; Passer au réel dit le reste.