# List customers

Store customers, oldest first, with phone, email, order count and total spent. Find one by phone or email.

```http
GET https://larm.sa/stores/{storeId}/v1/customers
```

Scope: `customers.list:read`

`phone` accepts any Saudi form: `05…`, `5…`, `9665…` or `+9665…`. `email` is an exact match. `search` looks in the name and email. To keep in sync, pass the time of your last sync in `created_after`, then listen for the customer events. `orders_count` and `total_spent` cover delivered orders that were not refunded. See [Customers and loyalty](/guides/customers-and-loyalty).

## Query parameters

| Field | Type | Required | Description |
|---|---|---|---|
| `limit` | integer = 25 | no | Number of items per page. |
| `cursor` | string | no | The meta.next_cursor value from the previous page. Valid for 15 minutes and bound to the same filters. |
| `email` | string | no | An exact email. Upper and lower case count as the same. |
| `phone` | string | no | The phone in any form: 05xxxxxxxx or +9665xxxxxxxx. |
| `search` | string | no | Search in the name and email. |
| `created_after` | string (date-time) | no | Customers who signed up after this time. |


## Response

| Field | Type | Required | Description |
|---|---|---|---|
| `data` | array<object> | yes |  |
| `data[].id` | string | yes |  |
| `data[].name` | string | yes |  |
| `data[].first_name` | string | no |  |
| `data[].last_name` | string | no |  |
| `data[].phone` | string \| null | yes | Phone number in E.164 format, such as +966512345678, or null if it is not a valid number. |
| `data[].email` | string \| null (email) | yes |  |
| `data[].orders_count` | integer | yes | Delivered orders that were not refunded. |
| `data[].total_spent` | string | yes | The total of those orders in SAR. |
| `data[].last_order_at` | string \| null (date-time) | no |  |
| `data[].created_at` | string (date-time) | yes |  |
| `execution` | object | no | Who executed the request: the app, version, installation and store. Field names here are camelCase. |
| `execution.appId` | string (uuid) | no |  |
| `execution.versionId` | string (uuid) | no |  |
| `execution.installationId` | string (uuid) | no |  |
| `execution.storeId` | string (uuid) | no |  |
| `execution.requestId` | string (uuid) | no |  |
| `execution.generation` | integer | no |  |
| `execution.routeEpoch` | integer | no |  |
| `execution.appAuthEpoch` | integer | no |  |
| `execution.grantRevision` | integer | no |  |
| `meta` | object | yes |  |
| `meta.has_more` | boolean | no |  |
| `meta.limit` | integer | no |  |
| `meta.next_cursor` | string \| null | no |  |
| `meta.consistency` | string | no | One of: `live_keyset`. |
| `meta.request_id` | string (uuid) | no |  |


## Example request

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


## Example response (200)

```json
{
  "data": [
    {
      "id": "5821",
      "name": "Sara Alotaibi",
      "first_name": "Sara",
      "last_name": "Alotaibi",
      "phone": "+966512345678",
      "email": "sara@example.com",
      "orders_count": 4,
      "total_spent": "820.00",
      "last_order_at": "2026-10-15T09:12:44Z",
      "created_at": "2026-03-02T16:20:11Z"
    }
  ],
  "execution": {
    "appId": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
    "versionId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
    "installationId": "c7e4a1f2-6b3d-4e8a-9c05-1d2f3a4b5c6d",
    "storeId": "5b1d7a62-0c4e-4f38-9a51-2e7b3c9d8f10",
    "requestId": "3f0c2b8e-7a51-4c1e-9d0a-5b6f1e2d4c3a",
    "generation": 1,
    "routeEpoch": 4,
    "appAuthEpoch": 1,
    "grantRevision": 2
  },
  "meta": {
    "next_cursor": null,
    "request_id": "3f0c2b8e-7a51-4c1e-9d0a-5b6f1e2d4c3a"
  }
}
```


## Errors

| HTTP | Code | Meaning |
|---|---|---|
| 400 | `INVALID_FILTER` | Unknown filter or invalid value. |
| 400 | `CURSOR_MISMATCH` | The cursor was issued for different filters. |
| 403 | `SCOPE_REQUIRED` | The token does not carry the required scope. |
| 503 | `APPS_SCOPE_RUNTIME_NOT_READY` | The resource is not enabled on this merchant's store yet. |
