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

# useSession

> The active tap session, the verified item read off it, and where the capture-and-verify flow currently stands.

```ts theme={null}
function useSession(): {
  session: TapSession | null;
  item: TapResponse["unit"] | null;
  status: SessionStatus;
  error: Error | null;
  verify: (tap: TapInput) => Promise<TapSession>;
};

type SessionStatus = "idle" | "capturing" | "verifying" | "verified" | "error";
```

`useSession` exposes the one active [`TapSession`](/sdks/core/reference/client/TapSession) the provider holds. With `autoVerify` left on (the default), [`EndstateProvider`](/sdks/web/reference/react/EndstateProvider) captures and verifies the landing redirect tap on mount, so `session` and `item` populate without any call of your own. `status` drives the UI while that runs, moving `idle` -> `capturing` -> `verifying` -> `verified`, or to `error` on failure.

`item` is a convenience: it is `session?.item ?? null`, the verified unit read straight off the session with no extra request.

## Example

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

export function ItemPanel() {
  const { item, status, error } = useSession();

  if (status === "capturing" || status === "verifying") return <Spinner />;
  if (status === "error") return <p>Could not verify: {error?.message}</p>;
  if (!item) return <p>No item tapped.</p>;

  return (
    <div>
      <h1>{item.name}</h1>
      <p>Genuine item {item.id}</p>
    </div>
  );
}
```

To verify a tap you captured yourself - for example when `autoVerify` is `false`, or after collecting a value through your own interface - call `verify` with the [`TapInput`](/sdks/core/reference/browser/captureTap):

```tsx theme={null}
const { verify } = useSession();
const session = await verify(tap);
```

## Returns

<ResponseField name="session" type="TapSession | null">
  The active session, or `null` until a tap is verified. Opened bound to the
  tap, so `session.claims.create({to})` and `session.transfers.create({to})`
  read `unit_id` from its scope.
</ResponseField>

<ResponseField name="item" type="TapResponse[&#x22;unit&#x22;] | null">
  The verified unit (`{(id, external_id, name, attributes, collection)}`), read
  off the session with no extra request. `null` until `status` reaches
  `"verified"`.
</ResponseField>

<ResponseField name="status" type="SessionStatus">
  Where capture-and-verify stands: `"idle"` before it starts, `"capturing"`
  while reading the tap, `"verifying"` during the verify request, `"verified"`
  once a session exists, and `"error"` on failure. Branch the UI on this.
</ResponseField>

<ResponseField name="error" type="Error | null">
  The failure that moved `status` to `"error"`, or `null`. For typed error codes
  and what retries automatically, see [Errors and
  retries](/sdks/core/errors-and-retries).
</ResponseField>

<ResponseField name="verify" type="(tap: TapInput) => Promise<TapSession>">
  Verifies a tap you captured yourself and adopts the resulting session as the
  active one. Use it when `autoVerify` is off or to verify a scanned tap.
</ResponseField>

## See also

<CardGroup cols={2}>
  <Card title="EndstateProvider" icon="square-code" href="/sdks/web/reference/react/EndstateProvider">
    The provider that owns the session and runs autoVerify.
  </Card>

  <Card title="useTap" icon="scan-line" href="/sdks/web/reference/react/useTap">
    Trigger an in-page Web NFC scan and verify it.
  </Card>

  <Card title="TapSession" icon="badge-check" href="/sdks/core/reference/client/TapSession">
    What the session is and what it authorizes.
  </Card>

  <Card title="Tap sessions" icon="book-open" href="/sdks/core/tap-sessions">
    The session lifecycle and scope.
  </Card>
</CardGroup>
