Skip to main content

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

import { initSocket, joinEventsChannel } from "@sippet-ai/sdk-js";

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.
  • Quickstart: /quickstart
  • Realtime patterns: /guides/realtime-telephony-patterns
  • SDK introduction: /sdk-js/introduction