# Customers and loyalty

Find a customer by phone or email, add new customers safely, follow changes, and read and adjust loyalty points.

## What your app needs

| You want to | Scope | Where |
|---|---|---|
| List customers and find one | `customers.list:read` | [`GET /customers`](/api/customers-list) |
| Add a customer and change their name | `customers.list:write` | [`POST /customers`](/api/customers-create), [`PATCH /customers/{id}`](/api/customers-update) |
| Read a customer's points | `loyalty:read` | [`GET /customers/{id}/loyalty`](/api/loyalty-get) |
| Add or remove points | `loyalty:write` | [`POST /customers/{id}/loyalty-adjustments`](/api/loyalty-adjustments-create) |
| Read a customer's orders | `orders:read` | [`GET /orders?customer_id=5821`](/api/orders-list) |

If your app only needs the customer of an order, `customers:read` is enough, and you do not need the whole list.

## Find a customer

```bash
curl "https://larm.sa/stores/$STORE_ID/v1/customers?phone=0512345678" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

`phone` accepts any Saudi form: `05…`, `5…`, `9665…` or `+9665…`. Answers always give the phone as `+9665…`, or `null` when the number is not valid. `email` is an exact match, and `search` looks in the name and email.

## Keep in sync

Read the whole list once, page by page, oldest first. Then subscribe to [`customer.created`](/events/customer-created), [`customer.updated`](/events/customer-updated) and [`customer.deleted`](/events/customer-deleted). When a customer is deleted, delete what you hold about them.

Every read of the list goes into the merchant's log.

## Add a customer

```bash
curl -X POST "https://larm.sa/stores/$STORE_ID/v1/customers" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"email":"sara@example.com","phone":"0512345678","first_name":"Sara","last_name":"Alotaibi"}'
```

- **The email is required.** A customer who already has this email or phone returns 409 `CUSTOMER_EXISTS`, so find them first.
- **The owner of the email takes over.** The new account has no password and is not active. It becomes a real account when that person registers on the store and proves the email with a code. Your app can never open someone else's orders or points this way.
- **Only names can change.** A phone or email decides who can sign in, so only the customer changes them.

## Loyalty points

Points exist when the merchant's plan includes the loyalty program and the merchant turned it on. Otherwise adding points returns 409 `LOYALTY_DISABLED`.

```bash
curl -X POST "https://larm.sa/stores/$STORE_ID/v1/customers/5821/loyalty-adjustments" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"points":50,"reason":"Bonus for a product review"}'
```

- `points` is positive to add and negative to remove. Removing more than the balance returns 409 `INSUFFICIENT_LOYALTY_POINTS`.
- `reason` shows in the customer's points history.
- A resend with the same `Idempotency-Key` does not add the points twice.
- The customer spends points at checkout. Your app cannot spend them for the customer.

## Not available

- Customer groups and tags.
- Marketing consent. The store does not record it per customer, so ask for it in your own app before you send marketing.
- The customer wallet, reading or changing it.
