Aller au contenu

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.

OrdreChampMéthode de comparaison
1customer_idCorrespondance exacte sur l'id du client
2emailEspaces de début et de fin retirés, en minuscules : Amina@Example.com correspond à amina@example.com
3phoneEspaces 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.

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 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 paiementLe client a déjà une valeurLe client n'en a pas
name, email, phoneIgnoréRenseigné
metadataFusionné clé par clé, vos clés l'emportentRenseigné
address, shippingIgnoré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.

POSThttps://api.wajub.com/customers

Au 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.

emailstringfacultatif
Obligatoire sauf si phone est fourni. Stocké en minuscules.
phonestringfacultatif
Obligatoire sauf si email est fourni. Envoyez du E.164, la correspondance est littérale.
namestringfacultatif
Nom affiché, le seul champ de nom que vous pouvez définir.
typeenumfacultatifdéfaut : individual
individual ou business. Envoyer business_name seul implique business.
business_namestringfacultatif
Obligatoire quand type vaut business. Devient le name du client.
currencystringfacultatif
Devise préférée, utilisée par défaut sur le checkout quand la conversion automatique est activée.
preferred_languagestringfacultatif
Langue du checkout hébergé, qui passe après les réglages d'équipe et de branding.
addressobjectfacultatif
Adresse de livraison : country, city, state, postal_code, address_line1, address_line2.
billingobjectfacultatif
Adresse de facturation, même structure que address.
customer_groupstringfacultatif
Segment libre sur lequel vous pouvez filtrer la liste.
tagsarrayfacultatif
Chaînes de 50 caractères maximum chacune.
metadataobjectfacultatif
Vos propres données clé-valeur, au format libre.

Envoyez 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.

Réponse · 201 Created
{
"code": 201,
"status": "Created",
"message": "Customer created",
"customer": {
"id": "cus_test_sAaim5apjocIgtlhzJY3wQ8s",
"type": "individual",
"name": "Amina Diallo",
"email": "amina@example.com",
"phone": "+237670000000",
"status": "active",
"blocked": false,
"tags": [
],
"metadata": {
"user_id": "u_9182"
},
"sandbox": true,
"created_at": "2026-09-11T10:24:00Z"
}
}

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 clientCe que le checkout en fait
Cartes et numéros Mobile Money déjà utilisésLes propose comme moyens enregistrés, utilisables en un geste, le moyen par défaut en premier, dix au maximum
preferred_languageDéfinit la langue de la page, sauf si le réglage d'équipe ou de branding l'emporte
currencyDevient 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.

GEThttps://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.

GEThttps://api.wajub.com/customers
Paramètre de requêteAccepte
per_pageDe 1 à 100, 25 par défaut
searchTexte libre sur le nom, l'email, le téléphone et l'id
statusactive, inactive, blocked
typeindividual, business
countryCode pays à deux lettres
customer_groupLa chaîne de groupe définie sur le client
cursorUn 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.

AppelEffet
POST /customers/{id}/blockPasse à blocked, enregistre votre reason et un horodatage blocked_at
POST /customers/{id}/unblockRemet le client à active
POST /customers/{id}/deactivatePasse à inactive
POST /customers/{id}/activatePasse à active

Bloquer un client déjà bloqué répond 400, tout comme débloquer un client qui ne l'est pas.

Supprimer un client, c'est l'effacer

La suppression n'est pas l'archivage réversible qu'elle est sur la plupart des ressources.

DELETEhttps://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.

Webhooks

Trois événements suivent un client, et ils portent l'objet client complet comme payload.

ÉvénementDéclenché quand
customer.createdUn client est créé, y compris implicitement par un paiement
customer.updatedUn champ change, y compris un changement de statut ou une fusion depuis un paiement
customer.deletedLe 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.

Que pensez-vous de ce contenu ?