Customers
The payer record Wajub reuses across payments, and what it changes at checkout.
Every payment is attached to a customer, the payer record Wajub finds or creates for you and reuses across your payments. Five pages go further:
- Pay as a known customer, by its id, and what a known customer changes on the checkout page.
- Manage customers: create one up front, update, list, block, tax ids and webhooks.
- Deletion and erasure, what deleting a customer removes and what it keeps.
- Pocket, where your payers find their payments, across merchants.
- In the Dashboard, the list, the export and customer merges.
Every payment creates or finds one
A payment must carry at least one of email, phone or customer_id. With none of the three the
API answers 422 and nothing is recorded.
Given one, Wajub looks for a matching customer on your account, in the environment you are calling.
If it finds one, the payment is attached to it. If it does not, it creates the customer and
attaches the payment to that. Either way you get a customer object back on the payment, carrying
the id you can reuse from then on.
Sandbox and live are separate populations. A customer created by a sandbox payment is invisible to
a live one, and the ids differ: cus_test_… in sandbox, cus_… in production.
How Wajub decides two payments are the same person
Matching runs in a fixed order, and stops at the first hit.
| Order | Field | How it is compared |
|---|---|---|
| 1 | customer_id | Exact match on the customer id |
| 2 | email | Trimmed, lowercased, so Amina@Example.com matches amina@example.com |
| 3 | phone | Read in E.164 first, so +237 6 70 00 00 00, 237670000000 and, for an account in Cameroon, 670000000 match +237670000000 |
An account holds one customer per email, whatever its case, and per phone once in E.164.
Phones are stored in E.164
Every customer phone is stored in E.164, whoever writes it: the API, a payment, a payment link or
invoice payer, the Dashboard. A number written with + (or 00) is read in its own country; one
written without it is read in phone_country when you send it, else your account's country. A
value that does not read as a phone number is kept as sent, and only matches itself. The formats
are in Phone number formats.
When a payment carries both an email and a phone, the email decides. The phone is only consulted if no customer matched the email, which means an existing customer can be found by email and then quietly gain a phone number they never had.
A payment never overwrites a customer
When a payment matches an existing customer, the data you sent is merged in, but only into the gaps. A field that already holds a value is left alone.
| Sent on the payment | Customer already has a value | Customer has none |
|---|---|---|
name, email, phone | Ignored | Filled in, unless another customer of the account already holds that email or phone |
metadata | Merged key by key, your keys win | Filled in |
address | Ignored | Attached as the primary shipping address |
shipping | Ignored | Attached as the primary billing address |
Send the delivery address as customer.address.
The practical consequence: you cannot correct a customer through a payment. Send a payment with
"name": "Amina Diallo" for a customer already named Amina N. and the old name survives. Use
PUT /customers/{id} for corrections. A payment
sent with X-Sync never touches the merchant's metadata: its metadata goes to the platform's
own, described in On behalf of a subaccount.
The first payment drops the address
Addresses are only attached when the customer already existed. A brand new customer created by a
payment is stored with its email, name, phone and metadata alone, so an
address sent on that first payment is not kept on the customer record. Create the customer up
front if the address matters to you.