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

# Realtime session tokens

> Secure your browser realtime subscriptions with short-lived session tokens.

## Overview

Use this flow for browser realtime subscriptions:

1. Your backend calls `POST /api/realtime/session` with a **secret** API key.
2. Sippet returns a short-lived `session_token`.
3. Your backend returns that token to the browser.
4. The browser connects to `/socket` with `session_token`.

Publishable keys no longer grant realtime subscriptions, REST reads, or RPC actions.

## Server-side token minting

Call Sippet from your backend only.

```ts theme={null}
const response = await fetch("https://api.sippet.ai/api/realtime/session", {
  method: "POST",
  headers: {
    "content-type": "application/json",
    "x-api-key": process.env.SIPPET_SECRET_KEY!,
  },
});

if (!response.ok) {
  throw new Error(`Token mint failed: ${response.status}`);
}

const data = await response.json();

return {
  sessionToken: data.token,
  expiresAt: data.expires_at,
  ttlSeconds: data.ttl_seconds,
};
```

## Browser socket initialization

```ts theme={null}
import { initSocket, joinEventsChannel } from "@sippet-ai/sdk-js/client";

const { sessionToken } = await fetch("/api/sippet/realtime-session", {
  method: "POST",
  credentials: "include",
}).then((r) => r.json());

initSocket({
  baseUrl: "https://api.sippet.ai",
  socketOptions: {
    params: {
      session_token: sessionToken,
    },
  },
});

const channel = joinEventsChannel();

channel.on("incoming_call", (payload) => console.log("incoming_call", payload));
channel.on("call_answered", (payload) => console.log("call_answered", payload));
channel.on("call_ended", (payload) => console.log("call_ended", payload));
```

## Refresh strategy

* Tokens are short-lived (default 5 minutes).
* Re-mint before expiry or on socket auth failure.
* Keep refresh logic in your backend route, not in client code.

## Migration notes

If you previously called `initSocket({ publishableKey })`, migrate to `socketOptions.params.session_token`.

## Related pages

* Quickstart: `/quickstart`
* Realtime patterns: `/guides/realtime-telephony-patterns`
* SDK introduction: `/sdk-js/introduction`
