SUQODocs
User GuideAPI ReferenceSDKs

Customers

Listing, retrieving, creating and updating customers with the SUQO PHP SDK.

Five operations: list(), autoPaging(), read(), create() and update(). A customer record is also created implicitly the first time someone subscribes, through subscriptions->create()'s customer field; create() records one without opening a subscription.

Listing

$page = $suqo->customers->list(pageSize: 50);

echo $page->count, PHP_EOL;

foreach ($page->results as $customer) {
    echo $customer->id, ' ', $customer->buyerPhone, PHP_EOL;
    echo '  ', $customer->fullName ?? '(no name)', PHP_EOL;
}

Or walk every page without page math:

foreach ($suqo->customers->autoPaging() as $customer) {
    handle($customer);
}

Retrieving one

$customer = $suqo->customers->read('cus_0390b1820');

echo $customer->buyerEmail ?? '-', PHP_EOL;

The method is read(), not retrieve() — the name comes from the operation the API declares. A 404 also covers an id belonging to the other environment; the two look identical.

Creating one

use Suqo\Params\CustomerCreateParams;

$customer = $suqo->customers->create(new CustomerCreateParams(
    email: '[email protected]',
    phone: '9810000001',
    fullName: 'Ram Bahadur',
    address: 'Kathmandu, Nepal',
));

echo $customer->id, PHP_EOL;   // cus_2a108b4eb

Only email is required. The call is an upsert, and that is what makes it safe to retry. An email or phone your account already holds corrects that customer and answers 200 instead of 201 — nothing in the return value distinguishes them, so compare id or createdAt if you need to know which happened.

phone must be a Nepali mobile number — ten digits starting 96, 97 or 98. A +977 country code, a leading zero, spaces and dashes are accepted and stripped server-side. It identifies the buyer and cannot be changed afterwards. The name and address are your account's own copy of the buyer's details, not a shared profile — they are not visible to other sellers.

What you send and what you read back are spelled differently: phone and email go out under those names and come back as buyerPhone and buyerEmail.

Throws ValidationError on 400 — a missing email, a rejected phone, or {"email": ["You cannot add yourself as a customer."]}.

Updating one

use Suqo\Params\CustomerUpdateParams;

// Rename, leave everything else alone.
$suqo->customers->update('cus_2a108b4eb', new CustomerUpdateParams(
    fullName: 'Ram Bahadur',
));

// Clear the address.
$suqo->customers->update('cus_2a108b4eb', new CustomerUpdateParams(address: ''));

Every field is optional, and null and '' are different instructions: leaving a field null omits it from the body, while passing '' sends it and clears it.

The phone identifies the buyer and cannot be changed — it is accepted only at its current value, raising ValidationError with {"phone": ["Phone cannot be changed."]} otherwise. It exists on CustomerUpdateParams only so a round trip through toArray() can resend it unchanged; leave it null in ordinary use.

Throws NotFoundError on 404, ValidationError on 400.

Shape

Suqo\Model\Customer — id, buyerPhone, buyerEmail, fullName, address, createdAt, all ?string, plus toArray().

id is a prefixed public id (cus_0390b1820) — not an integer, and not a UUID like the subscription ids elsewhere in the API.

Every field except id, buyerPhone and createdAt can be null in practice: a record with only a phone number on file is normal. createdAt carries microseconds and a +05:45 offset rather than Z, and is kept as an opaque string like every other timestamp.

Not the same shape as a subscription's customer

buyerPhone and buyerEmail keep their wire stems here. The customer embedded on a subscription is a different type — SubscriptionCustomer, with phone / fullName / email and no prefix, plus nested billing and shipping. Both describe a buyer; they are not the same record, and the SDK never conflates them.

On this page