Journal des modifications
Les nouveautés de la plateforme Wajub, classées par date, version et produit.
Toutes les modifications importantes apportées à l'API et aux produits Wajub. La version actuelle
de l'API est 2026-10-11 (Gestion des versions). Les changements additifs ne
nécessitent aucune action. Les changements cassants sont publiés sous une nouvelle date.
2026-10-14
CASSANT API Transfers
Un changement de confidentialité sur toutes les versions de l'API à la fois : il n'est lié à aucune
version datée, et X-Wajub-Version ne conserve pas l'ancien comportement.
- Cassant pour une intégration qui affiche
registered_nameaprès unname_mismatch:POST /beneficiaries/{id}/verifyne renvoie que les initiales du nom détenu par l'opérateur quand il ne correspond pas à celui que vous avez déclaré,P*** N***. Une correspondance renvoie toujours le nom complet. Vérifier le nom d'un portefeuille
CASSANT API Paiements
Un changement de sécurité sur toutes les versions de l'API à la fois : il n'est lié à aucune version
datée, et X-Wajub-Version ne conserve pas l'ancien comportement.
- Cassant pour une intégration qui lit le client d'un paiement avec une clé publique (
pk.) :POST /paymentsne renvoie danscustomer,shipping_addressetbilling_addressque ce que la requête a envoyé, jamais le client que le compte a déjà avec cet e-mail ou ce téléphone.GET /payments/{id}, ainsi quePOST /payments/{id},/splitset/confirm, ne renvoient nicustomer, nishipping_address, nibilling_address, etpayment_methodne contient quechannel. Lisez-les depuis votre serveur, avec une clé privée ou restreinte. Authentification - Cassant pour une intégration qui lit le client que renvoie
POST /customersavec une clé publique : quand le compte a déjà un client avec cet e-mail ou ce téléphone, la réponse, toujours200, contient sonidet les champs envoyés par la requête. Lisez le client enregistré depuis votre serveur, avec une clé privée ou restreinte ; ces clés ne changent pas. Authentification - Cassant pour une intégration qui réutilise une
Idempotency-KeysurPOST /paymentsavec un autre corps : le corps entier est comparé,expires,customer,metadata,bearer,addressetshippingcompris, et un changement répond422. Un changement limité à l'un de ces champs renvoyait le paiement d'origine, sans le changement. Pour une clé privée ou restreinte, un paiement créé avant le 2026-10-14 est encore comparé sur les champs listés alors. SurPOST /payments, une clé qu'une clé publique a utilisée répond422à une clé privée ou restreinte, et inversement. Idempotence
API Paiements
expires.inenvoyé vide, blanc ounulldonne àPOST /paymentsson expiration par défaut, 24 heures : il créait un paiement déjà expiré. SurPATCH /payments/{id}, il laisse l'expiration telle qu'elle était. Modifier un paiement préparé- OPay (
ng.opay) et PalmPay (ng.palmpay) acceptent un numéro de n'importe quel réseau, comme Wave, Express Union, Djamo et Capitec Pay. API directe
CLI
- CLI 1.7.4 : un
406 Private Key Required, la réponse à une clé publique (pk.) sur une route qui demande une clé secrète, commewajub payments listouwajub customers retrieve, indique que la requête demande une clé secrète (sk.) ou restreinte (rk.), dit d'où vient la clé publique (WAJUB_API_KEY,--api-keyou le profil) et dit comment y mettre une clé secrète,wajub loginpour un profil. Il n'affichait que cette ligne.
Dashboard
- Modifier les coordonnées ou le statut d'un client demande désormais une vérification de sécurité récente, comme l'affichage d'une clé : modifier, bloquer, débloquer, activer, désactiver ou supprimer un client, un par un ou, hors modification, par lot, et le supprimer définitivement. La vérification dure 30 minutes.
- Supprimer des clients par lot les anonymise désormais, comme la suppression d'un seul client.
- Créer ou modifier un client live qui a un e-mail n'échoue plus sur une erreur.
- Le type d'un bénéficiaire s'affiche en lecture seule sur sa page de modification : il est fixé à sa création, et la page ne propose plus un changement qu'elle ne faisait pas.
Components
- Wajub.js 1.8.1 : chaque package passe en 1.8.1,
@wajub/js,@wajub/react,@wajub/vueet@wajub/sveltesans autre changement, et@wajub/angularest nouveau, pour Angular 17 et les versions ultérieures, installé avec@wajub/js1.8.0 ou une version ultérieure à ses côtés.provideWajub()etWajubServicechargent l'environnement d'exécution une seule fois, dans le navigateur uniquement. Des composants standalone affichent le checkout hébergé,<wajub-checkout-embed>, et chaque groupe de champs, de<wajub-card>à<wajub-crypto>, ou n'importe lequel d'entre eux avec<wajub-component>, etinjectConfirmPayment()envoie un champ. Ils se comportent comme les packages React, Vue et Svelte : le chargeurskeletonpar défaut, la hauteur estimée du formulaire tenue dès le rendu serveur, la même à l'hydratation, etappearance,locale,layoutetframeTitleenvoyés sur place, seulement quand leur contenu change. Les options sont des inputs, les callbacks des outputs, etonBeforeSubmitest l'inputbeforeSubmit. Le package fonctionne avec zone.js comme en zoneless, et avec Angular SSR. Angular - Wajub.js 1.8.0 :
loader: 'skeleton'garde votre page immobile pendant le chargement d'un champ de paiement. Le conteneur tient la hauteur du formulaire dèsmount(), avec un squelette dessiné dans le style de vos champs, et le formulaire apparaît en fondu une fois prêt. Un champ rechargé sur la page prend la hauteur que son type avait au repos, mesurée sur un vrai formulaire seulement, jamais sur un message affiché à sa place. La place n'est jamais inférieure aumin-heightpropre du conteneur, et sansreadyTimeoutle squelette laisse place à l'iframe au bout de 15 secondes, sans erreur.componentReserveHeight(type, variant, fields), surwajubet en export synchrone de@wajub/js, donne cette hauteur, une hauteur apprise sur la page une fois l'environnement d'exécution chargé.componentEstimatedHeight(type, variant, fields), de@wajub/js, donne l'estimation seule, la même sur le serveur et à l'hydratation.readyTimeoutsignale àonLoadErroret àloaderrorun champ qui n'est pas prêt à temps, avecready_timeout. Charger sans décaler la page - Wajub.js 1.8.0 :
appearance.inherit,trueou{ input, label, button, background }, reprend le style des champs, du libellé, du bouton et du fond de votre page, sous les clés que vous donnez, dans les champs de paiement,mount()etopen().wajub.appearanceFrom(), aussi sur le clientWajub()et dans@wajub/js, renvoie ce qu'il lit,{}depuis@wajub/jsquand la page charge un Wajub.js plus ancien. Reprendre le style de votre page - Wajub.js 1.8.0 :
onStateChange,onResizeetonRedirectàcreate(), pour les événementsstatechange,resizeetredirect, eton()etoff()typent la donnée de chaque événement avecComponentEventMap.confirmPayment({ timeout })ne compte plus le temps pendant lequel le paiement attend le payeur, commeAPPROVAL_REQUIRED,OTP_REQUIREDou3DS_REQUIRED, ni le temps qui suit le départ de la page chez le prestataire : un payeur qui validait sur son téléphone après plus d'une minute recevaitconfirmation_timeoutalors que le paiement aboutissait. Pendant ce temps, une iframe retirée de la page sansunmount()le fait rejeter aveccomponent_unmounted, et un champ remonté repart deINITIATED. Verrouiller votre checkout pendant le paiement - Wajub.js 1.8.0 :
update({ appearance }), sur un champ,mount()ouopen(), change les clés que vous donnez et garde les autres. Une clé donnée àundefinedounullest effacée, etappearance: undefinedefface tout, pour revenir à l'image de marque de votre Dashboard Wajub, alors qu'il ne faisait rien. Surmount()etopen(), un nouveau presetthemeremplace le précédent et ce qu'il apportait, alors que les couleurs denightrestaient sousflat, et une apparence qui n'a plus aucune clé arrive vide au checkout, alors qu'elle partait ànullet était ignorée.update({ layout })redispose les moyens d'un checkout intégré, en ligne comme dans la superposition, alors qu'il était seulement enregistré. Modifier l'apparence après le montage @wajub/react,@wajub/vueet@wajub/svelte1.8.0, qui demandent@wajub/js1.8.0 : chaque option ci-dessus est une prop, etBankTransferComponentetCryptoComponentrejoignent les composants de champs.CheckoutEmbedenvoieappearance,theme,localeetlayoutparupdate(), alors qu'il les lisait une seule fois, et ne se recharge que pour un nouveausessionIdouembedOrigin.useConfirmPaymentlit la session au moment de confirmer, depuis une ref ou un getter en Vue et un store ou un getter en Svelte, et unsessionIdpassé àconfirm()l'emporte. Les composants de champs Svelte prennent chaque gestionnaire en prop, et typent toutes leurs props. Mobile Money et carte dans votre propre checkout- Changements pour les composants de champs React, Vue et Svelte en 1.8.0 :
loadervaut'skeleton'par défaut, passez doncloader="none"pour garder l'iframe telle qu'elle arrive.minHeightn'a plus de valeur fixe par défaut : le conteneur tient dès le premier rendu la place que le SDK réservera, l'estimation decomponentEstimatedHeight()au rendu serveur et à l'hydratation, puis laisse le SDK tenir la place et finit à la hauteur du formulaire, si bien queminHeight={0}n'est plus nécessaire avecvariant="fields". UnminHeightque vous passez est gardé, et avecloader="none"chaque type garde sa propre hauteur. Un nouveauvariant,fields,loader,readyTimeout,collectAddress,addressModeoucollectNamemonte un nouveau champ dans le même conteneur, alors que seulssessionIdettypele faisaient, et que Svelte ne remontait jamais.appearance,locale,layoutetframeTitlepassent parupdate()seulement quand leur contenu change. Les trois premiers partaient ensemble à chaque changement, un objet écrit en ligne comptant pour un changement à chaque rendu, etframeTitleétait lu une seule fois. La propappearanceest envoyée entière : une clé que vous en retirez est effacée. Les gestionnaires sont toujours les derniers passés, et en changer ne recharge jamais le formulaire. Svelte monte un champ une seule fois au départ, alors qu'il le montait deux fois, et Vue remet l'environnement d'exécution et l'instance tels que le SDK les crée, pas en proxys réactifs. Avec un framework - Le checkout livré avec Wajub.js 1.8.0, quelle que soit la version chargée par votre page : un
champ de paiement dont la session est déjà terminée affiche son message à la hauteur du message,
puis envoie
readysi la session a été payée, sinonloaderroravecsession_terminal_expired,session_terminal_cancelledousession_terminal_failed: créez un nouveau paiement. Un champ qui ne peut pas savoir dans quelle page il se trouve envoieloaderroraveccomponent_origin_missing. Ni l'un ni l'autre n'envoyait rien : un squeletteskeletonrestait affiché, et le message était coupé à la hauteur du squelette. Pour ce qu'envoie Wajub.js 1.8.0, le checkout intégré appliqueupdate({ layout }), et une apparence vide ramène un champ ou un checkout à l'image de marque de votre Dashboard Wajub, alors qu'il gardait la précédente. Quand le formulaire n'arrive pas - Wajub.js 1.7.2 : avec
variant: 'fields', l'iframe d'un composant prend la hauteur de ses champs, sans minimum de 120px, qui laissait une bande vide sous un champ de numéro de téléphone. Les composants de champs React, Vue et Svelte gardent leur propreminHeight: passez0. Le SDK écarte les valeurs derulesque le checkout refusait déjà, comme;,{,\,image-set(ou une valeur de plus de 256 caractères. Dans votre propre bloc de moyen de paiement - Le checkout livré avec Wajub.js 1.7.2, quelle que soit la version chargée par votre page :
update({ appearance })sur un checkout intégré tient, alors que la saisie ou l'étape suivante du payeur remettait l'apparence donnée au montage. La page vers laquellecheckout()envoie le payeur prend votre apparence dès son premier rendu. UncolorSchemeque vous donnez s'applique dès le premier affichage sur chaque page, et masque le bouton clair et sombre du checkout. Lacoloret la police d'une règle.Inputatteignent le texte saisi, dans les champs de carte que le checkout dessine lui-même aussi, et lacolord'une règle.Labelatteint le libellé du titulaire de la carte avec Adyen. Une police Google Fonts que le checkout charge atteint les champs de carte Stripe, et sansfontSizeBaseles champs font 16px sur téléphone ou tablette, où iOS zoomait au focus. OPay et PalmPay acceptent un numéro de n'importe quel réseau, comme Wave, Express Union et Djamo. Apparence - Wajub.js 1.7.1 :
appearance.themeréglé surlight,dark,systemouauto, comme l'envoient d'anciennes intégrations dont le plugin WordPress, est lu commecolorScheme,systemvalantauto, quand vous ne donnez pas decolorScheme. Il était ignoré. Les préréglagesstripe,night,flatetnonene changent pas. Préréglages - Le checkout livré avec Wajub.js 1.7.1, quelle que soit la version chargée par votre page : un
colorSchemeque vous donnez l'emporte sur l'appareil du payeur et sur le choix qu'il a enregistré, dans un champ de paiement comme dans le checkout intégré.variables.fontFamily, qui charge une police Google Fonts connue du checkout,fontSizeBase, qui donne la taille des champs, 16px au moins sur téléphone ou tablette, libellés et aides un cran plus petits,colorText,colorTextSecondary,colorTextPlaceholderetborderRadiusstylisent désormais les champs.inputBackgroundColoretinputBorderColorne stylisent plus que les champs, alors qu'ils modifiaient tous les arrière-plans et toutes les bordures. Lesrules.Inputet.Labelatteignent les champs, alors qu'elles restaient sans effet, et une valeur qui pourrait charger une ressource ou sortir de sa déclaration, commeurl(ou;, est refusée par tous les chemins,update({ appearance })compris. Règles - Le même checkout :
readypart une fois le formulaire du composant affiché, ou aussitôt quand il n'a aucun formulaire à afficher. Il partait dès le chargement de la session, avant le formulaire. Dans le formulaire Mobile Money, chaque opérateur d'un canal qui en regroupe plusieurs, comme MTN et Orange au Cameroun, est un choix à part avec son logo, et avecfields.operator: 'detect'la liste apparaît quand le numéro ne permet pas de reconnaître l'opérateur. Un tel canal était un choix unique, fait à la place du payeur. Un portefeuille utilisable avec n'importe quel réseau, comme Wave, Express Union ou Djamo, accepte n'importe quel numéro : Wave était refusé avec un numéro Orange Money. Dans votre propre bloc de moyen de paiement
API Sync
- Un sous-compte nomme le marchand qui l'a revendiqué
connected_merchant, sur toutes les versions de l'API.slave, le même objet, est déprécié et disparaît dans la version 2026-10-12, qui retire aussi l'iddemasteret deconnected_merchant, leuidd'un canal, une répétition de sonid, et identifie un prestataire deGET /providersparprv.et son slug. Versionnage
2026-10-13
CASSANT API Paiements
Un changement de sécurité sur toutes les versions de l'API à la fois : il n'est lié à aucune version
datée, et X-Wajub-Version ne conserve pas l'ancien comportement.
- Cassant pour une intégration qui appelle ces routes avec une clé publique (
pk.) : elles répondent désormais406 Private Key Required.GET /payments,DELETE /payments/{id},POST /payments/{id}/closeetGET /payments/{id}/refunds;GET /customers,GET,PUTetDELETE /customers/{id}, ainsi que sesblock,unblock,activateetdeactivate; toutes les routes/linkset/invoices. Faites ces appels depuis votre serveur, avec une clé privée ou restreinte. Une clé publique crée, débite, confirme et lit toujours un paiement par son identifiant, litGET /payments/options, crée un client avecPOST /customerset lit les données de référence. Authentification - Cassant pour une clé restreinte qui n'a que des scopes
payment.*:POST /payments/{id}/closeavecoutcome: refundexige aussirefund.write, commePOST /refunds, etGET /payments/{id}/refundsexige aussirefund.read. Ajoutez à la clé le scope de remboursement dont elle a besoin. Scopes des clés restreintes - Cassant pour une plateforme dont la connexion a
paymentssansrefunds: avecX-Sync,GET /payments/{id}/refundsetPOST /payments/{id}/closeavecoutcome: refundexigent aussi la capacitérefundsde la connexion, comme/refunds: une connexion qui n'a quepaymentsreçoit désormais403. Capacités du compte DELETE /keys/currentrévoque toute clé créée par un appairage (wajub login, la connexion d'une application), plus seulement une clé dewajub login. Toute autre clé reçoit toujours409.
API Paiements
POST /payments/{id}/activateacceptereferenceetdescription, qui remplacent ceux donnés à la préparation du paiement, quand votre commande n'existait pas encore. Absents, ceux de la préparation restent. Activer un paiement préparéPATCH /payments/{id}vérifie le nouveau montant commePOST /payments: hors des limites de la devise, il répond422suramount, et quandacceptne laisse plus aucun moyen de le payer,422suraccept. Il accepteexpires.in, de 5 à 43 200 minutes à partir de maintenant, et le paiement garde cette expiration une fois activé. Modifier un paiement préparé
Dashboard CLI Plugins
- Approuver
wajub loginou la connexion d'une application, comme Connexion avec Wajub dans le plugin WordPress, est réservé au propriétaire, à un Administrator ou à un Developer (à un Sandbox User pour une clé sandbox uniquement), et exige un code de vérification de sécurité récent (il vaut de 15 à 30 minutes). Tout autre membre apprend qu'un administrateur ou un développeur doit approuver, et le support Wajub connecté à votre compte ne peut ni approuver ni refuser. La page démarre toujours sur Sandbox, quoi que demande l'application, et la personne qui approuve choisit l'environnement. Installation et authentification - La personne qui approuve choisit la durée de la clé d'une application : 90 jours, par défaut, ou
une durée indéterminée. Une clé de
wajub logindure toujours 90 jours. Une clé approuvée doit être récupérée dans les 15 minutes, sinon elle n'est jamais remise et elle est supprimée. Le propriétaire et chaque Administrator reçoivent un e-mail pour chaque clé créée par un appairage. - Settings → Developer → API Keys indique quand chaque clé cesse de fonctionner : Expire le … ou Expirée le …. Une clé sans expiration n'affiche aucune date. Environnements et API keys
- Transférer l'équipe, confirmer un payout, et afficher une API key ou copier ses lignes
.envdemandent un code de vérification de sécurité, de votre application d'authentification ou envoyé par SMS ou par e-mail, comme renouveler ou supprimer une clé. Ces actions demandaient votre mot de passe, ou rien, puis étaient refusées. Un mot de passe confirmé n'ouvre aucune de ces actions : c'est le code qui les ouvre, pendant 15 à 30 minutes. Équipe et sécurité
Components
- Wajub.js 1.7.0 :
frameTitle, passé àcreate()ou àupdate()d'un composant, nomme son iframe pour les lecteurs d'écran, dans la langue de votre page. L'iframe s'appelait toujoursWajub <type> component. - Wajub.js 1.7.0 : quand le paiement se poursuit sur la page du prestataire, PayPal, Mollie ou un
paiement crypto par exemple, le composant émet
redirectavec{ url, method }et Wajub.js y emmène votre page. L'iframe y allait elle-même, et les prestataires refusent d'y être affichés. Un prestataire qui prend tout l'onglet, comme Mollie, PayPal, Djamo, Adyen ou Paddle, ramène le payeur sur la page Wajub de la session, dans la langue du composant, qui affiche le résultat puis envoie le payeur sur lecallbackdu paiement avecstatus,referenceettrxref, d'elle-même après un succès et au choix du payeur après un échec, ou garde le résultat affiché quand il n'y a pas decallback. La page du prestataire ouverte dans un nouvel onglet depuis un paiement en attente ramène le payeur de la même façon. Une page restée sur une version antérieure de Wajub.js garde l'ancien comportement. Quand le paiement se poursuit sur la page du prestataire - Le checkout livré avec Wajub.js 1.7.0, quelle que soit la version chargée par votre page : un
envoi demandé avec
submit()ouconfirmPayment()qu'un composant refuse, quel que soit son formulaire, comme un numéro Mobile Money vide ou invalide, une carte laissée incomplète chez n'importe quel prestataire, des champs de carte encore en chargement, un virement sans IBAN ni numéro de compte, un paiement crypto sans actif ou un numéro de carte rejeté par son prestataire, émeterroravecsubmission_failedet un message pour le payeur, etconfirmPayment()rejette avec cette erreur. Un formulaire qui n'était pas prêt ne disait rien auparavant, sauf quand l'e-mail manquait. Un appui sur Entrée dans un formulaire qui n'est pas prêt n'affiche la raison que dans le composant. Un envoi pendant le paiement ne fait rien, quel que soit le moyen : rien n'est débité deux fois. Les écrans OTP, PIN, validation sur le téléphone, USSD et 3-D Secure donnent leur hauteur àresize, alors qu'ils étaient coupés à la hauteur du formulaire, et une fenêtre de carte bloquée par le navigateur aprèsonBeforeSubmitlaisse un bouton Continuer sur … dans le composant. Envoyer le paiement
Plugins
- Plugin WordPress 1.4.0 : deux nouveaux moyens de paiement WooCommerce, Mobile Money et Carte bancaire, chacun avec le formulaire de paiement de Wajub dans votre checkout, classique et Blocks. Les deux restent désactivés tant que vous ne les activez pas : une boutique existante ne voit aucun changement. WordPress
- Plugin WordPress 1.4.0 : Connexion avec Wajub, dans l'assistant de configuration et dans les réglages, obtient la clé du site une fois que vous l'approuvez dans le Dashboard, sans rien à copier ; coller des clés reste possible. L'expiration de la clé s'affiche dans l'administration, et l'adresse e-mail d'administration du site reçoit un e-mail dès 14 jours avant cette date.
- Plugin WordPress 1.4.0, changement de comportement : chaque environnement paie uniquement avec sa propre clé. Un site en Sandbox qui n'a qu'une clé live ne prend plus de paiements réels avec elle, et n'en prend aucun tant que vous n'ajoutez pas de clé sandbox ou ne passez pas en Live. À la mise à jour, un site de production dans ce cas passe une fois en Live et le signale ; une copie locale, de développement ou de préproduction reste en Sandbox.
- Plugin WordPress 1.4.0 : un client WooCommerce ne paie que ce qui reste. Un paiement inférieur au total de la commande, comme un paiement en plusieurs fois clôturé plus tôt, compte pour elle, et le client paie le reste depuis la page de paiement de la commande. Un paiement en plusieurs fois encore ouvert est repris quand c'est possible, ou clôturé en gardant ce qu'il a encaissé, et les remboursements faits dans WooCommerce sont répartis entre les paiements de la commande. WordPress
2026-10-12
NOUVEAU API
La version d'API 2026-10-12 est celle des nouveaux comptes. Un compte existant garde sa
version et l'obtient avec X-Wajub-Version ; les webhooks suivent toujours la version actuelle,
2026-10-11. Ses changements cassants :
- Un canal de
GET /channelsetGET /providersn'a pluscurrency, qui valaitXAFpour tous les canaux. currencyest obligatoire surPOST /transferset sur chaque ligne dePOST /transfers/batch. Les versions antérieures prennent encoreXAFpar défaut : envoyez-la quelle que soit votre version.- Un lien de paiement n'a plus de
category_id:POSTetPUT /linksne le prennent plus,GET /linksne filtre plus dessus, et un lien ne le renvoie plus. - Un transfert ou un remboursement arrêté avant son envoi affiche
cancelled, avec le motifmerchant_rejectedoucancelled_by_wajub, et?status=failedne le liste plus. Les versions antérieures affichentfailed. Les webhooks suivent la version actuelle : un tel arrêt part entransfer.failedourefund.failedtant que 2026-10-12 n'est pas actuelle, puis entransfer.cancelledourefund.cancelled.
API Paiements
-
POST /payments/{id}/splitsdébite les tranches en live, sur Mobile Money. Chaque appel débite la tranche suivante ; le paiement restepartialjusqu'à la dernière, et une tranche refusée laisse acquises les tranches payées. Chaque tranche payée est créditée sur votre solde dès qu'elle passe, avec sa part des frais Wajub, en live comme en sandbox ; elle est versée sur votre compte de versement comme tout paiement, et la page du paiement dans le Dashboard affiche sa retenue. Paiements fractionnés -
Nouveau
POST /payments/{id}/close: clôturez un paiement réglé en partie, en gardant (outcome: keep) ou en remboursant (outcome: refund) ce qui a été encaissé. Il passe àsucceededpour ce montant, et les remboursements se mesurent sur lui.DELETE /payments/{id}répond409 payment_partly_paidsur un tel paiement. Clôturer un paiement -
La sandbox ne fractionne plus d'elle-même un débit Mobile Money au-dessus du plafond par transaction : elle répond
422, comme le live. Une fois qu'un paiement a un plan en tranches, chaque débit suivant, y compris celui de la page de paiement, prend la tranche suivante, et un autre plan répond422. -
Nouveau
POST /payments/{id}/confirm: terminez depuis votre serveur, avec votre clé secrète, l'étape OTP, PIN, téléphone, date de naissance, adresse ou fenêtre du prestataire d'un débit. Il répond comme le débit :200,202avec l'étape suivante, ou402avecattempts_remaining. Confirmer une étape -
Chaque canal Mobile Money annoncé débite désormais en live : T-Money, Tigo Pesa, HaloPesa, Free Money, Vodafone Cash (Ghana et Égypte), AirtelTigo Money, Zamtel Kwacha, TNM Mpamba, Africell RDC, Moov Money au Gabon, au Burkina Faso et au Mali, et MTN au Liberia et en Guinée. Djamo et Capitec Pay acceptent tout numéro. Numéros de téléphone
-
accept.channelsacceptemobilepour tous les opérateurs Mobile Money. L'objet paiement renvoiebearer,expires_atetlink, le lien de paiement dont il vient. Choisir ce qu'un paiement accepte -
Un débit carte accepte
card_binà la racine du corps, comme chaque champ dedata. En sandbox, la carte de test est elle aussi lue à la racine (card.number,card.holder). -
Un débit sur un paiement déjà
processingrépond409avecerror_code: payment_in_progress. La réponse -
Le
402d'un débit refusé portepayer_message, une phrase à montrer telle quelle au payeur. Codes de statut -
callbackdoit être en HTTPS (http://localhostethttp://127.0.0.1acceptés en sandbox).metadata.cancel_urlest obsolète : le callback est l'unique retour, quelle que soit l'issue. Checkout hébergé -
GET /payments?reference=liste les paiements créés avec exactement cettereference. Un paiement se lit par sonid;referencevous appartient et n'est pas unique, etIdempotency-Keyévite les doublons. -
Un paiement échoué porte
failure_reasonetfailure_message, sur le paiement et danspayment.failed. Motifs d'échec -
Un blocage Shield répond
403avecerror_code: shield_blockedetblock_reference. Blocages Shield -
Un compte dont la vérification n'est pas approuvée ne peut encaisser aucun paiement live, quel que soit le prestataire :
402 merchant_not_verified. Conformité -
Un
customer_idinconnu surPOST /paymentsrépond422sur ce champ, et non404 Resource Not Found.operatoretsave_payment_methodsont lus à la racine d'un débit.GET /payments/optionsest documenté et répond dans l'enveloppe habituelle. -
La sandbox débite comme le live : les numéros d'échec répondent
402avecerror_code: insufficient_funds, un numéro au format local est lu dans le pays du canal, et chaque canal Mobile Money annoncé a un numéro de test, Vodafone Cash Égypte (+2010…) et Orange Money Sierra Leone (+23276…) compris. Capitec Pay a ses propres numéros de test (+2761…), qui choisissent le résultat ; le numéro de test de tout opérateur le paie toujours. Un numéro qui n'est pas un numéro de test reçoit un422qui liste les numéros de test de l'opérateur du canal. Scénarios de test -
GET /channels:min_amountetmax_amountsont des nombres en unité principale (c'étaient des chaînes cent fois plus grandes : retirez toute division par 100), etliveetchargedisent ce qu'ils promettent. Le plafond par transfert d'un canal est lui aussi lu en unité principale. Couverture -
Chaque
422portestatus: "Unprocessable Content"et un objeterrors; un refus qui ne concerne aucun champ précis range son message souserrors.request. Codes de statut -
Les filtres des listes sont vérifiés au lieu d'être ignorés, chacun avec une
422sur son champ :- toute liste paginée, codes et juridictions de taxe compris : un
pagequi n'est pas un entier à partir de 1 ; GET /linksetGET /invoices: unper_pagehors de 1–100, qui était ramené dans les bornes, et unsort_byou unsort_dirinconnu ;GET /invoices: unstatusou unpayment_statusinconnu, et undate_from,date_to,due_date_fromoudue_date_toqui n'est pas une date ou finit avant de commencer (il répondait500) ;GET /links: untypeinconnu ;GET /events: untypequ'aucun endpoint ne reçoit (les deux renvoyaient une liste vide) ;GET /channels: uncountryinconnu ;GET /countries: uneregioninconnue ;GET /currencies: untypeautre quefiat,cryptoouall, lu sans tenir compte de la casse, si bien quetype=CRYPTOliste les cryptomonnaies là où il listait les devises classiques.
GET /linkstrie désormais d'abord sur lesort_byet lesort_dirdemandés, puis du plus récent au plus ancien entre liens à égalité. Pagination - toute liste paginée, codes et juridictions de taxe compris : un
-
Les limites de débit se comptent par environnement : une rafale en sandbox n'entame plus le budget live. Lire un transfert ne compte plus dans le compteur d'écritures de versement. Un
429ou un400de version porte désormais les en-têtes CORS,X-Wajub-Versionest autorisé en preflight, etRetry-After,X-RateLimit-ResetetX-Wajub-Versionsont lisibles depuis un navigateur. Un429d'une limite plus stricte, comme celle des écritures de versement, répond comme le limiteur principal :typela nomme (payout_writes), etretry_aftercommeRetry-Afterdonnent l'attente réelle.X-RateLimit-Resetdonne la fin de la fenêtre en cours. Limites de débit -
GET /indique dansenvl'environnement de la clé utilisée./healthet/health/readyrenvoient la version de l'API. Monitoring -
Identité est disponible sur Growth, Scale et Enterprise ; Pay as you go reçoit
403. Identité -
Référence de l'API : chaque paramètre est décrit avec un vrai exemple, et les champs de requête qui acceptent
nulll'indiquent. Les pages des factures, des remboursements, du relevé et des créances montrent leur réponse de succès, et les listes de remboursements, bénéficiaires, liens, comptes et endpoints de webhook un élément complet. Les filtres d'unGETne sont que des paramètres de requête,beneficiarysurPOST /transfersprend unidou un objet, et les chemins des litiges s'écrivent{id}. La spécification OpenAPI déclare des schémas réutilisables (Payment, Transfer, Refund, Customer, Beneficiary, Invoice, Link, Account, Event, WebhookEndpoint, Balance, Error) que ses réponses référencent, pour en générer un client, etGET /eventsliste les 77 types d'événement qu'il accepte entype. Les pages d'aperçu des ressources sont disponibles en français. Référence de l'API
API Versements
- Un versement refusé répond
422avec unerror_codeà côté demessageeterrors, surPOST /transfers, sur chaque ligne refusée d'un lot et surPOST /accounts/{id}/payouts. Une ligne de lot dont le bénéficiaire n'existe pas ditbeneficiary_not_found, et non « safe to retry ». Refus de versement - Chaque ligne de lot passe les contrôles de
POST /transfers: les bornes de la devise (amount_out_of_range), et un bénéficiaire désigné par sonidseulement (beneficiary_not_found). - Un versement désigne le canal de son opérateur (
ke.mpesa,eg.vodafone…). Le seul canal générique estcm.mobile, qui déduitcm.mtnoucm.orangedu numéro : en live d'après le vrai plan de numérotation du Cameroun, comme les paiements, en sandbox d'après les préfixes de test. Tout autre{pays}.mobileest refusé comme un canal inconnu. Bénéficiaires - Un bénéficiaire supprimé reste sur ses transferts et son relevé, avec
deleted: true. Payer un bénéficiaire désactivé répond422 beneficiary_inactiveau lieu de404. - Un versement live qui attend plus de 10 secondes répond
429 payout_queue_busyavecRetry-After: renvoyez-le avec la mêmeIdempotency-Key. Limites - Les versements de toutes les devises comptent dans votre plafond quotidien de versements,
versements retenus pour vérification compris, dans l'API comme dans le Dashboard. Un versement
sandbox dont le portefeuille couvre le montant mais pas
les frais est refusé avec
insufficient_balance. - Un ancien versement du Dashboard qui attend encore votre confirmation, et qui affiche
pendingen live, peut de nouveau être confirmé ; il peut être retenu enreviewavant son départ. Après un refus, le bouton Confirmer peut de nouveau être utilisé. Statuts des transferts - Documentation : un versement refusé conserve le bénéficiaire passé en ligne. La référence et les
statuts des transferts suivent la vraie réponse, Balance documente
disputed,in.transitethold, le tableau des retenues gagne une ligne « Wajub a restreint votre compte », et les routes qui partagent le compteur d'écritures de versement sont listées. Transferts, Balance
API Factures
- Un paiement n'est rattaché qu'à une facture de son propre compte.
GET /invoices:amount_minetamount_maxse lisent en unité principale. La facture gagnecustomer, l'identifiantcus_; un paiement fait sur la page d'une facture la désigne dansinvoice.invoice.paidetinvoice.payment_succeededsont envoyés.POST /invoices/{id}/sendrépond422quand la facture n'a aucun destinataire et400pour une facture déjà payée, annulée ou remboursée.mark-paidrefuse un brouillon, une facture déjà payée et un montant nul. Une facture payée passe àrefundedune fois ses paiements en ligne intégralement remboursés ; une facture payée en partie en ligne aussi, avecinvoice.updated. Factures- Les factures envoyées par l'API prennent leur numéro dans la numérotation de votre compte, la même
séquence que le Dashboard : votre préfixe (
INV-par défaut), l'année et un compteur à quatre chiffres remis à zéro chaque année (INV-2026-0001). Un numéro est unique dans votre compte. - Nouveau champ
language(frouen) surPOSTetPUT /invoiceset dans chaque réponse de facture. Il fixe la langue des e-mails, des relances et du PDF, et la page de la facture s'ouvre dans cette langue (ajoutez?locale=frou?locale=enpour changer). Sans lui, une facture prend la langue préférée du client lié, sinon celle de votre compte (Settings → Regional → Language), sinonen; les factures créées dans le Dashboard enregistrent la leur selon la même règle. - Le PDF de la facture est public une fois la facture envoyée :
https://api.wajub.com/i/{id}/pdf, avec?locale=fr|en.invoice.createdest envoyé une seule fois, avec les lignes et les totaux, sansinvoice.updatedpendant la construction de la facture.PUT /invoices/{id}envoie un seulinvoice.updated, avec les lignes et les totaux enregistrés, et aucun quand il ne change rien. sort_bysurGET /invoicestrie désormais la liste, etsearchtrouve les factures par le nom et l'e-mail écrits dessus. Lepayment_datedemark-paiddevientpaid_atdès que le paiement solde la facture. LecurrencydePOSTetPUT /invoicesdoit être une devise prise en charge par Wajub, sinon422.- Sur une facture sans e-mail, l'adresse que le payeur donne sur sa page est enregistrée comme
customer_email, avecinvoice.updated. Un e-mail que vous avez renseigné n'est jamais remplacé. - Un paiement sur la page de la facture tient compte des avoirs du Dashboard : la facture ne passe à
paidqu'une fois ce qui a été payé, moins les avoirs, égal au total. Factures
Link Paiements
- Le
custom_urld'un lien de paiement doit être unique sur Wajub, liens supprimés compris (422). L'objet lien renvoiesingle_use_linket tous les autres champs que vous pouvez définir, et consulter un lien n'envoie pluslink.updated. Liens de paiement GET /customers?country=filtre sur le pays de l'adresse du client.PUT /customers/{id}gardenamesauf si un champ de nom est envoyé avec une valeur. Clients
API Remboursements Litiges
- Un remboursement live qui a pris de l'argent sur votre solde porte
ledger_balance_before,ledger_balance_afteretledger_balance_currency. Un remboursement que l'opérateur refuse après son envoi resteprocessingpendant que Wajub le mène à terme autrement, sans jamais revenir àpending. Un remboursement échoué porte toujours unfailure_reason, pris dans une seule liste en production et en sandbox. Remboursements refund.succeededpart une fois le remboursement sorti de votre solde et porteledger_balance_beforeetledger_balance_after, sandbox comprise. Un remboursement refusé par le prestataire que Wajub n'a pas pu mener à terme autrement finit avec la raison du prestataire ;ops_failedseulement sans raison connue. Gérer les remboursements- La
referenced'un remboursement n'est jamais que la vôtre : l'identifiant du prestataire est dansprovider_reference. Unmetadatade remboursement vide vaut{}, et la recherche de remboursements en sandbox couvre aussireference. dispute.deadline_approachingest envoyé deux jours avant l'échéance d'un litige.dispute.closedsuit aussidispute.lost. Les litiges ouverts depuis Pocket reçoivent undue_dateà sept jours, et le même rappel. Litiges- Une preuve de litige exige un texte ou un fichier (
422). Les justificatifs et les pièces jointes des messages sont des fichiers privés : chaque réponse de l'API qui renvoie un litige donne à chaque fichier uneurl, un lien signé valable 30 minutes, et les webhooks ne portent quefile_path. Le Dashboard les relie de la même façon et affiche dans le fil du litige le fichier joint par le payeur depuis Pocket. Litiges
Sync
- Un litige perdu rend votre commission selon le
commission_refund_policyde la connexion, comme un remboursement, et la sandbox déplace la commission dans les deux sens.fee.receiveddonne la commission dans la devise de la règle tarifaire. Capacités des comptes - Tant que les paiements d'une connexion sont suspendus, les lectures avec
X-Syncfonctionnent ; seuls les appels qui déplacent de l'argent sont refusés. Une connexion Relay ne porte plus de date d'invitation.POSTetPUT /accountsacceptent l'emaildu marchand, un rappel garde valide le lien que vous avez envoyé, et un nouveau lien relance les trente jours, comme le fait désormais Renvoyer l'invitation dans le Dashboard. Les événementsdispute.*sont copiés vers la plateforme. Onboarding POSTetPUT /accountsenregistrent vosmetadatatelles que vous les envoyez. Chaque compte les renvoie ({}si vides) ;PUTles fusionne, et une clé envoyée ànullest supprimée. Le compte affichepricing.min_fee, etGET /accounts?status=filtre sur le statut affiché,expiredcompris. Sous-comptes- Après l'onboarding, le marchand revient sur votre
callbackavecaccount, l'identifiantacc_…, à côté destateetstatus. Lecallbackdoit être en HTTPS (http://localhostethttp://127.0.0.1acceptés avec une clé sandbox) ; un callback déjà enregistré continue de fonctionner. - 50 invitations ouvertes au plus par environnement, au-delà
POST /accountsrépond429; les connexions Relay ne comptent pas. Une connexion de l'autre environnement répond404. Une connexion Relay n'a pas de lien d'autorisation :authorization_urlvautnull, et/tokenrépond422. POST /accounts/{id}/payoutsne renvoie que le versement automatique du jour, qui peut êtrefailed. Versements- Les événements envoyés par le Dashboard portent
accountà côté desync_uid.account.updatedest envoyé une fois, avec le compte entier, quandPUT /accounts/{id}modifie un compte, quandPOST /accounts/{id}/tokenremet une invitation annulée enpending, et quand Wajub envoie le versement d'un marchand Lite (last_payout_at). Un enregistrement qui ne change rien n'envoie rien,DELETEenvoieaccount.deauthorized, et on peut de nouveau choisiraccount.updatedsur un endpoint. Événements webhook - Commissions dues :
transactionest l'iddu paiement (trx_…), celui que litGET /payments/{id}, dansGET /accounts/{id}/commission-receivableset dans les webhooksaccount.commission_receivable_recordedetaccount.commission_receivable_collected, pour toutes les versions de l'API.
Tax
- Un remboursement n'annule sa part de taxe que si le paiement en a enregistré, et il le fait même après la désactivation de Tax ou quand votre offre ne la couvre plus. Rapports
- La taxe d'un paiement est enregistrée au taux national, comme
/tax/calculatela calcule, et n'est pas enregistrée tant que votre offre ne couvre pas Tax. Les alertes de seuil convertissent les ventes dans la devise du seuil, et le seuil UE compte tous les États membres. - La page de paiement hébergée n'affiche aucune ligne de taxe, et les montants convertis n'en
contiennent pas :
taxvautnulldans la session. La taxe se calcule quand le paiement est crédité, sans jamais s'ajouter à ce que paie le payeur. - Les numéros fiscaux des clients sont vérifiés avec les mêmes formats que le vôtre, avec ou sans
séparateurs, et ajouter un numéro déjà enregistré relance sa vérification (
200).gh.vatetgh.tinsuivent le format de la GRA (C0001234567, ou un PIN de Ghana Card) ; l'ancienne forme degh.tinà 12 caractères est refusée. Configuration - Enregistrements fiscaux : un doublon pour le même pays et le même État répond
422, un identifiant mal formé404, etPUTpeut réactiver un enregistrement révoqué./tax/calculaterépond422pour un pays inconnu et404pour un client inconnu, et retirer le numéro fiscal d'un client avec un identifiant mal formé répond404au lieu de500. API Tax - Documentation : exemples d'arrondi corrigés, autoliquidation précisée, permissions et pagination documentées.
Shield
- Les paiements sandbox n'ont jamais d'effet sur la notation du risque en live. Risk Scoring
- Des refus répétés sur un même BIN de carte chez vous comptent désormais dans le score de risque.
- La liste de blocage contrôle chaque valeur selon son type et l'enregistre sous une seule forme
(
+237 670 00 00 00et237670000000sont une seule entrée). Une valeur impossible répond422, et retirer une entrée inconnue répond404. Règles - Un
PUT /shield/settingspartiel garde vos réglages Advanced enregistrés./shield/statscompte les revues comme la file et inclut les litigesunder_review. Les règles en test sont toujours évaluées après la règle live qui décide. Un litige accepté dans le Dashboard pèse sur la réputation du payeur comme un litige accepté par l'API. API Shield
Orchestration
- Une route qui échoue sans cesse est mise en pause quelques minutes, puis essayée de nouveau ; une route qui échoue encore reste en pause plus longtemps. Bascule en cascade
- Le routage écarte un prestataire que Wajub marque en maintenance (
provider_in_maintenance), bientôt disponible ou désactivé (provider_unavailable) ; seuls les prestataires disponibles ou en bêta reçoivent des paiements. Le simulateur de routage indique chaque motif. Règles de routage - Chaque tentative enregistre sa latence, affichée dans la chronologie du paiement et pour chaque candidat dans le journal de routage. Une connexion peut être limitée à des devises choisies, dans l'assistant et sur sa page. Un rail Wajub approuvé démarre à la priorité 0, comme toute autre connexion. Prestataires
- Les alertes du Dashboard limitées à un canal ou à une règle, l'aperçu d'impact d'une règle et le conseiller lisent le canal et la règle de routage de chaque paiement, et « Cascade récupérée » ne compte que les basculements. Ils comptent les paiements routés à partir de cette version : les paiements antérieurs ne portent ni canal routé ni règle.
GET /channelsrenvoiecountries: []pour un canal global au lieu de[""].- Documentation : le délai à laisser à votre client (au moins 90 s), les sessions client et les confirmations qui ne basculent jamais, les prestataires que vous pouvez connecter, et les moyens internationaux à venir sur Couverture. Orchestration
Webhooks
payment.attempt_failedest envoyé quand une tentative est refusée aussitôt et que le paiement repassepending.payment.expiredetpayment.cancelledpartent en sandbox comme en live ; une expiration sandbox n'envoie pluspayment.failed.- Chaque tentative de livraison est signée avec le secret actuel de l'endpoint : une rotation couvre aussi les nouvelles tentatives.
link_payment_completen'est plus livré (payment.succeededle couvre), etGET /eventsne liste que les types livrés.- Dans les contenus, un objet vide comme
metadatareste{}au lieu de[], à la livraison, au renvoi ou dans une liste. Les événementspayment.split.*portent le paiement complet,payment_methodcompris. beneficiary.createdpart aussi pour les comptes de retrait ajoutés dans le Dashboard, ettransfer.processingune seule fois à l'approbation d'un versement retenu. Événements webhook
Components CLI Dashboard
- Wajub.js 1.6.0 :
onSuccess,onBreakdownetfetchSession()donnent les montants en unités normales (12.5pour 12,50 EUR) ; retirez toute division par 100.onSuccessporteid, l'identifiant Wajub du paiement. Au retour du checkout hébergé,referenceest cet identifiant ettrxrefvotre référence. En ligne, Terminé etclose()appellentonClose.CheckoutStategagne quatre états d'étape, chaque wrapper réexporte les types du cœur, etWajubPay.create()est obsolète. Référence de l'API - Wajub.js 1.6.0 : un checkout hébergé qui ne charge pas sa session ferme l'overlay ou retire le
cadre en ligne juste après
onLoadError, sansonClose.submit()sans bouton de paiement à presser appelleonErroravecnothing_to_submit. Chaque checkout n'écoute que sa propre iframe : avec deux checkouts sur une page, chacun ne reçoit que sa propre fermeture et son propre succès. En Vue,<CheckoutEmbed>affiche son état de chargement quandshow-loadingest absent. @wajub/svelte1.6.0 livre ses composants en source, compilés par le Svelte 4 ou 5 de votre projet, et ils ont désormais des types de props. Un projet Svelte 5 qui impose les runes à tous les fichiers doit en exclurenode_modules, comme le faitnpx sv create. Svelte- Checkout hébergé : un payeur qui réessaie pendant que sa tentative précédente est en cours attend
son issue sur un écran « paiement en cours », dans sa langue, au lieu d'une erreur en anglais. Si
cette tentative se termine sans débit, le checkout revient au moyen de paiement et affiche le
payer_messagedu refus. Le retour après un paiement échoué portereference(l'identifiant Wajub) ettrxref(votre référence). Checkout hébergé - Le CLI 1.7.3 complète
payment.attempt_failedetdispute.deadline_approaching, et déclenche chaque canal Mobile Money avec son numéro sandbox. Une connexion ne déplace plus votre profil par défaut : une première connexion sandbox devient le profil par défaut, une connexion live jamais (wajub config use <profil>). Avec-d, une valeur à zéro initial ou de plus de 15 chiffres, et un champ nomméphone, finissant par_phone,account_numberoureference, restent du texte.wajub doctorexige Node.js 22, etwajub open balanceouvre la page des soldes.wajub listen --eventsne propose pluspayment.checkout_page_opened,payment.redirected_to_callbacknilink.expired, qu'aucun endpoint ne reçoit. Déclencheurs - Dashboard : une équipe peut détenir une seconde clé publique, et en modifier ou supprimer une. Le rôle Développeur gère les prestataires, les domaines, la bascule sandbox/live et l'orchestration (règles de routage, politiques de canal, alertes), et peut lancer le simulateur de routage et prévisualiser l'impact d'une règle. Les membres qui gèrent les réglages peuvent exiger la double authentification. Un membre derrière une IP bloquée peut encore changer son mot de passe, sa double authentification et ses passkeys. L'assistant de connexion laisse décochés les canaux à activation explicite. Équipe et sécurité
- Dashboard : se connecter avec une passkey compte comme second facteur. Fermez une
seule de vos autres sessions depuis Settings, Security. Filtrez le journal d'audit de l'équipe par
membre. Une clé d'API désactivée est marquée Désactivée, et les clés restreintes ne proposent
pas de scope
settings. Approuverwajub loginou l'appairage d'un autre appareil demande la permission de gérer les clés d'API. - Dashboard : les sites autorisés à intégrer votre checkout ont leur propre page, Settings → Checkout embedding, sur toutes les offres, Pay as you go compris, et le rôle Développeur peut les modifier. Une fois la liste renseignée, seuls ces sites peuvent afficher votre checkout. Tant qu'elle est vide, le Dashboard vous rappelle de les déclarer : faites-le avant d'encaisser en live.
- Dashboard : modifier Team security, créer ou modifier une clé d'API, créer, modifier, supprimer ou promouvoir un endpoint de webhook, inviter, modifier ou retirer un membre, quitter une équipe, modifier les réglages de sécurité des versements et enregistrer la liste d'intégration demandent de confirmer votre identité ; l'enregistrement de la liste d'intégration figure aussi dans le journal d'audit. Un endpoint de webhook créé sans description reçoit une erreur de validation au lieu d'une erreur serveur.
- Konsole : les logs d'API enregistrent la version d'API de chaque requête. Explorateur de logs
SDK Plugins
- Les SDK serveur relancent le
409envoyé par l'API quand une requête avec la mêmeIdempotency-Keyest encore en cours, et renvoient le résultat de la première : Node.js et C# 2.0.0, PHP 2.0.1, Ruby 1.3.0, Python, Go et Java 1.2.1. Go garde la mêmeIdempotency-Keyd'une tentative à l'autre. Idempotence - SDK serveur, mêmes versions : correctifs de sécurité dans la vérification de signature des webhooks. Mettez à jour votre SDK serveur.
- SDK Node.js 2.0.0 : les résultats sont des objets typés là où la 1.5.0 renvoyait des
enregistrements bruts,
WebhookEventporte le type dansevent, etexpires.inest typé.payments.initializedisparaît : appelezcreate. SDK Node.js - SDK C# 2.0.0 :
Webhooks.ConstructEventrenvoie des valeurs simples (string,longoudouble,bool, dictionnaires et listes) au lieu deJsonElement. Le code qui lisait desJsonElementdoit passer aux valeurs simples. SDK C# - SDK Ruby 1.3.0 : les méthodes de taxe (rapports, codes, enregistrements, juridictions, seuils) et la liste de blocage Shield sont dans la gem, comme dans les autres SDK serveur. SDK Ruby
- React Native 1.4.1, Android 1.2.1 et Flutter 1.5.0 :
401,404et une session terminée (410) ne sont pas réessayables, et une erreur serveur (5xx) est une erreur d'API. React Native et Android annulent le paiement quand le payeur ferme l'interface avant d'avoir rien soumis, comme Flutter, dontshowWajubPaymentSheetappelle désormaisonCancel. Les interfaces React Native et Flutter parlent français. React Native ouvre la page 3D Secure sur Android 11+ sans bloc<queries>, et@stripe/stripe-react-nativeest vraiment facultatif.watchStatus()de Flutter suit l'identifiant Wajub du paiement et continue le polling pendant toute la surveillance. SDK mobiles - Extension WordPress 1.2.1 : correctif de sécurité pour le contenu payant et pour l'inscription aux cours LearnDash, LifterLMS et Tutor LMS. Mettez à jour vers la 1.2.1. Les boutons des cours ne s'affichent qu'aux visiteurs connectés. Chaque intégration lit le retour du payeur par l'identifiant Wajub du paiement, et une commande antérieure à 1.2.1 retrouve son paiement par la référence envoyée par l'extension. WordPress
- Extension WordPress 1.2.1 : un remboursement partiel lancé depuis WooCommerce est enregistré une
seule fois. MemberPress envoie le reçu de la transaction. L'ancienne adresse de
webhook répond
403à une livraison qu'elle refuse. - Documentation : un
callbackmobile doit être un App Link ou Universal Link en https. Les pages Components documententisOpen(), les hauteurs des champs, les types de champs et leurs propriétés, avec des exemples qui compilent.
2026-10-11
NOUVEAU API
Nouvelle version datée de l'API : 2026-10-11, avec un changement cassant : le status d'un
paiement affiche refunded ou partially_refunded une fois des remboursements réussis, et
GET /payments?status= filtre sur cette lecture ; un paiement remboursé n'est donc plus listé sous
succeeded. Envoyez X-Wajub-Version: 2026-09-01 pour continuer à lire succeeded.
Ce que dit le statut du paiement
Votre compte ne bouge pas. Tous les comptes existants sont désormais fixés sur 2026-09-01, et un
nouveau compte est fixé sur la version en vigueur à sa création. Jusqu'ici un compte ne portait
aucune version et suivait celle de la plateforme : une nouvelle version l'aurait atteint le jour de
sa sortie. Les webhooks restent mis en forme pour la dernière version, quelle que soit celle de
votre compte. Gestion des versions
API Sync Shield Konsole
- Un litige que vous acceptez ou clôturez pèse moins sur la réputation du payeur qu'un litige
tranché contre vous. Le litige porte désormais
metadata.resolutionàaccepted. Score de risque POST /beneficiaries/{id}/verifyinterroge désormais l'opérateur pour tous les comptes. Hors Sync Relay, les vérifications faites avant cette version n'atteignaient pas l'opérateur : vérifiez de nouveau tout bénéficiaire dont le nom compte pour vous. Sur vos propres bénéficiaires, la réponse est une information : l'appel répond200avecverification(verified,name_mismatchoulookup_unavailable) etregistered_name, le nom que détient l'opérateur, et le bénéficiaire reste payable quel que soit le résultat. Une clé sandbox obtient toujourslookup_unavailable: la sandbox n'a pas d'opérateur. Sur un compte Relay, l'appel reste une barrière et ne renvoie aucun nom. Un compte de versement ajouté dans le Dashboard ne peut plus être vérifié par cet appel. Vérifier le nom d'un portefeuille- Documentation : une
Idempotency-KeysurPOST /payments,/transfers,/transfers/batchet/refundsn'expire jamais ; seule la réponse enregistrée dure 24 heures. Une clé réutilisée pour autre chose répond201avec l'ancienne ressource et ne fait rien. Idempotence - La page Couverture marque désormais « bientôt disponible » les rails qu'aucun prestataire connectable ne porte encore : Égypte, Algérie, Maroc, Tunisie, Sierra Leone, OPay et PalmPay au Nigeria, et la crypto. Couverture
- SDK mobiles : Flutter et React Native 1.4.0, Android 1.2.0. Cartes par un prestataire qui les
collecte sur sa propre page (Paystack, Flutterwave, PayPal, Kkiapay, FedaPay, CinetPay) et
portefeuilles en un geste comme Djamo. Un paiement Mobile Money revient comme une action à
approuver,
push_approval. SDK mobiles - Shield : Always allow customer sur un examen est ouvert à tous les plans. Une tentative bloquée par Shield figure dans votre file d'examen, et autoriser le client laisse passer son prochain paiement, sauf s'il figure dans votre liste de blocage ou correspond à une liste de sanctions. Shield, lists affiche les clients autorisés et permet d'en retirer un. Le blocage ou le remboursement depuis un examen, les règles personnalisées et la liste de blocage restent réservés à Shield Advanced. Règles
- Une facture récurrente produit désormais ses copies : la prochaine est due un intervalle après
invoice_date, jamais dans le passé. Chaque copie est un brouillon ordinaire, généré une seule fois par cycle, qui conserve la remise globale ; elle reste à envoyer et à payer. Les dates de début et de fin du Dashboard sont maintenant appliquées. Une facture marquée récurrente auparavant reste inactive tant que sa récurrence n'est pas enregistrée de nouveau. Factures récurrentes - Konsole : désactiver ou réactiver un endpoint webhook depuis son formulaire prend désormais effet.
- Konsole : le secret de signature d'un nouvel endpoint est affiché une fois à sa création, Reveal fonctionne sur la page de l'endpoint, et Promote to Live crée l'endpoint live et affiche son secret une fois.
- Konsole : la recherche dans les logs d'API retrouve un appel par son
X-Request-Id, en live comme en sandbox. L'export JSON contient les enregistrements complets, et les exports des logs et des événements appliquent désormais les filtres affichés. - Konsole : nouveaux filtres sur l'endpoint (logs d'API), la catégorie et le statut de livraison (événements) et le prestataire retenu (journal de routage).
- Konsole : renvoyer une livraison dont l'endpoint a déjà accepté l'événement est refusé et n'est pas décompté de vos Répétitions de webhooks par mois. Sans ligne cochée, la relance groupée prend les livraisons échouées de la dernière heure, des 24 dernières heures ou des 7 derniers jours. Testeur de webhooks
- Vue d'ensemble de Konsole : Diagnose est proposé sur les cartes d'authentification, de latence et d'endpoint. « Clé d'API inutilisée » surveille vos clés d'API, et « Secret de signature de plus de 6 mois » compte depuis le dernier renouvellement.
- Les logs d'API masquent moins de champs anodins et affichent un préfixe de clé plus long. Explorateur de logs
POST /beneficiaries/{id}/verifya son propre plafond sur tous les plans : 10 vérifications par minute et 200 par jour et par compte en live, 10 par minute en sandbox. Au-delà, la réponse est429. Limites- Konsole ne propose plus
payment.checkout_page_openedetpayment.redirected_to_callbackpour un endpoint webhook : ils ne sont jamais livrés. Un endpoint qui en liste un le garde, sans effet. Événements webhook - Vous pouvez arrêter une facture récurrente quel que soit son statut, payée comprise :
POST /invoices/{id}/stop-recurring, ou Arrêter la récurrence dans le menu d'actions de la facture. Les copies déjà générées restent. L'objet facture porte désormaisnext_invoice_date, la date de la prochaine copie, etrecurring_parent, la facture récurrente dont une copie a été générée. Arrêter une récurrence refund.updatedest désormais livré, et un endpoint peut s'y abonner. Qui envoie un remboursement live- Un remboursement dans une devise à trois décimales comme le TND garde toutes ses décimales : un
remboursement complet ou un litige accepté aboutit. Dans une devise sans subdivision comme
le XAF, la part des frais et
payer_amountsont des nombres entiers. Qui supporte les frais - Avec
X-Sync, une plateforme ne voit que les clients que sa connexion a créés ou utilisés. Un paiement est créé sans aucun autre client, et leur identifiantcus_est traité comme inconnu.DELETE /customers/{id}répond403: effacer un client est une décision du marchand. Types de compte DELETE /customers/{id}retire désormais aussi les coordonnées du client des factures, des adresses d'un paiement, des corps des livraisons de webhook (et de leurs relances), des copies reçues par une plateforme Sync, des statistiques et de la recherche. Un appel répété termine un effacement qu'un appel précédent a laissé inachevé. Supprimer un payeurPOST /events/{id}/resendlivre de nouveau aux endpoints qui n'ont pas accepté l'événement.- Avec
X-Sync, uneIdempotency-Keyappartient à la connexion, et accepter ou clore un litige est refusé une fois les paiements de la connexion suspendus. - Une règle personnalisée sur
ip_countryne lit qu'une adresse du payeur vérifiée. Si vous utilisez votre propre checkout - Relancer un lot de payouts avec la même
Idempotency-Keyrenvoie les lignes déjà parties, même quand l'heure n'a plus de place. Limites POST /beneficiaries/{id}/verifyrend payable un bénéficiaire resté non vérifié quand les noms correspondent. Vérifier le nom d'un portefeuille- Un paiement envoyé en examen parce que le nom du payeur est proche d'une liste de sanctions apparaît dans Shield, Reviews même quand Shield est désactivé. Score de risque
- Une copie récurrente générée reste un brouillon tant que vous ne l'envoyez pas, même après son
échéance ; une copie passée
overduesans avoir été envoyée redevient un brouillon. Une série désactivée puis réactivée reprend après sa dernière copie, l'annulation effacenext_invoice_date, et un devis, une estimation ou une copie générée ne peut pas devenir récurrent (422). Dupliquer une facture récurrente donne un simple brouillon. Factures récurrentes - Konsole : Rotate sur la page d'un endpoint remplace son secret de signature, après votre mot de passe, et affiche le nouveau une seule fois. Testeur de webhooks
- Les webhooks sont toujours mis en forme pour la version actuelle de l'API, quelle que soit la version de l'appel qui les déclenche.
API Paiements Factures Sync Dashboard
POST /payments/{id}renvoie désormais ce dont l'étape suivante du payeur a besoin : un202qui nomme une étape dansactionporteaction_url,otp_idetotp_masked_contact, les identifiantspin,phone,birthdayetaddress, etclient_session.crypto.depositest un champ de la sandbox. Quandactionest renseigné- Wave (
ci.wave,sn.wave), Express Union (cm.eu) et M-Pesa (ke.mpesa,tz.mpesa,mz.mpesa) peuvent être débités en live. Wave et Express Union acceptent tout numéro. M-Pesa accepte un numéro Safaricom au Kenya et un numéro Vodacom en Tanzanie et au Mozambique, etmobileou un agrégat de pays envoie un tel numéro sur M-Pesa. Les autres canaux n'acceptent qu'un numéro de leur propre opérateur. Laisser Wajub trouver l'opérateur - Un paiement créé avec
acceptpeut être débité surmobileou sur un agrégat de pays commecm.mobile. La restriction est vérifiée sur l'opérateur que donne le numéro, et un numéro qui sort de ce que le paiement accepte est refusé. Choisir ce qu'un paiement accepte - Une page numérotée d'une liste porte désormais
next_cursorethas_moredansmeta, à côté des compteurs de pages. Envoyez cenext_cursorcommecursoret le parcours continue juste après le dernier élément de la page. Sur toutes les listes qui acceptent un curseur ;GET /invoicesetGET /linkstriés avecsort_byrestent paginés par numéro. Avec le SDK PHP,getNextPage()etautoPagingIterator()suivent ce curseur à partir de la deuxième page : mêmes éléments, mais lemetade ces pages n'a pluscurrent_page,last_pagenitotal. Pagination - Un fichier joint à un message de litige avec
POST /disputes/{uid}/messagesest désormais enregistré. Envoyer un message - Une facture sans
customer_emailnicustomer_idpeut maintenant être payée : sa page demande un e-mail au payeur, utilisé pour le paiement et sa confirmation. Sur cette page, l'e-mail que vous avez mis sur la facture est toujours conservé. Démarrage rapide des factures - Un paiement en ligne sur une facture s'ajoute à ce que vous avez enregistré avec
mark-paid. Enregistrer un paiement encaissé ailleurs - Sync : un sous-compte accepté n'affiche jamais
expired.expires_atest la date de l'invitation ; elle est effacée quand le marchand accepte, y compris sur les connexions déjà acceptées, et les paiements d'une connexion acceptée passent. Le Dashboard redemande l'accord du marchand avant un changement de tarif. Onboarding - Sync : chaque événement
account.*envoyé par l'API désigne sa connexion dansdata.account, l'identifiantacc_….account.deauthorized,account.payment_activatedetaccount.payment_suspendedgagnent cette clé ;data.idn'est pas toujours la connexion. Événements webhook - Clés API, Dashboard : la date d'expiration d'une clé se fixe à la création, se change ou se retire sur une clé privée ou restreinte, et s'affiche à côté de la clé. Modifier autre chose la conserve. La liste d'IP autorisées accepte les adresses IPv4 et IPv6 et les plages CIDR des deux familles, à la création comme à la modification, et une entrée IPv6 correspond quelle que soit son écriture. Environnements et clés
- Orchestration : l'assistant de connexion d'un fournisseur pré-remplit la priorité
0, la valeur documentée, au lieu de50. Les connexions existantes gardent leur priorité. Fournisseurs - Playground de la documentation : Tester cet endpoint fonctionne une fois connecté, en sandbox uniquement. Référence de l'API
- Documentation : le
callbackd'une connexion Sync est la page sur laquelle le marchand revient, pas l'adresse des événements. Ceux-ci vont à vos endpoints de webhook, etaccount.connecteddemande un abonnement par son nom. Capacités des comptes - Documentation : la référence de
POST /beneficiariesexigechanneletnameet n'a pas detype;POST /transfersdécrit lebeneficiaryen ligne (nameetchannelobligatoires, pas debank_code) et précise quereferencen'est jamais contrôlée pour l'unicité, seuleIdempotency-Keyprotège une relance ; lecompleted'un transfert n'esttrueque sursucceeded; l'objet Event listeevent,created,livemode,pending_webhooks,api_versionetrequest. Transferts, Événements - Documentation : le démarrage rapide Tax utilise maintenant
inclusive: true, car il débite le total calculé. Avecinclusive: false, un paiement de 11 925 XAF enregistrait 2 296 XAF de taxe au lieu de 1 925. Si vous avez suivi l'ancienne version, passezinclusiveàtrue; les enregistrements passés ne sont pas recalculés. Démarrage rapide Tax - Documentation : le conseil de garder cinq à dix appels simultanés est remplacé par un débit par
minute sous le plafond de chaque ressource pour votre plan (24 appels par minute sur
/paymentsen Pay as you go, où le plafond est de 30), avec un exemple qui attend leRetry-After. Performances - Documentation : dans le démarrage rapide Payment Links, les champs supplémentaires se décrivent
avec
nameettype, et nonkey. Le premier exemple de la page d'accueil des Components envoieemail; sans contact du payeur, l'API répond422. Le cookbook marketplace Django crée la connexion avecwithdrawals, enregistre lepayout_phonequ'utilise son exemple de retrait et lit la connexion dansdata.account. Démarrage rapide Payment Links, Marketplace Django
Components SDK CLI Plugins
- Wajub.js 1.6.0 : la
localepassée àmount(),open(),checkout()oucomponents()est désormais la langue d'ouverture du checkout ou du champ. Checkout hébergé - Wajub.js 1.6.0 : un checkout hébergé dont la session ne se charge pas appelle
onLoadErroravecsession_not_foundousession_terminal_expired. Il appelaitonError: déplacez ce traitement dansonLoadError. Référence de l'API - Wajub.js 1.6.0 :
checkout.submit()appuie sur le bouton de paiement du moyen en cours.unmount()retire le checkout hébergé en conservant l'instance,mount()le remet, en ligne et en superposition. Référence de l'API @wajub/vueet@wajub/svelte1.6.0 :useWajubOptional()renvoie une ref (Vue) ou un store (Svelte) qui suit le chargement du runtime. Lisezruntime.valueou$runtime.@wajub/sveltefonctionne dès le premier rendu, avec Svelte 4 comme Svelte 5. Vue, Svelte- SDK PHP 2.0.1 :
create(),retrieve()etupdate()surtransfers,beneficiaries,links,invoices,accountsetwebhookEndpointsne lèvent plusCannot instantiate abstract classaprès l'envoi de la requête. Si untransfers->create()a échoué ainsi en 2.0.0, le transfert a bien été créé : vérifiez avant de le renvoyer. SDK PHP - SDK Python 1.2.1 : le package sur PyPI contient de nouveau le module. Les versions 1.1.0 et
1.1.1 installaient un wheel vide. Installez avec
pip install "wajub>=1.2.1". SDK Python - SDK Ruby 1.3.0 :
customers.delete_tax_idappelleDELETE /customers/{id}/tax_ids/{tax_id}. SDK Ruby payments.initialize, alias decreate, n'existe plus dans les SDK Node.js et C# (2.0.0), ni dans Python, Go et Java (1.2.1) et Ruby (1.3.0). PHP le conserve. Appelezcreate. SDK- Les exemples SDK des pages transferts, solde, bénéficiaires, liens de paiement, factures et litiges correspondent aux signatures réelles de chaque SDK. La preuve de litige avec fichier est présentée comme une requête multipart.
- SDK React Native 1.4.1 :
watchStatus()renvoie le statut quand le temps réel est activé, et le polling tourne pendant tout le suivi. SDK Android 1.2.1 :watchStatus()ouvre la connexion temps réel et garde le polling à côté. SDK mobiles - CLI 1.7.2 :
wajub trigger --channelpaie avec un numéro sandbox de l'opérateur du canal,--channel ci.orangecompris. Déclencheurs - Plugin WordPress 1.2.1 : un client qui revient de la page de paiement trouve sa commande dans
l'état de son paiement (WooCommerce, GiveWP) ; les remboursements lancés depuis WordPress sont
acceptés ; un remboursement fait dans le Dashboard arrive dans WooCommerce ;
[wajub_pay_content]se débloque. WordPress
2026-10-10
API Orchestration Sync Tax Shield Webhooks Components CLI
- Les appels Sync et Tax demandent le produit dans votre plan ou en option : sans lui,
/accounts, tout appel portantX-Syncet/taxrépondent403avecerror_code: feature_not_in_plan. Sync · Tax - Un endpoint webhook live doit utiliser
https://: en créer un enhttp://, ou en pointer un vers une URLhttp://, répond422. Les endpoints sandbox acceptent toujourshttp://. Les endpoints live déjà enhttp://conservent leurs livraisons, et Konsole les signale. Webhooks customer_idsurPOSTetPUT /invoicesattend l'identifiantcus_du client. FacturesPUT /accounts/{id}répond409avecerror_code: merchant_not_verifiedquand il passepayment_statusàactivepour un marchand dont la vérification n'est pas approuvée. Onboarding- Avec
X-Sync, une plateforme n'atteint que ce que la connexion a apporté. Les litiges sont ceux de ses paiements ; les liens, factures et bénéficiaires sont ceux qu'elle a créés, et un versement ne va qu'à l'un de ces bénéficiaires ;GET /eventsliste les événements de tout cela, etPOST /events/{id}/resendenvoie à vos propres endpoints. Le reste répond404./balance,/webhooks,/shield,/taxet/listenrépondent403avecX-Sync. Un paiement sur un lien ou une facture de la connexion porte la connexion, et il est refusé dès que la connexion ne peut plus encaisser.write,settings,subscriptionsetanalyticsne sont plus des capacités : en demander une répond422. Types de comptes DELETE /customers/{id}anonymise et supprime le client ; si une partie échoue, il répond500et ne change rien.customer.deletedporte la fiche anonymisée et n'est plus suivi decustomer.updated. Les coordonnées du client sont retirées des événements déjà enregistrés, un appel répété répond200au lieu de404, et la copie archivée est supprimée après 120 jours. Supprimer un payeur- La vélocité horaire des payouts ne compte que les payouts acceptés : un payout refusé, faute de fonds ou par le plafond lui-même, n'occupe aucune des six places, et le réessayer ne prolonge pas l'attente. Un lot occupe une seule place quel que soit son nombre de lignes ; chaque ligne ajoute tout de même son montant au montant horaire. Limites
- Sur un débit fait avec une clé secrète, faites noter l'IP du payeur : appelez
Wajub.signals()(Wajub.js 1.6.0) dans le navigateur du payeur et transmettez le résultat dansdata._client. Sontokenatteste l'adresse du payeur. Si vous utilisez votre propre checkout - Un payeur dont le nom est proche d'un nom sous sanctions, sans l'être, part désormais en revue
quel que soit le score. Vous pouvez choisir de le
refuser, avec
sanctions_near_match_actionsurPUT /shield/settingsou dans Shield, Risk controls. Une correspondance exacte reste toujours refusée. Notation du risque - Un paiement passe désormais à votre prestataire suivant quand le premier répond que le chemin est en panne : l'opérateur a dépassé son délai ou est indisponible, vos identifiants sont refusés, ou ses fonds de roulement sont épuisés. Un refus qui concerne le payeur s'arrête toujours là. Ce qui arrête la cascade
- Un remboursement live dit qui l'envoie :
execution_mode(automatic,merchantoumanual) et, quand il n'est pas envoyé automatiquement,manual_reasonavec uncodestable et unmessage.refund.updatedpart quand l'un des deux change. Un remboursement encoreprocessingcompte dans ce qui reste à rembourser. Qui envoie un remboursement live - Vous choisissez qui supporte les frais Wajub d'un paiement quand vous le remboursez :
fees_bearersurPOST /refundset dans le formulaire de remboursement du Dashboard, avec une valeur par défaut dans Settings, Refunds.merchantrend au client tout ce qu'il a payé pour la part remboursée,customerlui laisse la part des frais. Le remboursement portefee_amountetpayer_amount, et votre solde est débité depayer_amount. Rien ne change tant que vous ne le réglez pas : les frais restent à celui qui les a payés. Qui supporte les frais - Un paiement créé avec
beareràcustomerne vous coûte pas de frais : ils sont pris une fois, chez le payeur, et aucunfee.chargedn'est émis pour ce paiement. La sandbox fait de même. Qui paie les frais - Accepter ou clore un litige par l'API rembourse désormais le payeur :
POST /disputes/{id}/acceptet/closecréent un remboursement du montant contesté avec le motifcustomer_complaint. Ce remboursement ne vous débite pas une seconde fois. Une rétrofacturation, que la banque du payeur a déjà remboursée, n'est pas remboursée en plus, ni par l'API ni par le Dashboard.dispute_settlementest une clé réservée dans lemetadatad'un remboursement. Concéder - Wajub Components :
fetchSession()fonctionne depuis le site de n'importe quel marchand. Sessions js.wajub.comenvoie désormaisAccess-Control-Allow-Origin: *: importerwajub.mjscomme module fonctionne. Wajub.js- CLI 1.7.1 :
wajub logoutretire aussi la clé deconfig.json.bak. Supprimez toutconfig.json.baklaissé par une version antérieure. Déconnexion
2026-10-09
NEW Payments Components
deferred: truesurPOST /paymentsprépare un paiement pour des champs de paiement affichés avant que la commande existe : pas de transaction, pas depayment.createdet aucune ligne dans vos paiements avant quePOST /payments/{id}/activatele crée avec le total final et le client. Avant que la commande existePATCH /payments/{id}modifie le montant et la devise d'un paiement préparé tant que le checkout est ouvert, sans remonter les champs. Modifier un paiement préparé- Wajub Components :
variant: 'fields'intègre les champs d'un composant dans votre propre bloc de moyen de paiement, etfields.countryetfields.operator: 'detect'retirent les listes de pays et d'opérateurs du Mobile Money. ÉgalementonBeforeSubmit,fields.customer: 'external', et les composantsbankTransferetcrypto. L'environnement d'exécution servi depuisjs.wajub.comles lit,@wajub/js1.5.0 ajoute leurs types, et@wajub/vueet@wajub/svelte1.5.1 transmettentvariant. Dans votre propre bloc de moyen de paiement
Orchestration
- Le routeur applique d'abord l'instruction la plus précise : les connexions désignées par vos
règles de routage correspondantes, chacune suivie du secours de la règle, puis la politique du
canal, ou la
priorityde la connexion sur un canal sans politique. Orchestration des paiements - Les règles de routage appliquent désormais leur poids et leurs conditions avancées : fenêtres
horaires, segments clients, filtres de métadonnées et plafonds de fréquence. Une règle supprimée
ne route jamais. Un filtre de métadonnées
inprend des valeurs séparées par des virgules, eteqetincomparent le texte des valeurs :100saisi dans le Dashboard correspond à une valeur numérique. Règles de routage - Les frais fixes d'une connexion sont convertis de votre devise de base dans la devise du paiement avant que le routeur compare les coûts.
- L'ordre de cascade, l'objectif et les garde-fous d'une politique de canal ordonnent les connexions qu'aucune règle n'a placées. Un garde-fou recule une connexion, il ne refuse jamais un paiement.
- Le simulateur de routage de la page Règles de routage exécute le vrai routeur, à blanc.
- Une carte saisie dans les champs propres à un prestataire n'est débitée que par ce prestataire, et ne bascule jamais. Un refus Stripe est définitif et renvoie le code de refus de Stripe.
- Une connexion sans identifiants est ignorée : la suivante est essayée. Une clé manquante ou refusée est signalée sur la connexion, et votre équipe en est avertie par e-mail. Cascade et repli
2026-10-03
CLI
- CLI 1.7.0 :
wajub completionremplacewajub autocomplete. Lancezwajub completion installune fois ;wajub autocompletereste un alias, et un shell configuré par lui continue de compléter après la mise à jour. La complétion couvre désormais les valeurs (statuts, types d'événements, chemins d'API, profils), fish et le bash fourni avec macOS. CLI - CLI 1.6.1 : la première version publiée avec les sessions d'écoute (la 1.6.0 n'a jamais atteint npm).
2026-10-02
CLI
- CLI 1.6.0 :
wajub listenpasse par des sessions d'écoute, et votre handler reçoit chaque livraison exactement comme la production l'envoie. Le CLI 1.5.0 et les versions antérieures ne peuvent plus écouter : leurwajub listens'arrête et demande une mise à jour (npm install -g @wajub/cli@latest). Toutes les autres commandes des anciennes versions continuent de fonctionner. Listen - CLI 1.5.0 : les Agent Skills sont copiées dans
~/.agents/skillset~/.claude/skillsà la première commande après une installation ou une mise à jour, sanswajub login. Désactivez-le avecWAJUB_NO_SKILLS=1.
2026-09-19
API Payments
- La limite de requêtes est désormais le plafond par minute de votre plan, partagé par toutes vos clés, avec une part plus petite pour les paiements, les payouts et quelques autres routes, et aucun plafond sur Enterprise, sauf pour les écritures de payout (création de bénéficiaires, de transferts et de lots), plafonnées à 20 par minute sur tous les plans. Limites de requêtes
- Une rétrofacturation ouverte chez un prestataire vous parvient désormais sous forme de litige,
avec son échéance dans
due_date.
2026-09-17
NOUVEAU Payments Transfers Sync
- En live, les données de carte brutes envoyées à
POST /payments/{id}sont refusées. - Créances :
POST /beneficiaries/{id}/receivablesenregistre ce qu'un vendeur déjà payé vous doit, et une ligne de payout groupé peut le reprendre en premier. Nouveaux événementsbeneficiary.receivable_recordedetbeneficiary.receivable_recovered. - Payouts vers un compte Wajub.
- Sync :
account.change_requestedquandPUT /accounts/{id}propose de nouvelles conditions, etaccount.commission_receivable_recordedetaccount.commission_receivable_collectedpour une commission qui n'a pas pu être prélevée à la source.
2026-09-16
NOUVEAU Transfers Sync
POST /transfers/batch: jusqu'à 500 payouts en un appel, avec uneIdempotency-Keyobligatoire.- Les comptes Sync reçoivent un mode, Lite, Direct ou Relay, et
POST /accounts/{id}/payoutspaie un marchand Lite, en live uniquement. - Les webhooks d'onboarding envoyés à une plateforme Sync s'appellent désormais
account.onboarding_started,account.onboarding_email_verified,account.onboarding_account_selected,account.onboarding_kyc_submittedetaccount.connected, et on peut s'y abonner. Catalogue des événements
2026-09-15
Webhooks API Transfers
- Nouvelles tentatives des webhooks : toute livraison en échec, sauf un
410, est retentée avec une attente progressive, pendant 72 heures au plus. Auparavant, il y avait cinq tentatives sur environ seize minutes, et un4xxn'était jamais retenté. Nouvelles tentatives - Idempotence : la réponse enregistrée est renvoyée avec
Idempotent-Replayed: true, une seconde requête arrivée pendant que la première s'exécute reçoit un409, et la même clé avec un autre corps reçoit un422. Idempotence - Payouts par virement bancaire.
SDK
- SDK PHP 2.0.0, avec des changements cassants : il demande PHP 8.4 ;
update()etdelete()sont retirés derefundsettransfers, que l'API n'a jamais eus ;tax->reports()renvoie l'objet rapport,shield->addToBlocklist()la liste de blocage mise à jour, etlisten->config()etlisten->auth()déballent leur enveloppe. La pagination par curseur est suivie pargetNextPage()etautoPagingIterator(). SDK PHP
2026-09-11
Payments Transfers CLI
- Portefeuilles Djamo, pour les paiements et pour les bénéficiaires.
DELETE /keys/currentrévoque la clé créée parwajub login.wajub logoutl'appelle.
2026-09-07
Transfers
- Ajout du canal
sn.wavepour les transferts au Sénégal.
2026-09-01
NOUVEAU API
Nouvelle version datée de l'API : 2026-09-01, avec un changement cassant : ledger_balance_before
et ledger_balance_after sont retirés de l'objet transfert. Envoyez X-Wajub-Version: 2026-08-01
pour les conserver. Gestion des versions
L'API a accepté cette version à partir du 10 septembre : avant cette date,
X-Wajub-Version: 2026-09-01 répondait 400.