Customers & consent
Before you act for a customer, for example to take a payment, they must be registered with Waffy, linked to your organization and have given consent.
What you need
401.Consent status
| Status | Meaning |
|---|---|
PENDING | Linked, but the customer has not agreed yet. |
VERIFIED | The customer agreed. You can act for them. |
REJECTED | The customer declined. A fresh consent link, OTP verification or checkout login can reverse it. |
Until consent is established, calls that act for the customer fail with consent_required (or consent_rejected after a decline).
1. Register or link a customer
One call covers every case. A new phone number is registered and linked, an existing Waffy customer is just linked, and one already linked is returned as is. You never need to check first.
export CUSTOMER_PHONE=+9665XXXXXXXX
curl -s -X POST "$ID_BASE_URL/realms/waffy/waffy-partner/customers" \
-H "Authorization: Bearer $ORG_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"phoneNumber\":\"$CUSTOMER_PHONE\",\"firstName\":\"Sara\",\"lastName\":\"Al-Otaibi\"}"{ "waffyUserId": 2264, "userIdentification": 39311497 }phoneNumberis required, in the form+9665XXXXXXXX.firstName,lastNameandemailare optional.- Keep
waffyUserId. You need it for bank account and address calls and for contracts. - The other party of a contract (the provider) is registered with the exact same call. There is no separate type or role.
The consentMethod field
| Value | What happens |
|---|---|
"sms" | Sends the signed consent link by SMS in the same call. Only the first call that creates the link sends it; use the resend call below later. |
"otp" | Accepted, but it does nothing in this call. Send the OTP yourself with otp/send (path B). |
| empty or omitted | Nothing is sent and the customer stays PENDING. Exception: if your client has automatic consent enabled (a Waffy-managed setting, ask Waffy), the customer is linked as already consented and nothing more is needed. |
2. Establish consent
Pick the path that fits your integration.
| Path | How | Best for |
|---|---|---|
| A. Signed link | The customer gets an SMS link and approves on a Waffy page. Send it with consentMethod: "sms" or the resend call. | The simplest option. No UI of your own. |
| B. Your own OTP screen | Waffy sends a code, your UI collects it, you verify it server to server (otp/send, otp/verify). | You want the customer to stay on your pages. |
| C. Checkout login | The customer logs in on Waffy’s checkout page when they pay. No extra API call. | Consent is only needed at payment time. |
Path A: send or resend the consent link
consentMethod: "sms" only sends on the first call. To send again, because the customer missed it or declined and you want to ask once more, use this call. It works for PENDING and REJECTED customers alike:
curl -s -X POST "$ID_BASE_URL/realms/waffy/waffy-partner/consent/send" \
-H "Authorization: Bearer $ORG_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"phoneNumber\":\"$CUSTOMER_PHONE\"}"{ "sent": true }| HTTP | Meaning |
|---|---|
| 400 | This customer is not linked to your organization yet. Register or link them first. |
| 404 | No Waffy account exists for this phone number. |
| 429 | Your organization’s hourly consent-link limit was reached. It is counted per client and separately from the OTP limit. |
The link can be used once. Opening it again, approving or declining twice, shows a "link no longer valid" page.
Path B: verify an OTP yourself
Send the code. This works even if the customer is not registered yet:
curl -s -X POST "$ID_BASE_URL/realms/waffy/waffy-partner/otp/send" \
-H "Authorization: Bearer $ORG_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"phoneNumber\":\"$CUSTOMER_PHONE\"}"Collect the code in your own UI, then verify it. This registers the customer if needed and records consent in the same call, so you don't need the register call first:
curl -s -X POST "$ID_BASE_URL/realms/waffy/waffy-partner/otp/verify" \
-H "Authorization: Bearer $ORG_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"phoneNumber\":\"$CUSTOMER_PHONE\",\"otp\":\"123456\",\"firstName\":\"Sara\",\"lastName\":\"Al-Otaibi\"}"{ "waffyUserId": 2264, "userIdentification": 39311497 }| Call | HTTP | Meaning |
|---|---|---|
otp/send | 429 | Your organization’s hourly OTP limit was reached. |
otp/send | 400 | Phone number missing or not recognizable. |
otp/send | 502 | Sending the OTP failed downstream. Transient, retry. |
otp/verify | 400 | Wrong or expired code, or a missing field. Nothing is created or consented on a failed attempt. Send a new OTP and retry. |
otp/verify | 502 | Creating the customer or recording consent failed downstream. Retry. |
The response contains identifiers only, never a token. A successful verification also reverses an earlier decline. To pay, get a payment ticket as for any consented customer (see Authentication).
Testing consent without a phone
In the sandbox you can approve or decline as the customer would, from curl or Postman (the collection's Consent folder). There is no API to read a customer's consent token, because in production it only reaches them by SMS. In the sandbox, ask Waffy for the token of your test phone number.
export CONSENT_TOKEN=<from Waffy> # View the page (always 200 text/html; check the body, not the status code) curl -s "$ID_BASE_URL/realms/waffy/waffy-consent/$CONSENT_TOKEN" # Approve: PENDING -> VERIFIED curl -s -X POST "$ID_BASE_URL/realms/waffy/waffy-consent/$CONSENT_TOKEN/decision" \ --data-urlencode "approved=true" # Decline: PENDING -> REJECTED curl -s -X POST "$ID_BASE_URL/realms/waffy/waffy-consent/$CONSENT_TOKEN/decision" \ --data-urlencode "approved=false"
Testing only
consent_required and consent_rejected. In production the customer decides on their own phone.