> ## 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.

# EndstateProvider

> Holds one client, the active tap session from the landing tap, and one optional, auth-gated wallet. Wrap your tree in it, then read state through the hooks.

```ts theme={null}
function EndstateProvider(props: EndstateProviderProps): ReactElement;

interface EndstateProviderProps {
  publishableKey:
    | EndstatePublishableKey
    | (() => EndstatePublishableKey | Promise<EndstatePublishableKey>);
  wallet?: EndstateWalletConfig;
  tapSources?: readonly TapSource[];
  autoVerify?: boolean; // default true
  baseUrl?: string;
  children: ReactNode;
}

interface EndstateWalletConfig {
  getIdentityToken: () => string | Promise<string>;
  enabled?: boolean; // auth-readiness gate; default true
  container?: HTMLElement;
  timeouts?: { frameReadyMs?: number; sessionMs?: number };
}
```

`EndstateProvider` is the root of the React surface, imported from `@endstate-sdk/web/react`. It constructs one [`EndstatePublicClient`](/sdks/core/reference/client/EndstatePublicClient) for its lifetime, captures and verifies the landing redirect tap on mount (unless `autoVerify` is `false`), and, when a `wallet` is configured, provisions the customer's wallet. Every hook - [`useSession`](/sdks/web/reference/react/useSession), [`useWallet`](/sdks/web/reference/react/useWallet), [`useTap`](/sdks/web/reference/react/useTap), [`useClaim`](/sdks/web/reference/react/useClaim), [`useTransfer`](/sdks/web/reference/react/useTransfer), and [`useEndstateClient`](/sdks/web/reference/react/useEndstateClient) - reads from this one provider and throws if used outside it.

React is an optional peer dependency (`^19`), needed only for the `/react` subpath. The package root stays React-free.

## Example

```tsx theme={null}
"use client";
import { EndstateProvider } from "@endstate-sdk/web/react";

function App() {
  return (
    <EndstateProvider
      publishableKey="end_pk_..."
      wallet={{
        // A fresh, single-use identity credential minted by your own backend.
        // Placeholder for your mint call - never a cached value.
        getIdentityToken: () => mintIdentityToken(),
        // Auth gate: hold provisioning until your customer is signed in.
        enabled: isSignedIn,
      }}
    >
      <YourApp />
    </EndstateProvider>
  );
}
```

`EndstateProvider` renders in the browser. Mount it inside a Client Component (`"use client"`); capture, verify, and wallet provisioning all run in effects, so server rendering is a no-op.

## Parameters

<ParamField body="publishableKey" type="EndstatePublishableKey | (() => EndstatePublishableKey | Promise<EndstatePublishableKey>)" required>
  Your publishable key (`end_pk_...`), or a function that returns one (sync or
  async) when you resolve it at runtime. A secret key is rejected by the type
  and again at runtime. Narrow and validate a string with
  [`publishableKey()`](/sdks/core/reference/browser/publishableKey) from core.
</ParamField>

<ParamField body="wallet" type="EndstateWalletConfig">
  Configures the customer wallet. Omit it entirely on pages that do not
  provision a wallet - the tap flow needs no wallet. When present, its
  `getIdentityToken` callback supplies the identity credential and `enabled`
  gates when provisioning starts. See the wallet fields below.
</ParamField>

<ParamField body="tapSources" type="readonly TapSource[]">
  Tap sources the client dispatches to. Defaults to
  [`defaultTapSources()`](/sdks/web/reference/tap-sources/defaultTapSources) -
  the landing redirect plus in-page Web NFC where the device supports it.
</ParamField>

<ParamField body="autoVerify" type="boolean" default="true">
  When `true` (the default), the provider captures the landing redirect tap and
  verifies it on mount, so a page opened by a tap has a session ready without
  any extra call. Set it to `false` to capture and verify yourself through
  [`useSession().verify`](/sdks/web/reference/react/useSession) or
  [`useTap`](/sdks/web/reference/react/useTap).
</ParamField>

<ParamField body="baseUrl" type="string">
  Overrides the API base URL the client calls. Leave it unset in product code;
  it exists for testing against a non-default host.
</ParamField>

<ParamField body="children" type="ReactNode" required>
  The subtree that reads Endstate state through the hooks.
</ParamField>

## Wallet configuration

The optional `wallet` prop takes an `EndstateWalletConfig`:

<ParamField body="getIdentityToken" type="() => string | Promise<string>" required>
  Supplies the identity credential each wallet session is established from. It
  is called fresh for every session establishment and must never return a cached
  value - the credential is single-use and short-lived. Your own backend mints
  it from your login; it is a placeholder function here (`getIdentityToken: ()   => mintIdentityToken()`), never a fake fetch route. See [the identity
  credential](/sdks/web/wallet#the-identity-credential) and [Bring your own
  auth](/external-auth).
</ParamField>

<ParamField body="enabled" type="boolean" default="true">
  Auth-readiness gate. Provisioning waits until this is `true`, so pass your
  sign-in state (`enabled: isSignedIn`) to defer wallet setup until the customer
  is authenticated. Left at its default (`true`), provisioning starts at mount,
  which preserves page-load setup timing for apps with no auth gate.
</ParamField>

<ParamField body="container" type="HTMLElement" default="document.body">
  Where the hidden wallet frame is appended. Override only when `document.body`
  is not the right mount point.
</ParamField>

<ParamField body="timeouts" type="{ frameReadyMs?: number; sessionMs?: number }">
  Wait budgets in milliseconds. `frameReadyMs` bounds the frame handshake
  (default `5000`); `sessionMs` bounds identity issuance and session
  establishment (default `30000`). A stage that exceeds its budget fails with
  `wallet.timeout`.
</ParamField>

<Note>
  The wallet frame is provisioned only while `enabled` is `true`. With `enabled:
      false`, [`useWallet().status`](/sdks/web/reference/react/useWallet) reports
  `"idle"` and no identity credential is requested; it flips to `"provisioning"`
  the moment the gate opens.
</Note>

<Note>
  There is no `environment` field. The wallet frame origin is compiled into the
  package and is not configurable from the browser - a security property of the
  design.
</Note>

## Returns

A React element that provides Endstate context to `children`. Read state through
the hooks below.

## See also

<CardGroup cols={2}>
  <Card title="useSession" icon="badge-check" href="/sdks/web/reference/react/useSession">
    The verified item and session status from the landing tap.
  </Card>

  <Card title="useWallet" icon="wallet" href="/sdks/web/reference/react/useWallet">
    The provisioned account, status, and refresh.
  </Card>

  <Card title="useClaim" icon="hand" href="/sdks/web/reference/react/useClaim">
    Claim ownership in a single call.
  </Card>

  <Card title="createEndstateClient" icon="box" href="/sdks/web/reference/createEndstateClient">
    The vanilla client factory, for pages without React.
  </Card>
</CardGroup>
