> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://platform.bctrl.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://platform.bctrl.ai/_mcp/server.

# Multi-Tenant Isolation

> One subaccount per customer - scoped keys, hard limits, and per-customer usage metering.

Reselling browser automation to your own customers? Give each one a [subaccount](/sdk/account): an isolated, separately-metered environment under your organization. A key scoped to it can't see anything else, and limits stop one customer from eating your capacity.

```ts
import { Bctrl } from "@bctrl/sdk";

const bctrl = new Bctrl({ apiKey: process.env.BCTRL_API_KEY! }); // parent org key

// 1. One subaccount per customer, keyed by your own id.
const sub = await bctrl.subaccounts.create({
  name: "Acme Corp",
  externalId: "acme", // your tenant id - look it up later with list({ externalId })
  limits: {
    monthlyCredits: 50_000,
    maxConcurrentRuntimes: 5,
  },
});

// 2. Mint a key confined to that subaccount.
const key = await bctrl.apiKeys.create({ name: "acme-key", subaccountId: sub.id });
console.log(key.secret); // shown once - store it now

// 3. A client on the scoped key lives entirely inside Acme's world.
const acme = new Bctrl({ apiKey: key.secret });
const runtime = await acme.runtimes.create({ type: "browser", name: "acme-task" });
// runtimes, runs, vault secrets, files - all isolated to the subaccount.

// 4. Meter every customer in one call.
const usage = await bctrl.subaccounts.usage.list();
for (const row of usage.data) {
  console.log(row);
}
```

The scoped client is the whole tenancy model: run it server-side per tenant and every recipe in this cookbook - [live embeds](/cookbook/embed-live-view), [replays](/cookbook/customer-replay), [vault logins](/cookbook/vault-login) - is automatically confined to that customer. Embed URLs minted from Acme's client can only ever show Acme's runs, which is exactly what you want when the iframe lands in Acme's dashboard.

A parent-org key can still reach into any subaccount for support and admin; a subaccount key can never reach out.

## Lifecycle

When a customer churns, archive rather than delete - the usage history stays readable for billing:

```ts
await bctrl.subaccounts.archive(sub.id);
```

## Next

* [Account & Org](/sdk/account) - keys, subaccounts, usage in depth
* [Embed a Live Browser View](/cookbook/embed-live-view) - the customer-facing surface
* [Pricing: Subaccount billing](/pricing/subaccounts) - how metering maps to billing