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-23
Sync Webhooks
- Nouvel événement
account.onboarding_declined: le marchand a refusé la connexion dans l'onboarding hébergé. Rien n'est connecté et le lien d'invitation reste valable ;reasoncontient ses mots quand il en a donné. Comme les autres événements des étapes du marchand, il n'atteint qu'un endpoint abonné à son nom. Comptes, pour les plateformes Sync
2026-10-17
CASSANT Sync
Un changement sur toutes les versions d'API à la fois : il n'est pas lié à une version datée, et
X-Wajub-Version ne conserve pas l'ancien comportement. Il concerne les livraisons Sync qui portent
X-Sync-Event, celles des étapes du marchand lui-même, et le retour vers votre page.
- Cassant pour une plateforme qui vérifie
X-Sync-Signature: ces livraisons ne le portent plus. VérifiezX-Sync-Signature-V1avecX-Sync-Timestamp, comme le faitconstructEventdans les SDK. Vérification de la signature - Cassant pour une plateforme qui lit
sync_uid: ces livraisons désignent la connexion dansaccountseulement, l'identifiantacc_…, et ne portent aucun identifiant interne de Wajub pour la connexion, la plateforme ou le marchand.account.onboarding_startedne porte plus l'adresse depuis laquelle le marchand a ouvert le lien. Livraisons du cycle de vie Sync - Cassant pour une plateforme qui lit
sync_idsur sa page de retour : le marchand revient avecaccount,stateetstatusseulement. Retour sur votre page - Seul un
2xxvaut livraison : une redirection n'est pas suivie et compte comme un échec. Chaque tentative part vers l'endpoint tel qu'il est à ce moment, signée avec son secret actuel, et un endpoint désactivé ou supprimé entre-temps ne reçoit plus rien.
API Webhooks Konsole
- Les renvois manuels de webhooks ne sont plus décomptés d'un quota mensuel, sur aucun plan. Un même
événement repart vers le même endpoint au plus une fois toutes les 5 minutes, depuis Konsole ou
avec
POST /events/{id}/resend. L'appel ignore un endpoint encore dans ce délai, et répond429avecerror_code: event_resend_cooldownet un en-têteRetry-Afterquand c'est le cas de chaque endpoint qui n'a pas accepté l'événement. Un 429 qui n'est pas une limitation - Konsole : Renvoyer dans ce délai indique combien de minutes il reste, et Relancer les livraisons échouées ignore ces livraisons et les compte dans son message. Testeur de webhooks
Link Orchestration
- Le webhook propre à un lien de paiement ne compte comme livré que sur un
2xx: toute autre réponse, une redirection comprise, est enregistrée comme échouée et retentée, et une redirection n'est jamais suivie. Son envoi de test indique seulement si l'endpoint l'a accepté. Dans le Dashboard - La cible Slack ou webhook d'une règle d'alerte doit être une URL
httpsqui ne pointe pas vers une adresse privée ou interne : Wajub n'envoie rien à une autre, et ne suit aucune redirection qu'elle renvoie. Alertes
CASSANT API
Un changement sur toutes les versions d'API à la fois : il n'est pas lié à une version datée, et
X-Wajub-Version ne conserve pas l'ancien comportement.
- Cassant pour une intégration qui fabrique ou modifie un
cursor: une liste n'accepte qu'unnext_cursorou unprev_cursortel qu'une réponse l'a renvoyé. Toute autre valeur, un curseur fait à la main ou modifié compris, renvoie un422surcursor. Un curseur renvoyé avant ce changement est encore lu jusqu'au 2026-11-13. Pagination par curseur - Cassant pour une intégration qui envoie à
GET /balanceune devise que Wajub ne sait pas convertir :currencyaccepte la devise de votre compte, ou une devise pour laquelle Wajub a un taux de change, en majuscules ou en minuscules. Tout autre code renvoie un422surcurrency. Solde - Cassant pour une plateforme qui distingue
403et404avecX-Sync: une connexion qui appartient à une autre plateforme répond404 Sync account not found., comme un identifiant qui n'existe pas. Clés et accès
API
- Une clé restreinte (
rk.ourk_test.) utilisée depuis un navigateur déclenche la même alerte de sécurité qu'une clé secrète : le propriétaire du compte et les administrateurs reçoivent un e-mail. Pour l'instant, la requête aboutit encore ; Wajub la refusera plus tard avec le même403, déplacez donc ces appels vers votre serveur. Les clés privées sont bloquées dans le navigateur
2026-10-16
CASSANT API
La version d'API 2026-10-12, celle des nouveaux comptes, apporte aussi ces changements. Les
versions antérieures gardent l'ancien comportement, et les webhooks suivent la version actuelle,
2026-10-11.
- Un paiement n'a plus
theming. Les versions antérieures lisent toujours la clé,nullsur un paiement créé à partir de maintenant. POST /webhooksetPUT /webhooks/{id}vérifient chaque type deeventsdans le catalogue des événements : un type qui n'existe pas, mal orthographié ou un préfixe commepayment.*répond422surevents.N.*prend toujours tous les types, et un endpoint garde les types qu'il a déjà. Endpoints de webhook- Une entrée de la liste de blocage Shield ne porte plus
team_id. Shield - Les
itemsd'un paiement fait sur la page d'une facture se terminent par la remise sur toute la facture, quand il y en a une : un élément aveckind: discount,name: Discount, untotalnégatif, etquantityetunit_priceànull. L'objet Payment
API Paiements
DELETE /payments/{id}répond409quand le paiement ne peut pas être annulé maintenant :error_code: payment_in_progresspendant qu'un débit est en cours, le payeur le validant sur son téléphone ou payant sur la page du prestataire, etpayment_partly_paidsur un paiementpartialou dont des échéances sont payées, à clôturer avecPOST /payments/{id}/close. Un paiementprocessingsans rien en cours peut être annulé, de même qu'un paiement dont l'expires_atest passé sans qu'il ait encore expiré. Annuler un paiement- De deux débits envoyés en même temps sur un paiement, le second répond
409 payment_in_progress. Un paiement dont le débit est encore en cours quandexpires_atpasse attend l'issue de ce débit avant de pouvoir expirer, et en live un débit sur un paiement dont l'expires_atest passé répond400. Expiration - Certains opérateurs, comme Orange Money au Burkina Faso, n'acceptent un paiement qu'avec un code
que le payeur génère d'abord. Le débit répond alors
202avecaction: payer_otpet, danspayer_otp, comment obtenir le code : débitez de nouveau avec lui dansdata.otp. Après trois codes refusés, le débit répond402 otp_attempts_exceeded. En sandbox,bf.orangedemande le code et accepte123456. Un code que le payeur génère - L'objet paiement renvoie
clientà une clé secrète ou restreinte : d'où le payeur a payé, la page de paiement hébergée, Wajub.js, un SDK mobile ou une autre application, telle qu'elle se déclare, avec sa version et sa plateforme quand elles sont connues. L'objet Payment POST /paymentsne conserve plustheming, sur toutes les versions : le champ est ignoré, jamais refusé.otp_masked_contactne contient plus que le contact masqué, comme080******78, et il est vide quand le prestataire n'en nomme aucun.GET /payments/optionsdonne à chaque canal et à chaque opérateurlogo_png, son logo en PNG. Prévisualiser les moyens- Pour un débit, un numéro Mobile Money peut commencer par
00au lieu de+. Le 0 qui fait partie d'un numéro en Côte d'Ivoire, au Bénin, au Congo et au Burkina Faso est conservé, et les renumérotations du Bénin et du Gabon se lisent sous leur nouvelle forme. Formats de numéros de téléphone - Sandbox : les numéros à dix chiffres du Bénin (
+2290190…,+2290191…,+2290197…) et les blocs actuels du Gabon (+24174…,+24177…,+24162…,+24165…,+24166…) ont des numéros de test, et00peut remplacer+. Scénarios de test
API
POST /accounts,POST /tax/registrations,POST /customers/{id}/tax_idsetPOST /disputes/{id}/messagesrespectentIdempotency-Key: un appel répété répond ce qu'a répondu le premier, pendant 24 heures. Idempotence- Un chemin qui encode une barre oblique ou une barre oblique inverse,
%2Fou%5C, répond404. Forme d'une erreur - Le
customerd'un litige est l'identifiantcus_du client, même une fois ce client supprimé, et satransactionl'identifianttrx_du paiement. L'un ou l'autre est omis quand il n'y en a pas. - Sur les versions antérieures à
2026-10-12, un canal deGET /channelsetGET /providersindique la devise dans laquelle il paie, ounullpour un canal qui ne paie pas dans une seule devise, comme une carte ou un actif crypto, au lieu deXAFpour chaque canal. Couverture
API Link
single_use_link: trueferme un lien après son premier paiement réussi et n'y laisse payer qu'un payeur à la fois : un autre payeur apprend qu'un paiement est en cours, et le lien rouvre si ce paiement n'aboutit pas. Un remboursement ne le rouvre pas. Si un second paiement aboutit malgré tout, le propriétaire, les administrateurs et les membres finance de votre équipe reçoivent un e-mail qui nomme le paiement à rembourser. Un lien qui avait déjàsingle_use_linkse ferme désormais après son premier paiement, sauf celui d'un produitdigital, dont le réglage devientsingle_use_access. Comment un lien se fermesingle_use_access: true, pour un produitdigital, permet à chaque acheteur de télécharger le fichier une seule fois ; le lien reste ouvert à l'acheteur suivant. L'acheteur télécharge par un lien propre à son paiement, jamais par l'adresse du fichier lui-même, et un remboursement total arrête le téléchargement.file_urlsurPOST /linksprend une adresse à vous : un fichier téléversé dans le Dashboard répond422. Produits numériques- L'URL de réunion d'un service parvient au payeur dans l'e-mail de confirmation de son paiement, avec ce qu'il faut préparer, et n'est plus sur la page avant le paiement.
link.expiredest envoyé une fois, dans la journée qui suit le passage de l'expiry_dated'un lien, sauf si le lien est archivé entre-temps, avec le lien dansdata, aux endpoints qui s'y abonnent, etGET /events?type=link.expiredle liste. Catalogue des événements
API Factures
- Les remises sur les lignes sont déduites du
subtotal, dutotalet duamount_dued'une facture, et une remise ne peut plus faire passer une ligne sous zéro :422suritems.N.discount_value. Les factures ouvertes qui ont une ligne remisée sont remises en cohérence, ce qui peut baisser leurtotalet leuramount_due, jamais augmenter ceux d'une facture déjà envoyée, et fait passer àpaidune facture déjà payée à hauteur de son nouveau total, avecinvoice.updatedetinvoice.paid. Calcul d'une ligne - Les
itemsd'un paiement fait sur la page d'une facture donnent à chaque ligne sontotal, net de sa remise et taxe comprise, sur toutes les versions. L'objet Payment global_discount_typeetglobal_discount_valuedéduisent une remise de toute la facture, qui les renvoie avechas_global_discount. Le reçu et la confirmation de paiement l'indiquent après les lignes. Une remise sur toute la facture- Les devis et les estimations créés avec
POST /invoicesse lisent, se corrigent, s'annulent et se suppriment par leurid, etGET /invoices?document_type=quoteouestimateles liste./sendet/mark-paidrépondent400sur eux. Devis et estimations - Vos clients sont relancés par e-mail de leurs factures impayées avant et après l'échéance, factures envoyées par l'API comprises, sauf si vous désactivez les relances dans Paramètres → Facture → Rappels automatiques, où vous choisissez aussi les jours. Une facture déjà envoyée depuis le Dashboard garde les relances déjà prévues pour elle ; vos jours prennent le relais pour les jours qui suivent. Relances
- Les e-mails de facture et de relance sont rédigés dans la
languagede la facture, pied de page compris.
SDK
- Les prochaines versions des SDK Flutter (1.6.0), React Native (1.5.0) et Android (1.3.0) guident
le payeur pour un code qu'il génère dans le menu de son opérateur, dans un nouvel état,
PAYER_OTP_REQUIRED(CheckoutState.payerOtpRequireden Dart). Unwhenou unswitchqui liste tous les états doit lui prévoir une branche. Chaque montant qu'affiche l'interface est ce que paie le payeur, frais Wajub compris quand il les supporte, pour le moyen ou l'opérateur qu'il choisit. États
2026-10-15
NOUVEAU Plugins
- Module PrestaShop 1.0.1, pour PrestaShop 8.1 à 9 : Mobile Money et Carte bancaire comme moyens de paiement à part entière, avec le formulaire de paiement de Wajub dans le tunnel de commande (Classic et Hummingbird), et Autres moyens de paiement sur la page de paiement Wajub, chacun affiché seulement si votre compte le propose pour le panier. La commande est créée quand le client la passe et réglée par le webhook, paiements en plusieurs échéances compris ; un paiement inférieur au total compte, et le client paie le reste. Une commande que PrestaShop divise en plusieurs colis est payée, remboursée et annulée comme une seule. PrestaShop
- Module PrestaShop 1.0.1 : Connexion avec Wajub obtient la clé de la boutique depuis le
Dashboard, avec le type de client
prestashop; le back-office et l'adresse e-mail de la boutique sont prévenus à partir de 14 jours avant l'expiration d'une clé ainsi créée. Les remboursements dans les deux sens, depuis la page de la commande et depuis le Dashboard ; un remboursement que Wajub ou le module refuse ne crée pas d'avoir. Une connexion par boutique en multiboutique, et les données du client pour le module RGPD de PrestaShop. Connecter votre application à Wajub - Module PrestaShop 1.0.1 : des alertes dans le back-office pour un environnement choisi sans clé, une clé qui expire, une boutique ouverte au public encore en mode Test, Wajub absent du tunnel de commande et une tâche planifiée qui ne s'exécute pas ; les réglages préviennent une boutique non servie en HTTPS en production. Wajub · Test s'affiche dans l'en-tête du back-office tant que la boutique accepte des paiements de test. La désinstallation garde la trace des paiements, remboursements et notes Wajub des commandes. Alertes du back-office
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. 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. 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.
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.
- 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 :
@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 Wajub.js. 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. 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.@wajub/js,@wajub/react,@wajub/vueet@wajub/sveltepassent en 1.8.1 sans autre changement. Angular - Wajub.js 1.8.0 :
loader: 'skeleton'garde votre page immobile pendant le chargement d'un champ de paiement : un squelette dessiné dans le style de vos champs tient la hauteur du formulaire jusqu'à ce qu'il soit prêt.componentReserveHeight(type, variant, fields), surwajubet en export synchrone de@wajub/js, donne cette hauteur.componentEstimatedHeight(type, variant, fields), de@wajub/js, donne une estimation identique 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 que le payeur passe sur la page du prestataire. Un champ retiré 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. Surmount()etopen(), un nouveau presetthemeremplace le précédent et ce qu'il apportait.update({ layout })redispose les moyens d'un checkout intégré, en ligne comme dans la superposition. 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.CheckoutEmbedapplique sur place un changement d'appearance, detheme, delocaleou delayout, 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 composant tient la place dont le formulaire a besoin, si bien queminHeight={0}n'est plus nécessaire avecvariant="fields", et unminHeightque vous passez est gardé. Un nouveauvariant,fields,loader,readyTimeout,collectAddress,addressModeoucollectNamemonte un nouveau champ dans le même conteneur. La propappearanceest envoyée entière : une clé que vous en retirez est effacée. Changer de gestionnaire ne recharge jamais le formulaire. Avec un framework - Un champ de paiement dont la session est déjà terminée affiche son 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. Quand le formulaire n'arrive pas - Wajub.js 1.7.2 : avec
variant: 'fields', un composant prend la hauteur de ses champs ; avec les composants de champs React, Vue et Svelte, passezminHeightà0. Les valeurs derulesque le checkout refuse sont écartées. Dans votre propre bloc de moyen de paiement update({ appearance })sur un checkout intégré tient pendant les étapes suivantes du payeur. 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, champs de carte compris, et lacolord'une règle.Labelatteint le libellé du titulaire de la carte. Une police Google Fonts que le checkout charge atteint les champs de carte, et sansfontSizeBaseles champs font 16px sur téléphone ou tablette, pour qu'iOS ne zoome pas 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,systemouautoest lu commecolorScheme,systemvalantauto, quand vous ne donnez pas decolorScheme. Les préréglagesstripe,night,flatetnonene changent pas. Préréglages - 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 que les champs. Lesrules.Inputet.Labelatteignent les champs, et le contrôle des valeurs deruless'applique par tous les chemins,update({ appearance })compris. Règles readypart une fois le formulaire du composant affiché, ou aussitôt quand il n'a aucun formulaire à afficher. 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 portefeuille utilisable avec n'importe quel réseau, comme Wave, Express Union ou Djamo, accepte n'importe quel numéro. 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
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. 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. Le propriétaire et chaque Administrator reçoivent un e-mail pour chaque clé créée par un appairage. - Paramètres → Développeurs → Clés API 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é. É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. - Wajub.js 1.7.0 : quand le paiement se poursuit sur la page du prestataire, le composant émet
redirectavec{ url, method }et Wajub.js y emmène votre page. Au retour de cette page, le payeur arrive sur la page Wajub de la session, dans la langue du composant, qui affiche le résultat puis l'envoie sur lecallbackdu paiement avecstatus,referenceettrxref, ou garde le résultat affiché quand il n'y a pas decallback. 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 - Un envoi demandé avec
submit()ouconfirmPayment()qu'un composant refuse, comme un numéro Mobile Money vide ou invalide, une carte laissée incomplète ou rejetée, des champs de carte encore en chargement, un virement sans IBAN ni numéro de compte ou un paiement crypto sans actif, émeterroravecsubmission_failedet un message pour le payeur, etconfirmPayment()rejette avec cette erreur. 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 : 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, 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. 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. 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 -
Un débit Mobile Money au-dessus du plafond par transaction répond
422, en sandbox comme en 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, 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 ;GET /links: untypeinconnu ;GET /events: untypequ'aucun endpoint ne reçoit ;GET /channels: uncountryinconnu ;GET /countries: uneregioninconnue ;GET /currencies: untypeautre quefiat,cryptoouall, lu sans tenir compte de la casse.
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 la part des transferts. 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./healthrenvoie 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. 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 peut répondre
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 (Paiement — Langue), 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 resteprocessing, 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 qui échoue 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. 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
- 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. API Shield
Orchestration
- 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. 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 HTTP (au moins 90 s), 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. 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. 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 Paramètres, Sécurité. 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, Paramètres → Intégration de la page de paiement, 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 Sécurité de l'équipe, 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
- SDK serveur Node.js et C# 2.0.0, PHP 2.0.1, Ruby 1.3.0, Python, Go et Java 1.2.1 : 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 et Android 1.2.1, et Flutter à partir de sa prochaine version, 1.6.0 : une
erreur qu'un nouvel essai ne peut pas corriger, comme une session terminée, n'est plus marquée
retryable. React Native et Android annulent le paiement quand le payeur ferme l'interface avant d'avoir rien soumis, etshowWajubPaymentSheetde Flutter appelle 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. 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. 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.
- 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. 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 porte désormais
metadata.resolutionàaccepted. Litiges POST /beneficiaries/{id}/verifyinterroge désormais l'opérateur pour tous les comptes. Hors Sync Relay, vérifiez de nouveau tout bénéficiaire vérifié avant cette version 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 : React Native à partir de 1.4.1 et Android à partir de 1.2.1, leurs premières versions publiées qui les apportent, et Flutter à partir de sa prochaine version, 1.6.0. Cartes sur la page sécurisée du prestataire de paiement, et portefeuilles en un geste comme Djamo. SDK mobiles
- Shield : Toujours autoriser ce client 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, Listes 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, Afficher fonctionne sur la page de l'endpoint, et Passer en production 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é. 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 : Diagnostiquer 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- 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 événements enregistrés et des livraisons de webhook, et des copies reçues par une plateforme Sync. 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. 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, Examens 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 : Renouveler 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. 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.
- 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,/shieldet/taxré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.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 et un appel répété répond200au lieu de404. Supprimer un payeur- Sur un débit fait avec une clé secrète depuis votre propre checkout, appelez
Wajub.signals()(Wajub.js 1.6.0) dans le navigateur du payeur et transmettez le résultat tel quel dansdata._client. 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 Paramètres, Remboursements.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 - Importer
wajub.mjsdepuisjs.wajub.comcomme 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 du nouveau
wajub listen; la 1.6.0 n'a pas été publiée.
2026-10-02
CLI
- CLI 1.6.0 :
wajub listenremet à votre handler 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. Les écritures de payout (création de bénéficiaires, de transferts et de lots) sont plafonnées à 20 par minute sur tous les plans, Enterprise compris. 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 pendant 72 heures au plus, un4xxcompris. 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 etshield->addToBlocklist()la liste de blocage mise à jour. 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.
wajub logoutrévoque la clé créée parwajub login.
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