Customers
The shop's customer accounts: find them, add them, and set the wholesale membership that prices their carts.
Reach them through $admin->customers. Reading needs the customers:read scope, changing them customers:write.
List customers
$admin->customers->list(array $query = []): array
One page of the shop's customers, by words in the name, email or phone, or an exact email; or oldest change first with updatedSince. Read the next page with meta.nextCursor as cursor. Scope: customers:read.
Parameters
| Parameter |
Type |
|
$query |
array |
The query fields below, by name. |
Query fields
| Parameter | Type | Description |
|---|
search | string | At most 200 characters. |
email | string | An exact email (case-insensitive). At most 255 characters. |
limit | integer | At least 1. At most 100. Default 50. |
cursor | string | meta.nextCursor (or the cursor in links.next) of the previous page. At most 1000 characters. |
updatedSince | string (date-time) | Records changed at or after this time (ISO 8601, any offset or Z), oldest change first, for incremental sync. |
Returns
An array with data (a list of AdminCustomer), links and meta:
| Field | Type | Description |
|---|
links | object | |
links.first | null | |
links.last | null | |
links.prev | string (uri) or null | |
links.next | string (uri) or null | |
meta | object | |
meta.path | string (uri) | |
meta.perPage | integer | |
meta.nextCursor | string or null | |
meta.prevCursor | string or null | |
data | array of AdminCustomer | |
data[].id | integer | |
data[].name | string | |
data[].email | string or null | |
data[].emailVerified | boolean | |
data[].phone | string or null | |
data[].phoneVerified | boolean | |
data[].wholesale | boolean | |
data[].wholesaleMembershipId | integer or null | |
data[].createdAt | string (date-time) or null | |
data[].updatedAt | string (date-time) or null | |
Errors
| Status | When |
|---|
401 | invalid_api_key: no active Admin key in Authorization: Bearer. |
403 | admin_key_in_browser (an Origin header was sent), ip_not_allowed, plan_required(the shop's plan lacks the Integration API, or the feature the endpoint needs), orinsufficient_scope. |
422 | Validation errors ({ message, errors }), or an idempotency refusal(idempotency_key_reused, idempotency_key_invalid). |
429 | Rate limited. |
Example
$page = $admin->customers->list(['email' => '[email protected]']);
$customer = $page['data'][0] ?? null;
Iterate over every customer
$admin->customers->all(array $query = []): Generator
Every customer matching the query, one at a time, fetching the next page as you read. It takes the same query as list, without cursor. Scope: customers:read.
Returns
A generator of AdminCustomer arrays, each:
| Field | Type | Description |
|---|
[].id | integer | |
[].name | string | |
[].email | string or null | |
[].emailVerified | boolean | |
[].phone | string or null | |
[].phoneVerified | boolean | |
[].wholesale | boolean | |
[].wholesaleMembershipId | integer or null | |
[].createdAt | string (date-time) or null | |
[].updatedAt | string (date-time) or null | |
Example
foreach ($admin->customers->all(['updatedSince' => $lastSyncedAt]) as $customer) {
$crm->saveCustomer($customer);
}
Get a customer
$admin->customers->get(int $id): array
One customer by their id. Scope: customers:read.
Parameters
| Parameter |
Type |
|
$id |
int |
The customer's id. |
Returns
An AdminCustomer:
| Field | Type | Description |
|---|
id | integer | |
name | string | |
email | string or null | |
emailVerified | boolean | |
phone | string or null | |
phoneVerified | boolean | |
wholesale | boolean | |
wholesaleMembershipId | integer or null | |
createdAt | string (date-time) or null | |
updatedAt | string (date-time) or null | |
Errors
| Status | When |
|---|
401 | invalid_api_key: no active Admin key in Authorization: Bearer. |
403 | admin_key_in_browser (an Origin header was sent), ip_not_allowed, plan_required(the shop's plan lacks the Integration API, or the feature the endpoint needs), orinsufficient_scope. |
404 | not_found: the shop has no such record. |
429 | Rate limited. |
Create a customer
$admin->customers->create(array $input, string|false|null $idempotencyKey = null): array
A new customer, emailed at once to choose a password. The email, and the phone when given, must be unique in the shop. Scope: customers:write.
Parameters
| Parameter |
Type |
|
$input |
array |
The customer's fields, below. |
$idempotencyKey |
string|false|null |
Your own Idempotency-Key, or false for none. One is made for you when null. |
Request fields
| Field | Type | Description |
|---|
name required | string | At most 255 characters. |
email required | string (email) | Unique in the shop. At most 255 characters. |
phone | string or null | Unique in the shop. At most 50 characters. |
Returns
The new AdminCustomer:
| Field | Type | Description |
|---|
id | integer | |
name | string | |
email | string or null | |
emailVerified | boolean | |
phone | string or null | |
phoneVerified | boolean | |
wholesale | boolean | |
wholesaleMembershipId | integer or null | |
createdAt | string (date-time) or null | |
updatedAt | string (date-time) or null | |
Errors
| Status | When |
|---|
401 | invalid_api_key: no active Admin key in Authorization: Bearer. |
403 | admin_key_in_browser (an Origin header was sent), ip_not_allowed, plan_required(the shop's plan lacks the Integration API, or the feature the endpoint needs), orinsufficient_scope. |
409 | idempotency_in_progress: a request with this Idempotency-Key is still running. Retry with the same key after Retry-After seconds; the first answer is then replayed. |
422 | Validation errors ({ message, errors }), or an idempotency refusal(idempotency_key_reused, idempotency_key_invalid). |
429 | Rate limited. |
Example
$customer = $admin->customers->create([
'name' => 'Sara Ali',
'email' => '[email protected]',
]);
Set a wholesale membership
$admin->customers->setMembership(
int $id,
?int $wholesaleMembershipId,
DateTimeInterface|string|null $unmodifiedSince = null,
string|false|null $idempotencyKey = null,
): array
Puts the customer in one of the shop's wholesale memberships, or back to retail with null. Business plan (403 plan_required). Scope: customers:write.
Parameters
| Parameter |
Type |
|
$id |
int |
The customer's id. |
$wholesaleMembershipId |
int|null |
The membership's id, or null for retail. |
$unmodifiedSince |
DateTimeInterface|string|null |
The customer's updatedAt as you read it. If it changed since, the change is refused with 409 edit_conflict. |
$idempotencyKey |
string|false|null |
Your own Idempotency-Key, or false for none. |
Request fields
The SDK sends the membership id as wholesaleMembershipId:
| Field | Type | Description |
|---|
wholesaleMembershipId required | integer or null | |
updatedAt | string (date-time) or null | The record's updatedAt as you read it; a newer record gets 409 edit_conflict. |
Returns
The changed AdminCustomer:
| Field | Type | Description |
|---|
id | integer | |
name | string | |
email | string or null | |
emailVerified | boolean | |
phone | string or null | |
phoneVerified | boolean | |
wholesale | boolean | |
wholesaleMembershipId | integer or null | |
createdAt | string (date-time) or null | |
updatedAt | string (date-time) or null | |
Errors
| Status | When |
|---|
401 | invalid_api_key: no active Admin key in Authorization: Bearer. |
403 | admin_key_in_browser (an Origin header was sent), ip_not_allowed, plan_required(the shop's plan lacks the Integration API, or the feature the endpoint needs), orinsufficient_scope. |
404 | not_found: the shop has no such record. |
409 | edit_conflict (the record changed after If-Unmodified-Since or updatedAt), or idempotency_in_progress. |
422 | Validation errors ({ message, errors }), or an idempotency refusal(idempotency_key_reused, idempotency_key_invalid). |
429 | Rate limited. |
Example
$customer = $admin->customers->get(88);
$admin->customers->setMembership(88, 3, unmodifiedSince: $customer['updatedAt']);