Skip to main content
There are exactly two ways for a client to start a conversation with your agent. Pick one — there is no third path, and your API key is never one of them in the browser.

Public agent ID

The browser calls Fish Audio directly with just an agentId. No credential — requires the agent to be public.

Session token

Your backend creates a session with your API key and hands the short-lived token to the SDK. The default for private agents.

Public agents: connect with an agent ID

If the agent is public, the SDK creates the session itself — no backend, no credential:
JavaScript
Fish Audio accepts the request only when the agent has public access enabled and the page’s Origin is on the agent’s allow-list; requests are rate-limited per IP and per agent. Origins match on exact scheme, host, and port — localhost and 127.0.0.1 are different origins, so list both during development. See Public agents for setup.

Session tokens: mint on your backend

For private agents, 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 SDK with the token

Pass the object to AgentSession.start({sessionToken}) unmodified. The SDK handles the connection from there.
In session token mode, 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 ID mode.

Request fields

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

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 to re-mint mid-call.
  • Once a session ends, the token is spent. Mint 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

Enable credential-free access with origin allow-lists.

Web SDK

Everything AgentSession can do once connected.

React SDK

Hooks and components for React apps.

Dynamic variables

Personalize each session at creation time.