Getting Started · Step 2 of 5

Users & IBANs

Every participant in a contract must exist in Waffy and be linked to your organization. Anyone who will receive money also needs a bank account.

  1. 1Auth
  2. 2Users
  3. 3Contract
  4. 4Payment
  5. 5Settle

Tokens used on this page

Registering a customer and adding a bank account or address use your org token. See Authentication.

Register or link the user

Call this for every user, buyer and seller, before creating a contract. One call registers a new phone number, or links an existing Waffy customer to your organization:

bash
curl -s -X POST "$ID_BASE_URL/realms/waffy/waffy-partner/customers" \
  -H "Authorization: Bearer $ORG_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+9665XXXXXXXX",
    "firstName": "Ahmed",
    "lastName": "Al-Ghamdi"
  }'
json
{ "waffyUserId": 2264, "userIdentification": 39311497 }

Save waffyUserId as the buyer or seller id and call it once for each party. The seller (provider) is registered with the same call.

Consent

A newly linked customer is PENDING until they consent. Establishing consent, by SMS link, your own OTP screen or checkout login, is covered in Customers & consent.

Add a bank account (IBAN)

Required for anyone who will receive money: the seller, and the buyer in case of a refund. It is also required, with a valid address, for bank transfer cash-out. Saudi format: SA + 22 digits.

bash
curl -s -X POST "$AUTH_BASE_URL/api/users/external/$SELLER_ID/banks" \
  -H "Authorization: Bearer $ORG_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "iban": "SA0380000000608010167519",
    "currency": "SAR",
    "beneficiaryName": "Ahmed Al-Ghamdi",
    "nationalId": "1000000000"
  }'

# Repeat for the buyer with their own IBAN and nationalId

$SELLER_ID is the waffyUserId from the register call. $AUTH_BASE_URL is the authentication service host for your environment.

Add an address

Required for bank transfer cash-out alongside the IBAN. Only addressLabel (for example HOME or WORK) and countryCode are required; the other fields are optional.

bash
curl -s -X POST "$AUTH_BASE_URL/api/external/profiles/$SELLER_ID/addresses" \
  -H "Authorization: Bearer $ORG_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "addressLabel": "HOME",
    "street": "King Fahd Road",
    "district": "Al Olaya",
    "city": "Riyadh",
    "countryCode": "SA",
    "postalCode": "12271"
  }'

# Repeat for the buyer

Absher identity verification (optional, KYC)

A two-step flow, only needed if your organization requires Saudi national ID verification. The user enters their national ID, Absher validates it and sends an OTP to the phone registered with that ID in the government system (this may differ from their Waffy phone).

Token for these two calls

The examples below were written with the legacy user_token. Check with Waffy whether your integration should send the client admin token instead before building on them.

Step 1: submit the national ID

Waffy forwards the ID to Absher. If it is valid, Absher sends an OTP to the user's registered phone. nationalId must be exactly 10 digits.

bash
curl -s -X PATCH "$AUTH_BASE_URL/api/users/external/$USER_ID/national-id" \
  -H "Authorization: Bearer $USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "nationalId": "1000000000"
  }'

Step 2: validate the OTP

bash
curl -s "$AUTH_BASE_URL/api/external/otps/validate" \
  -H "Authorization: Bearer $USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "ABSHER_OTP",
    "phoneNumber": "+966XXXXXXXXX",
    "otp": 123456
  }'
json
{
  "data": {
    "valid": true
  }
}
OTP typeUse
WAFFY_OTPStandard Waffy OTP verification
ABSHER_OTPSaudi national ID verification via Nafath/Absher

Legacy user endpoints (deprecated)

Deprecated: do not use for new integrations

Organizations that integrated before the Partner API sign users up with the legacy app_token. This keeps working while they move to the calls above. Waffy will announce a retirement date.
Legacy callTokenReplaced by
POST /v2/api/users/sign-upapp_tokenRegister or link the user
POST /api/users/{id}/IBANuser_tokenAdd a bank account
POST /api/profiles/{id}/addressesuser_tokenAdd an address
bash
# Legacy sign-up / link (app_token)
curl -s "$WAFFY_AUTH_URL/v2/api/users/sign-up" \
  -H "Authorization: Bearer $APP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+966XXXXXXXXX",
    "firstName": "Ahmed",
    "lastName": "Al-Ghamdi",
    "clientUserId": "your_internal_user_id"
  }'
# => { "data": { "id": 99001, "preExistingUser": false, "clientUserToken": "eyJhbGc..." } }

In the legacy flow data.id is the user id and clientUserToken is the customer's Waffy password, used for the legacy payment-time token. Store it encrypted, never log it and never expose it to a browser.