Skip to main content
layercode-js-sdk.

LayercodeClient

The LayercodeClient is the core client for all JavaScript frontend SDKs, providing audio recording, playback, and real-time communication with the Layercode agent.
import LayercodeClient from "https://cdn.jsdelivr.net/npm/@layercode/js-sdk@latest/dist/layercode-js-sdk.esm.js";

window.layercode = new LayercodeClient({
  agentId: "your-agent-id",
  conversationId: "your-conversation-id", // optional
  authorizeSessionEndpoint: "/api/authorize",
  metadata: { userId: "123" }, // optional
  onConnect: ({ conversationId, config }) => {
    console.log("connected", conversationId);
    console.log("agent config", config);
  },
  onDisconnect: () => console.log("disconnected"),
  onError: (err) => console.error("error", err),
  onDataMessage: (msg) => console.log("data message", msg),
  onUserAmplitudeChange: (amp) => console.log("user amplitude", amp),
  onAgentAmplitudeChange: (amp) => console.log("agent amplitude", amp),
  onStatusChange: (status) => console.log("status", status),
});

window.layercode.connect();

Usage Example

Constructor Options

options
object
required
Options for the LayercodeClient.
options.agentId
string
required
The ID of your Layercode agent.
options.conversationId
string
The conversation ID to resume a previous conversation (optional).
options.authorizeSessionEndpoint
string
required
The endpoint to authorize the session (should return a client_session_key and session_id). Note: From Mon Sep 1, 12:00 UTC, the response will include conversation_id instead of session_id (see REST API page).
options.metadata
object
Optional metadata to send with the session authorization request.
options.onConnect
function
Callback when the client connects. Receives { conversationId: string | null; config?: AgentConfig }. Use config to inspect the effective agent configuration returned from authorizeSessionEndpoint.
options.onDisconnect
function
Callback when the client disconnects.
options.onError
function
Callback when an error occurs. Receives an Error object.
options.onDataMessage
function
Callback for custom data messages from the server.
options.onUserAmplitudeChange
function
Callback for changes in the user’s microphone amplitude (number, 0-1).
options.onAgentAmplitudeChange
function
Callback for changes in the agent’s audio amplitude (number, 0-1).
options.onStatusChange
function
Callback when the client’s status changes. Receives a string: "disconnected" | "connecting" | "connected" | "error".

Methods

connect
function
required
connect(): Promise<void> Connects to the Layercode agent, authorizes the session, and starts audio capture and playback.
disconnect
function
required
disconnect(): Promise<void> Disconnects from the Layercode agent, stops audio capture and playback, and closes the WebSocket.

Turn-taking (Push-to-Talk)

Layercode supports both automatic and push-to-talk turn-taking. For push-to-talk, use these methods to signal when the user starts and stops speaking:
triggerUserTurnStarted
function
triggerUserTurnStarted(): Promise<void> Signals that the user has started speaking (for push-to-talk mode). Interrupts any agent audio playback.
triggerUserTurnFinished
function
triggerUserTurnFinished(): Promise<void> Signals that the user has finished speaking (for push-to-talk mode).

Text messages

Use this method when the user submits a chat-style message instead of speaking.
sendClientResponseText
function
sendClientResponseText(text: string): void Ends the active user turn and forwards text to the agent. The user.transcript event is emitted before the agent responds, keeping UI components in sync.

Events & Callbacks

  • onConnect: Called when the connection is established. Receives { conversationId, config }. Use config to inspect the agent configuration returned by your authorize endpoint.
  • onDisconnect: Called when the connection is closed.
  • onError: Called on any error (authorization, WebSocket, audio, etc).
  • onDataMessage: Called when a custom data message is received from the server (see response.data events from your backend).
  • onUserAmplitudeChange: Called with the user’s microphone amplitude (0-1).
  • onAgentAmplitudeChange: Called with the agent’s audio amplitude (0-1).
  • onStatusChange: Called when the status changes ("disconnected", "connecting", "connected", "error").
