# JavaScript SDK

> switchbox-js — the Switchbox class, methods, and options.

The browser SDK is published to npm as **`switchbox-js`**. It has **zero runtime
dependencies** — only the browser's `fetch` and Web Crypto APIs. Using React?
See the [React SDK](/docs/sdk/react), which wraps this one.

```bash
npm install switchbox-js
```

The same reference ships in the package [README on
npm](https://www.npmjs.com/package/switchbox-js).

## Switchbox.create(options)

```js
import { Switchbox } from 'switchbox-js';

const client = await Switchbox.create({
  sdkKey: 'your-sdk-key',
});
```

The recommended entry point. It constructs the client **and awaits the first
config fetch**, resolving to a client that's ready to evaluate. Create one and
reuse it.

Background refreshes are **conditional requests**: the SDK sends back the `ETag`
the edge gave it, so a poll that finds nothing changed returns an empty `304` with
no config body. In a browser that means steady-state polling costs your users
almost no bandwidth, whatever the size of your config. This is automatic, with
nothing to configure.

For advanced control you can split the two steps:

```js
const client = new Switchbox({ sdkKey: 'your-sdk-key' });
await client.init();
```

### Options

| Option | Type | Default | Description |
|---|---|---|---|
| `sdkKey` | `string` | — | The environment's SDK key from the dashboard. Required. |
| `cdnBaseUrl` | `string` | Switchbox edge | Override the CDN base URL (advanced). |
| `pollInterval` | `number` | `10` | Seconds between background config refreshes. |
| `onError` | `(error: Error) => void` | — | Called when a fetch or parse fails, or a hook you supplied throws. |
| `onEvaluation` | `(flagKey, result, user?) => void` | — | Called after every evaluation — wire it into your analytics. See [Measure in your own analytics](/docs/recipes/measure-in-your-analytics). |
| `telemetry` | `boolean` | `true` | Anonymous usage telemetry (see below). `false` disables it. |

## client.enabled(flagKey, user?)

```js
if (await client.enabled('new_checkout', { user_id: '42' })) {
  showNewCheckout();
}
```

Resolves to whether a boolean flag is enabled. Returns `false` if the flag is
absent. **Async** — evaluation uses Web Crypto for rollout hashing, so `await` it.

## client.getValue(flagKey, user?, defaultValue?)

```js
const algo = await client.getValue('search_algorithm', { user_id: '42' }, 'v1');
```

Resolves to a string, number, or JSON flag's value (a `json` flag comes back as a
parsed object/array), or `defaultValue` if the flag is absent.

## client.getAllFlags(user?)

```js
const all = await client.getAllFlags({ user_id: '42' });
// { dark_mode: true, search_algorithm: 'v2', max_results: 50 }
```

Resolves to every flag's value for the user. Empty object if no config is loaded.

## client.onConfigChange(callback)

```js
const unsubscribe = client.onConfigChange(() => {
  // a new config version arrived — re-read any flags you're displaying
});
```

Subscribes to config-version changes (fired after each successful background
poll). Returns an unsubscribe function. This is what the React hooks use to
re-render on a flag change.

## client.destroy()

```js
client.destroy();
```

Stops background polling. Call it when tearing down the client.

## The onEvaluation hook

```js
const client = await Switchbox.create({
  sdkKey: 'your-sdk-key',
  onEvaluation: (flagKey, value, user) => {
    // forward the exposure to your analytics
  },
});
```

Fires after every `enabled()` and `getValue()` call with the flag key, the
resolved value, and the user context you passed in. It is fire-and-forget: an
exception inside your handler never breaks the flag check (it is reported
through `onError`), and the hook carries no evaluation logic. Ready-made
handlers for PostHog, Amplitude, Segment, and GA4 are in
[Measure in your own analytics](/docs/recipes/measure-in-your-analytics).

## Anonymous usage telemetry

The SDK reports anonymous aggregate usage — per-flag evaluation counts and
value distribution, with **no identity, no user context, and no cookies** —
which powers the dashboard's flag usage panel. On by default; pass
`telemetry: false` to disable it. Exactly what is sent and shown is documented
in [Connection & usage](/docs/dashboard/monitoring).

## Why evaluation is async

`enabled()` and `getValue()` return promises because rollout bucketing uses the
browser's asynchronous Web Crypto digest. After the first fetch there's no network
involved — the `await` resolves on the same tick — but the methods stay async to
keep one hashing implementation across platforms.

## Offline behaviour

If a fetch fails, the SDK keeps serving the last good config. If it has never
fetched one, `enabled()` resolves to `false` and `getValue()` to your default.
Errors are routed to `onError` rather than thrown.

## Next

- [React SDK](/docs/sdk/react) — hooks and the `<Feature>` component.
- [Evaluation order](/docs/reference/evaluation-order).
- [Use with OpenFeature](/docs/sdk/openfeature): the vendor-neutral API, with Switchbox as one line.
