Skip to main content
An authenticated session starts on your server: your backend calls the session endpoint with your API key and receives a short-lived session token, which your client uses to connect. The API key never leaves your server, and every session parameter — user identity, overrides, dynamic variables — is set by code you trust. This is how private agents run in production. The token is client-agnostic. Create it the same way regardless of which surface renders the conversation:
No backend, and anyone may talk to the agent? A public agent lets the SDK create sessions with just an agentId — no token involved, gated by an origin allowlist and rate limits.

Create a token on your backend

Your backend exchanges your API key for a single-conversation token.
1

Create a session from your backend

Call POST /v1/agent/sessions with your API key. This is where you set per-session parameters — user identity, overrides, dynamic variables.
2

Return the response to your frontend

The response is the session token. Forward it verbatim.
3

Start the client with the token

Pass the object to AgentSession.start({sessionToken}) unmodified. The SDK handles the connection from there.
On the client, fetch the token from your backend and pass it to the SDK unchanged:
Browser
More on what the SDK can do once connected is in the Web SDK reference.
overrides, dynamic_variables, language, tool_events, timezone, and world_context belong in your backend’s creation request — the SDK forwards these options only in public agent mode.

Request fields

Unknown fields — top-level or inside overrides — are rejected with 422.

Overrides

overrides replaces parts of the agent’s published configuration for one session — the agent itself never changes:
On public agents, keyless (browser-created) sessions may override only language and voice_id — the prompt-shaping fields are rejected with 400 regardless of the agent. Create the session from your backend to use them. The session record stores which overrides took effect. Everything else on the request is not an override: dynamic_variables, timezone, record_audio, and tool_events are separate top-level fields. Session length is not settable per session — max_duration_seconds comes from the agent’s conversation configuration.

Response

JSON
Treat the response as opaque and pass it to start() unmodified. If the SDK does not recognize the transport value, it fails fast with an unsupported_transport error asking you to upgrade the SDK — it never silently degrades.

Token lifetime

  • A session token is single-use: start() consumes it once to establish the conversation.
  • On network drops the SDK reconnects at the transport level using the same connection state — it never re-creates the session, so you never need a fresh token mid-call.
  • Once a session ends, the token is spent. Create a new token for each conversation.

Ending sessions from your backend

A session normally ends from the client side — the user disconnects, or the agent hangs up. To force-end a live session server-side, call the end endpoint with your API key and the session_id from the creation response:
Request
The agent disconnects and the call terminates — the response is 204. The session record stays readable in conversation history, along with the transcript and recording when the agent stores them. The same endpoint ends in-progress phone calls too.

Keep API keys on the server

Your API key grants full access to every resource in your team — agents, sessions, tools, phone numbers. Never embed it in a browser, mobile app, or any code you ship to users. The only credential that belongs in a client is the session token, and the only credential-free path is a public agent ID.

Error responses

Session creation fails with standard HTTP statuses; the SDK surfaces them as a FishAgentError with statusCode set. The complete status-code reference for every /v1/agent endpoint — error shapes, 400 vs 422, conflict semantics — is on Agents API errors.

Going further

Public agents

The credential-free alternative, with origin allow-lists.

Widget with private agents

Feed the widget session tokens from your backend via sessionTokenProvider.

Web SDK

Everything AgentSession can do once connected.

Dynamic variables

Personalize each session at creation time.