Client
The JavaScript client object — initialization and core methods.
createEasyClient returns an EasyBrowserClient — the typed EasyApiClient from @easylabs/common decorated with browser-only helpers. One client wraps one API key. Construct it once at app startup and pass it around (via your DI container, a module-level singleton, or your framework's context primitive).
The factory validates the supplied key against GET /validate-key before resolving, so a successful await is your guarantee that the key works against the resolved environment.
Constructor
import { createEasyClient } from "@easylabs/browser";
const easy = await createEasyClient({
apiKey: "sk_test_...",
});Options
| Option | Type | Required | Description |
|---|---|---|---|
apiKey | string | yes | Your Easy Labs secret key. Keys prefixed sk_test_ route to the sandbox environment; everything else routes to production. |
__internal_api_url | string | no | Internal. Override the resolved API base URL. Used for tests and local development. Public consumers should leave this unset. |
__dev | boolean | no | Internal, deprecated. No-op. Kept on the type for source compatibility and will be removed in a future major. |
Throws
Error("apiKey is required to create an Easy Labs browser client.")ifapiKeyis empty.Error("API key validation failed: ...")if the key is rejected by/validate-key.- A network error if the API is unreachable.
Direct import
If you only need the embedded-checkout helper, you don't have to construct a client at all — mountEmbeddedCheckout is a tree-shakeable named export:
import { mountEmbeddedCheckout } from "@easylabs/browser";It authenticates against the session's client_secret, not your API key.
The Element factories (mountCardNumberElement, etc.) and the wallet button factories (createApplePayButton, createGooglePayButton) are also tree-shakeable named exports. Element factories require an initialised Basis Theory client — call createEasyClient first, or use configureBasisTheoryFromKey(apiKey, apiUrl) for a lighter bootstrap when you don't need the typed EasyApiClient surface.
Core methods
The returned client exposes the full EasyApiClient surface from @easylabs/common. A representative slice — these are all methods you call on the client instance (easy.createCustomer(...)):
| Method | Purpose |
|---|---|
createCustomer(data) / getCustomer(id) / getCustomers(params) | Customer CRUD. |
createEmbeddedCheckoutSession(data) | Mint a session server-side. Do not call from the browser — exposes your secret key. |
getEmbeddedCheckoutSession(id) | Fetch session status (open / complete / expired). |
validateEmbeddedCheckoutSession(body) / confirmEmbeddedCheckoutSession(body) | Iframe-context endpoints. Authenticate via client_secret, not the API key. |
getCryptoPaymentStatus(sessionId) | Poll a session's crypto payment state. |
createPaymentLink(payload) / getPaymentLinks(params) / getPaymentLink(id) | Payment-link CRUD. |
createPaymentInstrument(data) / updatePaymentInstrument(id, data) | Payment instrument management. |
getProducts(params) | List products. |
listInvoices(query) | List invoices with filters. |
For the complete surface, refer to the type definitions exported from @easylabs/common (re-exported from @easylabs/browser). Every method returns a typed ApiResponse<T> and throws EasyApiError on non-2xx responses.
Related exports
These are standalone factory functions exported from @easylabs/browser — they are not methods on the client returned by createEasyClient. Import them directly and call them with their own arguments:
| Export | Purpose |
|---|---|
mountEmbeddedCheckout(container, options) | Mount the hosted-checkout iframe. Authenticates against the session's client_secret, so no client construction is needed. See Embedded Checkout. |
mountCardNumberElement / mountCardExpirationDateElement / mountCardVerificationCodeElement / mountTextElement | Mount iframed PCI-isolated form fields. Require an initialised Basis Theory client (see below). See Elements. |
tokenize({ cardNumber, cardExpiration, cardCvc }) | Exchange three mounted card elements for a Basis Theory token reference. |
createApplePayButton / createGooglePayButton | Render native wallet buttons. See Wallet Checkout. |
configureBasisTheoryFromKey(apiKey, apiUrl?) | Lighter bootstrap for Element factories when you don't need the typed EasyApiClient surface. createEasyClient already runs this for you. |
Element factories require Basis Theory to be initialised first — call createEasyClient (which initialises it as part of bootstrap) or configureBasisTheoryFromKey before mounting any element.
Errors
Every API call rejects with an EasyApiError carrying the HTTP status, the API error code, and the parsed details payload:
import { EasyApiError } from "@easylabs/browser";
try {
await easy.cancelSubscription("sub_123");
} catch (err) {
if (err instanceof EasyApiError && err.status === 429) {
await new Promise((r) =>
setTimeout(r, (err.retryAfterSeconds ?? 1) * 1000),
);
} else {
throw err;
}
}Lifecycle
The client holds no long-lived resources — no sockets, no timers, no listeners. It's a thin façade over fetch plus an in-memory copy of your API key. You can construct it as many times as you want, but in practice one instance per app is the right shape.
There is no dispose or close. To "tear it down", drop your reference and let the garbage collector handle it.
mountEmbeddedCheckout does create resources (a <iframe> element and a window message listener). Call handle.unmount() when navigating away from the checkout — see Embedded Checkout › Cleanup.