Skip to main content

Guides

TypeScript SDK

The @browlix/sdk package — typed calls for every operation, safe retries, session helpers and webhook verification.

View as Markdown

@browlix/sdk has no runtime dependencies and works in Node 20 or later, Bun, Deno, Cloudflare Workers and browsers that may hold a key.

Install

The package is published by Browlix, with its SHA-256 on the download page:

bash
npm i https://browlix.com/api/public/sdk/v1/download/latest

Create a client

ts
import { Browlix, BrowlixError } from "@browlix/sdk";

const bx = new Browlix({ apiKey: process.env.BROWLIX_API_KEY! }); // the SDK never reads env itself

Options: baseUrl (default https://browlix.com), attempts for safe retries (default 3), timeoutMs per request (default 60 s), and a custom fetch.

Call any operation

ts
const { data, page } = await bx.call("profiles.list", { query: { limit: 20, os: "windows" } });

for await (const profile of bx.paginate("profiles.list", { state: "active" })) {
  console.log(profile);
}

call(id, { path, query, body }) is typed from the OpenAPI document for each operation id: the input always, and from SDK 0.9.0 also data for every operation whose reply fields are published in the reference (profiles, sessions, bindings, devices, feedback, workspace). OPERATIONS lists them. New reply fields can appear without notice — see Versions and changelog.

Writes

Writes get a command_id when you omit one and report it as reply.commandId. Automatic retries resend the same id, so nothing is applied twice. After OUTCOME_UNKNOWN, read the result with bx.receipt(commandId).

Sessions

ts
const s = await bx.startSession({ profileId, deviceId, wait: { timeoutMs: 120_000 } });
const a = await bx.attach(s.data.id);
// … connect Playwright on this machine with a.endpoint and a.headers …
await bx.stopSession(s.data.id);

waitForSession and startSession({ wait }) only wait. Aborting with signal (INTERRUPTED) or timing out (WAIT_TIMEOUT) leaves the session running. stopSession is the only call that ends one.

Errors

Every failure is a BrowlixError with the API's code, retryable, and info (status, details, correlationId, commandId, retryAfterSeconds). Key-shaped text is redacted from messages.

ts
try {
  await bx.call("sessions.start", { body: { profile_id: profileId, device_id: deviceId } });
} catch (e) {
  if (e instanceof BrowlixError && e.code === "BUSY") console.log("BUSY", e.info.details);
  else throw e;
}

Webhooks

verifyWebhook(secret, headers, rawBody) checks a Standard Webhooks signature and timestamp (5-minute tolerance) and returns the parsed event — see Webhooks.