Gérer les clients
Créer un client en amont, le modifier, le lister et le bloquer, conserver ses numéros fiscaux, et suivre ses webhooks.
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é tel qu'envoyé, et retrouvé quelle que soit la casse : un second POST /customers avec Amina@Example.com renvoie le client enregistré avec amina@example.com.phonestringfacultatifemail est fourni. Enregistré en E.164 : un numéro sans son préfixe international est lu dans phone_country, sinon dans le pays de votre compte.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.xxxxxxxxxxxxxxxx…" \
-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 (quelle que soit sa casse) 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.
Modifier un client
Un paiement ne corrige jamais un client, il ne remplit que les champs encore vides : voir Un
paiement n'écrase jamais un client. Les
corrections passent par PUT /customers/{id}.
https://api.wajub.com/customers/{id}PUT /customers/{id} ne change que les champs que vous envoyez. Le name ne change que si vous
l'envoyez : first_name et last_name sont refusés, et envoyer business_name sur un particulier
laisse son nom intact (sur une entreprise, un nouveau business_name devient son nom, sauf si vous
envoyez aussi name). Un email (quelle que soit sa casse) ou un phone déjà porté par un autre
client du compte répond 422 sur ce champ, A customer with this email already exists. ou
A customer with this phone already exists.
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 de l'adresse de livraison ou de facturation du client |
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, ainsi que le next_cursor et le
has_more qui permettent de continuer avec un curseur. Envoyez ce next_cursor comme cursor et
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.
Pour le compte d'un sous-compte
Une marketplace qui crée un client pour le compte d'un de ses sous-comptes ajoute l'en-tête X-Sync
à POST /customers, et la règle des doublons ci-dessus s'applique : quand le marchand a déjà un
client avec cet email ou ce téléphone, ce client est renvoyé avec 200, et rien n'est dupliqué.
L'appel de la plateforme ne remplit que les champs que le marchand a laissés vides ; il ne change
jamais un champ qu'il a renseigné. Le client renvoyé, trouvé ou créé, est dès lors ouvert à la
connexion : la plateforme peut le lire, le retrouver dans la liste, le modifier et l'utiliser sur
ses paiements et ses factures. Un paiement créé avec X-Sync et l'email ou le téléphone d'un client
existant est rattaché à ce client de la même façon.
Avec X-Sync, un client ne montre jamais les notes, le block_reason ni les metadata du
marchand, et notes envoyé avec X-Sync est ignoré. Les metadata sont celles de la plateforme :
elle les lit et les écrit comme sur tout client, chaque connexion a les siennes, et celles du
marchand restent les siennes. Sur un client que le marchand avait déjà, POST /customers et les paiements
ajoutent les clés que la plateforme n'a pas encore définies, et PUT /customers/{id} remplace les
metadata de la plateforme.
Types de compte donne le détail.
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.
Numéros fiscaux
Les numéros d'identification fiscale d'un client entreprise sont conservés dans leur propre liste, une entrée par numéro : un NIU camerounais, un NINEA sénégalais, un numéro de TVA européen. La liste est disponible en live uniquement.
https://api.wajub.com/customers/{id}/tax_idstypestringobligatoirecm.niu, sn.ninea, ci.ifu, ke.pin, ng.tin, gh.tin, gh.vat, eu.vat, gb.vat ou us.ein. Un autre type est accepté aussi, et seule sa longueur est vérifiée.valuestringobligatoirecountry_codestringobligatoireCM.Ajoutez le numéro depuis votre serveur, avec une clé privée live :
curl https://api.wajub.com/customers/cus_sAaim5apjocIgtlhzJY3wQ8s/tax_ids \
-H "Authorization: $WAJUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "cm.niu",
"value": "M123456789000L",
"country_code": "CM"
}'Le numéro revient pending, et Wajub le vérifie en arrière-plan. verification_status passe ensuite
à verified quand la valeur respecte le format de son type, à failed quand elle ne le respecte
pas, et à unavailable quand la vérification n'a pas pu se faire. Les formats sont ceux qui servent
à vérifier votre propre numéro d'immatriculation (configuration de Tax
les liste) : un NIU camerounais compte une lettre, douze chiffres et une lettre. Pour un numéro
eu.vat, la vérification va plus loin et interroge le service européen VIES pour savoir si le numéro
existe.
Ajouter de nouveau le même type et le même numéro ne crée pas de copie : l'appel répond 200 avec
l'entrée existante, repassée à pending le temps d'une nouvelle vérification. C'est ainsi que l'on
relance une vérification unavailable.
GET /customers/{id}/tax_ids liste les numéros avec leur statut, et
DELETE /customers/{id}/tax_ids/{tax_id} en retire un.
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.
Pages associées
- Référence API des clientsTous les champs de la ressource, et les cinq endpoints générés.
- Règles ShieldLa liste de blocage qui refuse vraiment un payeur, par email, téléphone, IP ou BIN.
- 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.