Server Events
Server-to-client events published during WebRTC and WebSocket sessions
The server sends events to your client throughout a session. Events notify you of state changes, speech activity, and conversation content as it happens.
Listening for events
WebRTC (Web SDK)
Pass an onData callback when initializing the SDK. Every server event is delivered through this handler:
const instance = await NapsterCompanionApiSdk.init(token, {
onData: (data) => console.log("Event received:", data),
});WebSocket
Listen for messages on the WebSocket connection. Each message is a JSON-encoded event:
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log("Event received:", data);
};Event types
| Event | Description |
|---|---|
avatar_state_changed | The agent's readiness state changed |
talk_state_changed | The agent's speaking state changed |
message_received | A conversation message event with an action field describing the lifecycle stage |
avatar_state_changed
Fires when the agent's readiness state changes.
{
"event": "avatar_state_changed",
"data": {
"state": "ready"
}
}| State | Description |
|---|---|
preparing | The agent is initializing |
ready | The agent is ready to receive input |
talk_state_changed
Fires when the agent starts or stops speaking.
{
"event": "talk_state_changed",
"data": {
"state": "started"
}
}| State | Description |
|---|---|
preparing | The agent is preparing to speak |
started | The agent is actively speaking |
ended | The agent has finished speaking |
message_received
The primary event for tracking the conversation. Every message_received event contains a data object with the following structure:
{
"event": "message_received",
"data": {
"role": "user | assistant",
"action": "string",
"response_id": "string",
"item_id": "string",
"content": "string",
"previous_item_id": "string",
"reason": "string",
"error": "string",
"timestamp": "2026-03-04T12:00:00Z"
}
}Not every field is present in every event. The fields included depend on the action.
| Field | Type | Description |
|---|---|---|
role | "user" or "assistant" | Who the message is from |
action | string | The lifecycle stage of the message |
response_id | string | Groups related events in the same response |
item_id | string | Unique identifier for this conversation item |
content | string | Text content (transcription or response text) |
previous_item_id | string | ID of the preceding item, used to preserve ordering |
reason | string | Present in cancelled events (e.g., "turn_detected") |
error | object | Present in failed events |
timestamp | datetime | When the event occurred (included in every message) |
User message lifecycle
These events track the user's speech input and transcription, all with role: "user".
speech_started
The user began speaking. The item_id identifies the user message item that will be created when speech stops.
{
"role": "user",
"action": "speech_started",
"item_id": "item_APuyFRtVtA9m8o9Qhyj9e"
}speech_stopped
The user stopped speaking.
{
"role": "user",
"action": "speech_stopped",
"item_id": "item_APuyFRtVtA9m8o9Qhyj9e"
}created
The user's speech transcription has started. The previous_item_id links this item to the preceding item in the conversation.
{
"role": "user",
"action": "created",
"item_id": "item_APuyFRtVtA9m8o9Qhyj9e",
"previous_item_id": "item_APuxlnjrohdgargU6tHe9"
}completed
The user's speech transcription is finalized. The content field contains the full transcription text.
{
"role": "user",
"action": "completed",
"item_id": "item_APuyFRtVtA9m8o9Qhyj9e",
"content": "Hi there!"
}This event can arrive after assistant response events have already started. Do not assume user transcription completes before the assistant begins responding.
If content is empty, the user's speech could not be recognized. You may want to display a placeholder like "[inaudible]" in your UI.
failed
The user's speech transcription failed. The error field contains details.
{
"role": "user",
"action": "failed",
"item_id": "item_APuyFRtVtA9m8o9Qhyj9e",
"error": { }
}Assistant response lifecycle
These events track the agent's response generation, all with role: "assistant".
created (response-level)
A new response has started generating. The response_id groups all subsequent events for this response.
{
"role": "assistant",
"action": "created",
"response_id": "resp_APuyF0H6ffvKBP0MJE6h9"
}created (item linked to response)
A response item has been linked to the response.
{
"role": "assistant",
"action": "created",
"response_id": "resp_APuyF0H6ffvKBP0MJE6h9",
"item_id": "item_APuy7jTGdjgsW0gOGOko2"
}created (item-level)
The response item has started generating. The previous_item_id preserves ordering in the conversation.
{
"role": "assistant",
"action": "created",
"item_id": "item_APuy7jTGdjgsW0gOGOko2",
"previous_item_id": "item_APuyFRtVtA9m8o9Qhyj9e"
}delta
An incremental text chunk of the response. These arrive in rapid succession as the agent generates its reply.
{
"role": "assistant",
"action": "delta",
"response_id": "resp_APuyF0H6ffvKBP0MJE6h9",
"item_id": "item_APuy7jTGdjgsW0gOGOko2",
"content": "Hello! How can I"
}completed
The response item is finished. The content field contains the full response text.
{
"role": "assistant",
"action": "completed",
"response_id": "resp_APuyF0H6ffvKBP0MJE6h9",
"item_id": "item_APuy7jTGdjgsW0gOGOko2",
"content": "Hello! How can I assist you today?"
}interrupted
The user barged in while the agent was responding. This fires on the user side with role: "user".
{
"role": "user",
"action": "interrupted",
"item_id": "item_APuyFRtVtA9m8o9Qhyj9e"
}cancelled
The response was cancelled. The reason field explains why (e.g., "turn_detected" when the user started speaking).
{
"role": "assistant",
"action": "cancelled",
"response_id": "resp_APuyF0H6ffvKBP0MJE6h9",
"reason": "turn_detected"
}failed
The response generation failed. The error field contains details.
{
"role": "assistant",
"action": "failed",
"response_id": "resp_APuyF0H6ffvKBP0MJE6h9",
"error": { }
}