options.onDeviceSwitched
function
Callback when the active input/output device changes in the browser. Useful for handling device disconnects and switches.
options.onUserIsSpeakingChange
function
Callback when VAD detects user speech start/stop. Receives a boolean.

Notes & Best Practices

  • The SDK manages microphone access, audio streaming, and playback automatically.
  • The metadata option allows you to set custom data which is then passed to your backend webhook (useful for user/session tracking).
  • The conversationId can be used to resume a previous conversation, or omitted to start a new one.

Authorizing Sessions

To connect a client (browser) to your Layercode voice agent, you must first authorize the session. The SDK will automatically send a POST request to the path (or url if your backend is on a different domain) passed in the authorizeSessionEndpoint option. In this endpoint, you will need to call the Layercode REST API to generate a client_session_key and conversation_id (if it’s a new conversation).
If your backend is on a different domain, set authorizeSessionEndpoint to the full URL (e.g., https://your-backend.com/api/authorize).
Why is this required? Your Layercode API key should never be exposed to the frontend. Instead, your backend acts as a secure proxy: it receives the frontend’s request, then calls the Layercode authorization API using your secret API key, and finally returns the client_session_key to the frontend. This also allows you to authenticate your user, and set any additional metadata that you want passed to your backend webhook. How it works:
  1. Frontend: The SDK automatically sends a POST request to your authorizeSessionEndpoint with a request body.
  2. Your Backend: Your backend receives this request, then makes a POST request to the Layercode REST API /v1/agents/web/authorize_session endpoint, including your LAYERCODE_API_KEY as a Bearer token in the headers.
  3. Layercode: Layercode responds with a client_session_key (and a conversation_id), which your backend returns to the frontend.
  4. Frontend: The SDK uses the client_session_key to establish a secure WebSocket connection to Layercode.
Example backend authorization endpoint code:
export const dynamic = "force-dynamic";
import { NextResponse } from "next/server";

export const POST = async (request: Request) => {
  // Here you could do any user authorization checks you need for your app
  const endpoint = "https://api.layercode.com/v1/agents/web/authorize_session";
  const apiKey = process.env.LAYERCODE_API_KEY;
  if (!apiKey) {
    throw new Error("LAYERCODE_API_KEY is not set.");
  }
  const requestBody = await request.json();
  if (!requestBody || !requestBody.agent_id) {
    throw new Error("Missing agent_id in request body.");
  }
  try {
    const response = await fetch(endpoint, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${apiKey}`,
      },
      body: JSON.stringify(requestBody),
    });
    if (!response.ok) {
      const text = await response.text();
      throw new Error(text || response.statusText);
    }
    return NextResponse.json(await response.json());
  } catch (error: any) {
    console.log("Layercode authorize session response error:", error.message);
    return NextResponse.json({ error: error.message }, { status: 500 });
  }
};

Custom Authorization

Use the optional authorizeSessionRequest function when you need to control how authorization credentials are exchanged with your backend (for example, to add custom headers or reuse an existing HTTP client).
Custom Authorization example
import LayercodeClient from "@layercode/js-sdk";

const client = new LayercodeClient({
  agentId: "agent_123",
  authorizeSessionEndpoint: "/api/authorize",
  authorizeSessionRequest: async ({ url, body }) => {
    const response = await fetch(url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-Custom-Header": "my-header",
      },
      body: JSON.stringify(body),
    });

    if (!response.ok) {
      throw new Error(`Authorization failed: ${response.statusText}`);
    }

    return response;
  },
});
If you omit authorizeSessionRequest, the client falls back to a standard fetch call that POSTs the JSON body to authorizeSessionEndpoint.

Request payload

The SDK sends the following fields in the authorization request body:
  • agent_id – ID of the agent to connect.
  • metadata – metadata supplied when instantiating the client.
  • sdk_version – version string of the JavaScript SDK.
  • conversation_id – present only when reconnecting to an existing conversation.
I