> ## Documentation Index
> Fetch the complete documentation index at: https://docs.endstate.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Server

> EndstateClient: the full API surface with a secret key, plus the waitUntil helpers, pagination, and the typed escape hatch.

`EndstateClient` takes a secret key (`end_sk_...`) and reaches every operation
in the spec. It runs on your server only.

```ts theme={null}
import { EndstateClient, secretKey } from "@endstate-sdk/core";

const endstate = new EndstateClient({
  apiKey: secretKey(process.env.ENDSTATE_API_KEY),
});
```

<Warning>
  Never construct `EndstateClient` in browser or Electron-renderer code. A
  secret key grants full access to your organization. For the browser, see
  [Browser](/sdks/core/browser).
</Warning>

## Resources

Every operation is grouped by resource. Each method has its own reference page
with the endpoint it calls, the credential it needs, and its retry class.

| Resource                    | Methods                                                                                                                                                                                                                                                                             |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `endstate.units`            | [`list`](/sdks/core/reference/units/list) · [`get`](/sdks/core/reference/units/get) · [`create`](/sdks/core/reference/units/create) · [`update`](/sdks/core/reference/units/update) · [`waitUntilIssued`](/sdks/core/reference/units/waitUntilIssued)                               |
| `endstate.collections`      | [`list`](/sdks/core/reference/collections/list) · [`get`](/sdks/core/reference/collections/get) · [`create`](/sdks/core/reference/collections/create) · [`update`](/sdks/core/reference/collections/update) · [`waitUntilActive`](/sdks/core/reference/collections/waitUntilActive) |
| `endstate.chips`            | [`list`](/sdks/core/reference/chips/list) · [`get`](/sdks/core/reference/chips/get) · [`pair`](/sdks/core/reference/chips/pair) · [`pairBulk`](/sdks/core/reference/chips/pairBulk)                                                                                                 |
| `endstate.taps`             | [`list`](/sdks/core/reference/taps/list) · [`create`](/sdks/core/reference/taps/create)                                                                                                                                                                                             |
| `endstate.chipReplacements` | [`get`](/sdks/core/reference/chip-replacements/get) · [`create`](/sdks/core/reference/chip-replacements/create) · [`waitUntilSettled`](/sdks/core/reference/chip-replacements/waitUntilSettled)                                                                                     |
| `endstate.claims`           | [`get`](/sdks/core/reference/claims/get)                                                                                                                                                                                                                                            |
| `endstate.transfers`        | [`get`](/sdks/core/reference/transfers/get)                                                                                                                                                                                                                                         |
| `endstate.settings`         | [`get`](/sdks/core/reference/settings/get) · [`update`](/sdks/core/reference/settings/update)                                                                                                                                                                                       |
| `endstate.publishableKeys`  | [`list`](/sdks/core/reference/publishable-keys/list)                                                                                                                                                                                                                                |
| `endstate.testHelpers`      | [`createTap`](/sdks/core/reference/test-helpers/createTap)                                                                                                                                                                                                                          |
| `endstate.service`          | [`health`](/sdks/core/reference/service/health) · [`info`](/sdks/core/reference/service/info)                                                                                                                                                                                       |

## Waiting for work to finish

Issuance and provisioning are asynchronous. Rather than writing your own poll
loop, use the `waitUntil` helpers - they share one polling primitive with
exponential backoff, and they throw `EndstateTerminalStateError` when
something settles in a failed state instead of polling until your budget runs
out.

```ts theme={null}
const collection = await endstate.collections.create({
  external_id: "fw26",
  name: "FW26 Outerwear",
});
await endstate.collections.waitUntilActive(collection.id);

const unit = await endstate.units.create({
  collection_id: collection.id,
  external_id: "jacket-0001",
});
await endstate.units.waitUntilIssued(unit.id);
```

Each accepts `{ timeoutMs, intervalMs, maxIntervalMs, signal, onPoll }`.

## Pagination

A list call is both awaitable and iterable. Await it for one page exactly as
the API returns it; iterate it for items across every page, following
`next_cursor` for you.

```ts theme={null}
// One page, verbatim - including the `pagination` envelope.
const page = await endstate.units.list({ limit: 50 });
page.pagination.has_more;

// Every unit, across pages.
for await (const unit of endstate.units.list()) {
  console.log(unit.external_id);
}

// Or collect, optionally bounded.
const first200 = await endstate.units.list().all({ maxItems: 200 });
```

[Cursors are opaque](/conventions/pagination) - pass `next_cursor` back
unchanged and never parse one.

## Issuing a session for a browser

A secret key may verify a tap on your server and hand the resulting session
token to a page. Unlike a publishable key, it may also set `ttl`.

```ts theme={null}
const session = await endstate.verify({ chip_id: chipId, e, c }, { ttl: 900 });

// Safe to send to the browser; your API key is not.
return { token: session.token, unit: session.item };
```

The page adopts it with `endstate.session(token)`. See
[Tap sessions](/sdks/core/tap-sessions).

## Environments

`baseUrl` is explicit and defaults to production. The SDK does not infer an
environment from your credential's prefix.

```ts theme={null}
import { ENDSTATE_STAGING_API_URL } from "@endstate-sdk/core";

new EndstateClient({ apiKey, baseUrl: ENDSTATE_STAGING_API_URL });
```

See [Environments](/environments) for what each one is for.

## Anything a method does not cover

Every operation in the spec is reachable by id, typed to the credential you
constructed the client with, so a new endpoint is usable before a convenience
method exists for it.

```ts theme={null}
const unit = await endstate.request("getUnit", { path: { unit_id: unitId } });

// Same call, plus request id, rate-limit headers, replay flag, attempt count.
const { data, meta } = await endstate.requestWithMeta("getUnit", {
  path: { unit_id: unitId },
});
meta.requestId;
```

The operation ids are the same ones in the
[API reference](/api-reference/introduction), and `OPERATIONS` exports the full
table if you need to inspect it at runtime.
