Customer Management
Customer Management pattern for JavaScript.
This recipe shows how to use the typed EasyApiClient surface from @easylabs/browser to build a small "manage customers" UI — list, create, look up, paginate. It assumes you've already constructed a client per the Quickstart.
A note on environments: @easylabs/browser is designed so the same client can run on the server (it's a thin fetch wrapper). For data-mutation flows like creating customers, decide deliberately whether the call belongs in the browser (with a key scoped accordingly) or behind your own backend endpoint. The examples below assume server-side execution unless noted.
Goal
Build the four common customer-management touch points:
- List customers with pagination.
- Look up a single customer by id.
- Create a new customer.
- Surface their payment instruments and active subscriptions.
Implementation
Setup
import { createEasyClient, EasyApiError } from "@easylabs/browser";
const easy = await createEasyClient({ apiKey: process.env.EASY_API_KEY! });List customers
getCustomers takes optional pagination params:
const { data: customers } = await easy.getCustomers({
limit: 25,
offset: 0,
});For a "load more" UI, increment offset by limit. To fetch a specific subset by id:
const { data } = await easy.getCustomers({ ids: ["cus_abc", "cus_def"] });Look up one customer
async function loadCustomer(id: string) {
try {
const { data } = await easy.getCustomer(id);
return data;
} catch (err) {
if (err instanceof EasyApiError && err.status === 404) {
return null;
}
throw err;
}
}Create a customer
CreateCustomer requires first_name and last_name; everything else is optional.
const { data: customer } = await easy.createCustomer({
first_name: "Ada",
last_name: "Lovelace",
email: "ada@example.com",
phone: "+15555550123",
personal_address: {
line1: "10 Downing St",
city: "London",
region: "GB",
postal_code: "SW1A 2AA",
country: "GB",
},
tags: { source: "signup_v2" },
});
console.log(customer.id);Fetch related resources
A few convenience endpoints sit alongside the core CRUD methods:
const { data: instruments } = await easy.getCustomerPaymentInstruments(
customer.id,
);
const { data: subscriptions } = await easy.getCustomerSubscriptions(
customer.id,
{ status: "active" },
);
const { data: orders } = await easy.getCustomerOrders(customer.id, {
limit: 10,
});
const { data: wallets } = await easy.getCustomerWallets(customer.id);getCustomerSubscriptions returns a Paginated<SubscriptionData> so you can drive infinite scroll off data.has_more if your shape requires it.
Update a customer
updateCustomer accepts a partial:
await easy.updateCustomer(customer.id, {
email: "ada+billing@example.com",
});Tradeoffs
- Browser vs. server.
EasyApiClientworks in both contexts, but mutations from the browser ship your API key to every user who loads the page. For anything beyond read-only utility flows, run mutations server-side and expose a thin endpoint. - Pagination ceilings.
limitis bounded by the API (see your tier's limits). Don't request unbounded list calls in a hot loop — paginate explicitly. - Error shape. Always branch on
EasyApiError.status/err.coderather than string-matchingerr.message. Themessageincludes the JSON-stringified error body and is intended for logs, not control flow. - Identity coupling. A
CustomerDataobject includes the underlying processor identity payload (entity,_links). Treat anything outside the documented top-level fields as opaque — it's there for advanced flows but not part of the stable contract.