Clients
La fiche payeur que Wajub réutilise d'un paiement à l'autre, et ce qu'elle change sur la page de checkout.
Vous avez des clients, que vous l'ayez demandé ou non. Chaque appel à POST /payments résout un
client avant d'enregistrer la transaction : le tout premier paiement que vous avez créé en sandbox
en a donc déjà produit un. Cette ressource n'est pas une option à activer, c'est l'identité du
payeur à laquelle chaque paiement est rattaché.
Voici comment fonctionne cette résolution, quand elle se passe mal, et ce qu'un client vous apporte réellement sur la page de checkout.
Chaque paiement en crée un ou en retrouve un
Un paiement doit porter au moins un champ parmi email, phone et customer_id. Sans aucun des
trois, l'API répond 422 et rien n'est enregistré.
Dès qu'il en reçoit un, Wajub cherche un client correspondant sur votre compte, dans l'environnement
que vous appelez. S'il en trouve un, le paiement lui est rattaché. Sinon, il crée le client et y
rattache le paiement. Dans les deux cas, le paiement vous renvoie un objet customer, avec l'id
que vous pourrez réutiliser ensuite.
La sandbox et le live sont deux populations séparées. Un client créé par un paiement en sandbox est
invisible pour un paiement live, et les ids diffèrent : cus_test_… en sandbox, cus_… en
production.
Comment Wajub décide que deux paiements viennent de la même personne
La recherche suit un ordre fixe et s'arrête à la première correspondance.
| Ordre | Champ | Méthode de comparaison |
|---|---|---|
| 1 | customer_id | Correspondance exacte sur l'id du client |
| 2 | email | Espaces de début et de fin retirés, en minuscules : Amina@Example.com correspond à amina@example.com |
| 3 | phone | Espaces de début et de fin retirés uniquement, puis comparaison caractère par caractère |
L'email est tolérant. Le téléphone ne l'est pas, et c'est cette asymétrie qui fait dérailler les listes clients des marchands.
La correspondance sur le téléphone est une comparaison exacte de chaînes
Pour cette recherche, +237670000000, 237670000000 et +237 6 70 00 00 00 sont trois clients
différents. Normalisez le numéro en E.164 une fois pour toutes, dans votre propre code, avant qu'il
n'atteigne l'API. Les règles sont dans Formats de numéros de téléphone.
Quand un paiement porte à la fois un email et un téléphone, c'est l'email qui décide. Le téléphone n'est consulté que si aucun client ne correspond à l'email : un client existant peut donc être retrouvé par son email, puis recevoir discrètement un numéro de téléphone qu'il n'avait jamais eu.
Payer en tant que client connu
Une fois que vous détenez un id, passez-le et laissez complètement de côté les champs de contact.
Le champ customer accepte l'id sous forme de simple chaîne, et customer_id accepte la même
valeur ; ce sont deux écritures de la même chose.
curl https://api.wajub.com/payments \
-H "Authorization: sk_test.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…" \
-H "Content-Type: application/json" \
-d '{
"amount": 5000,
"currency": "XAF",
"customer": "cus_test_sAaim5apjocIgtlhzJY3wQ8s",
"reference": "order-4173"
}'L'identifiant n'est pas forcément un id. Si la valeur que vous passez ne correspond à aucun id de
client, Wajub l'essaie comme numéro de téléphone, puis comme adresse email.
"customer": "amina@example.com" et "customer": "+237670000000" sont donc tous deux résolus, ce
qui est pratique quand votre propre base stocke l'email et non l'id Wajub.
Un identifiant qui ne correspond à rien donne un 404, pas un nouveau client
C'est le seul endroit où l'API refuse de créer. Passez customer ou customer_id et Wajub
trouvera ce client ou fera échouer l'appel avec 404 Customer not found ; il ne se rabat jamais
sur une création. Un id périmé, un client supprimé la semaine dernière ou un id live envoyé en
sandbox font tous échouer le paiement d'emblée. En cas de doute sur l'existence de la fiche,
envoyez plutôt email ou phone.
Un paiement n'écrase jamais un client
Quand un paiement correspond à un client existant, les données que vous avez envoyées sont fusionnées, mais seulement dans les champs vides. Un champ qui a déjà une valeur n'est pas touché.
| Envoyé sur le paiement | Le client a déjà une valeur | Le client n'en a pas |
|---|---|---|
name, email, phone | Ignoré | Renseigné |
metadata | Fusionné clé par clé, vos clés l'emportent | Renseigné |
address, shipping | Ignoré | Rattaché comme adresse principale |
Conséquence pratique : vous ne pouvez pas corriger un client via un paiement. Envoyez un paiement avec
"name": "Amina Diallo" pour un client déjà nommé Amina N. et l'ancien nom est conservé. Utilisez
PUT /customers/{id} pour les corrections.
Le premier paiement perd l'adresse
Les adresses ne sont rattachées que lors d'une fusion, quand le client existait déjà. Un tout
nouveau client créé par un paiement est enregistré avec son email, son nom, son téléphone et ses
métadonnées seulement : une address envoyée sur ce premier paiement n'est donc pas conservée sur
la fiche client. Créez le client en amont si l'adresse compte pour vous.
Créer un client en amont
La création explicite en vaut la peine quand vous connaissez le payeur avant qu'il ne paie : une inscription, une base clients importée, un compte B2B avec un numéro fiscal et une adresse de facturation.
https://api.wajub.com/customersAu moins un champ parmi email et phone est obligatoire. Tout le reste est facultatif ; les champs
ci-dessous sont ceux qu'il faut connaître, et la liste complète se trouve dans la
référence API.
emailstringfacultatifphone est fourni. Stocké en minuscules.phonestringfacultatifemail est fourni. Envoyez du E.164, la correspondance est littérale.namestringfacultatiftypeenumfacultatifdéfaut : individualindividual ou business. Envoyer business_name seul implique business.business_namestringfacultatiftype vaut business. Devient le name du client.currencystringfacultatifpreferred_languagestringfacultatifaddressobjectfacultatifcountry, city, state, postal_code, address_line1, address_line2.billingobjectfacultatifaddress.customer_groupstringfacultatiftagsarrayfacultatifmetadataobjectfacultatifEnvoyez l'appel depuis votre serveur, avec la clé secrète.
curl https://api.wajub.com/customers \
-H "Authorization: sk_test.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cus-signup-9182" \
-d '{
"email": "amina@example.com",
"phone": "+237670000000",
"name": "Amina Diallo",
"metadata": { "user_id": "u_9182" }
}'Un nouveau client est renvoyé en 201 Created, avec l'id que vous passerez désormais sur vos
paiements.
Un doublon répond 200, pas 201
Si vous créez un client dont l'email ou le téléphone existe déjà, l'API renvoie la fiche existante
avec 200 OK et le message Customer already exists for this merchant. Rien n'est dupliqué, et
rien n'est mis à jour non plus. Testez code === 201 pour distinguer une vraie création d'une
correspondance, et ne traitez jamais le 200 comme une erreur.
Idempotency-Key fonctionne ici comme sur les paiements : la même clé rejoue la réponse d'origine
pendant 24 heures au lieu d'ouvrir une deuxième fiche. C'est la façon sûre de retenter un hook
d'inscription.
Une marketplace qui crée un client pour le compte d'un de ses sous-comptes ajoute l'en-tête X-Sync
à cet appel, comme décrit dans Sync.
Ce qu'un client change sur la page de checkout
C'est ce qui rentabilise l'appel supplémentaire. Un paiement rattaché à un client connu affiche une page différente.
| Ce que porte le client | Ce que le checkout en fait |
|---|---|
| Cartes et numéros Mobile Money déjà utilisés | Les propose comme moyens enregistrés, utilisables en un geste, le moyen par défaut en premier, dix au maximum |
preferred_language | Définit la langue de la page, sauf si le réglage d'équipe ou de branding l'emporte |
currency | Devient la devise présélectionnée quand la conversion automatique est activée |
Les moyens enregistrés sont le vrai gain pour les payeurs qui reviennent : le numéro est déjà là, masqué, et ils confirment sur leur téléphone sans le ressaisir.
Enregistrer un moyen de paiement est la décision du payeur
Une carte ou un numéro Mobile Money n'est conservé que si le payeur coche la case sur la page de checkout. Ce n'est jamais déduit ni coché par défaut : une fiche client sans moyen enregistré est donc l'état normal tant que personne n'a donné son accord. Seuls les cartes et le Mobile Money sont réutilisables ; les portefeuilles et les virements bancaires ne sont pas conservés.
Récupérer et lister
La récupération prend l'id du client et renvoie le même objet que l'appel de création.
https://api.wajub.com/customers/{id}La liste renvoie vos clients du plus récent au plus ancien, et accepte des filtres qui correspondent à votre façon de les segmenter.
https://api.wajub.com/customers| Paramètre de requête | Accepte |
|---|---|
per_page | De 1 à 100, 25 par défaut |
search | Texte libre sur le nom, l'email, le téléphone et l'id |
status | active, inactive, blocked |
type | individual, business |
country | Code pays à deux lettres |
customer_group | La chaîne de groupe définie sur le client |
cursor | Un curseur opaque issu d'une réponse précédente |
La pagination a deux modes, et le mode par numéro de page est celui par défaut. Sans cursor, meta
contient current_page, last_page, per_page et total. Avec un cursor, l'endpoint passe en
mode curseur, où meta contient à la place per_page, next_cursor, prev_cursor et has_more.
Le mode curseur est celui qu'il vous faut pour un export complet, car il reste juste pendant que de
nouveaux clients sont créés. Pagination détaille les deux.
Le statut est une étiquette, pas une barrière
Un client est active, inactive ou blocked, et quatre endpoints le font passer d'un état à
l'autre.
| Appel | Effet |
|---|---|
POST /customers/{id}/block | Passe à blocked, enregistre votre reason et un horodatage blocked_at |
POST /customers/{id}/unblock | Remet le client à active |
POST /customers/{id}/deactivate | Passe à inactive |
POST /customers/{id}/activate | Passe à active |
Bloquer un client déjà bloqué répond 400, tout comme débloquer un client qui ne l'est pas.
Bloquer un client ne l'empêche pas de payer
status: blocked est un indicateur sur la fiche client, et rien dans le parcours de paiement ne le
lit. Un client bloqué peut créer et finaliser un paiement exactement comme avant. Pour refuser
réellement un payeur, ajoutez son email ou son téléphone à la liste de blocage de
Shield, vérifiée sur chaque transaction live, qui la rejette d'emblée.
Supprimer un client, c'est l'effacer
La suppression n'est pas l'archivage réversible qu'elle est sur la plupart des ressources.
https://api.wajub.com/customers/{id}La fiche est supprimée de façon logique et ses données personnelles sont anonymisées immédiatement, dans la même requête, pour répondre à une demande de droit à l'effacement sans deuxième étape. L'archive anonymisée est conservée 90 jours, puis détruite définitivement. Les paiements passés restent, car ce sont des écritures financières, mais l'identité derrière eux a disparu.
Aucune annulation possible via l'API
L'API n'a pas d'endpoint de restauration. Un client supprimé par erreur ne peut être récupéré que depuis le Dashboard, et seulement dans la fenêtre de 90 jours, avant la purge de l'archive. Désactivez plutôt que de supprimer quand vous voulez simplement écarter un client.
Webhooks
Trois événements suivent un client, et ils portent l'objet client complet comme payload.
| Événement | Déclenché quand |
|---|---|
customer.created | Un client est créé, y compris implicitement par un paiement |
customer.updated | Un champ change, y compris un changement de statut ou une fusion depuis un paiement |
customer.deleted | Le client est supprimé et anonymisé |
customer.created est plus bavard qu'il n'y paraît : il se déclenche pour chaque nouveau payeur que
voit votre checkout, pas seulement pour ceux que vous créez vous-même. L'enregistrement, la
vérification et les nouvelles tentatives sont traités dans Webhooks.
Dans le Dashboard
Customers liste les mêmes fiches, avec une chronologie par client, et ses paiements, remboursements et litiges dans des onglets dédiés. Les tags, groupes et notes y sont modifiables, et les actions groupées appliquent un changement à toute une sélection.
Deux outils n'ont pas d'équivalent dans l'API. Customers → Export produit un fichier CSV ou Excel de la liste, en live uniquement. Settings → Tools → Customer merges fusionne les doublons en une seule fiche : c'est ainsi que vous réparez une liste déjà éclatée entre trois formats de téléphone.
Pages associées
- Référence API des clientsTous les champs de la ressource, et les cinq endpoints générés.
- Formats de numéros de téléphoneNormalisez en E.164 avant que la correspondance ne coupe vos clients en deux.
- Règles ShieldLa liste de blocage qui refuse vraiment un payeur, par email, téléphone, IP ou BIN.
- Factures récurrentesFacturez un client connu selon un calendrier.
- WebhooksEnregistrez un endpoint et vérifiez la signature des événements client.
- PaginationDes numéros de page pour un écran, des curseurs pour un export.