Getting Started · Customers

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

An org token (see Authentication). Every call on this page uses it as the bearer. A client admin token or a customer token is rejected with 401.

Consent status

StatusMeaning
PENDINGLinked, but the customer has not agreed yet.
VERIFIEDThe customer agreed. You can act for them.
REJECTEDThe 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.

bash
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\"}"
json
{ "waffyUserId": 2264, "userIdentification": 39311497 }
  • phoneNumber is required, in the form +9665XXXXXXXX. firstName, lastName and email are 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

ValueWhat 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 omittedNothing 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.

PathHowBest for
A. Signed linkThe 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 screenWaffy 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 loginThe 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:

bash
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\"}"
json
{ "sent": true }
HTTPMeaning
400This customer is not linked to your organization yet. Register or link them first.
404No Waffy account exists for this phone number.
429Your 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:

bash
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:

bash
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\"}"
json
{ "waffyUserId": 2264, "userIdentification": 39311497 }
CallHTTPMeaning
otp/send429Your organization’s hourly OTP limit was reached.
otp/send400Phone number missing or not recognizable.
otp/send502Sending the OTP failed downstream. Transient, retry.
otp/verify400Wrong or expired code, or a missing field. Nothing is created or consented on a failed attempt. Send a new OTP and retry.
otp/verify502Creating 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.

bash
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

These calls exist so you can test your own handling of consent_required and consent_rejected. In production the customer decides on their own phone.