WebSocket API

Real-time bidirectional communication for live demo sessions. The WebSocket connection handles chat messages, typing indicators, iframe commands, and lead capture events.

Connection

wss://api.iraa.ai/ws/session/:sessionId?token=SESSION_JWT

The sessionId and token are obtained from the POST /api/v1/session endpoint.

All messages are JSON objects with type and payload fields.

JavaScript Example

// After creating a session via POST /api/v1/session
const { sessionId, token } = session;

const ws = new WebSocket(
  `wss://api.iraa.ai/ws/session/${sessionId}?token=${token}`
);

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  switch (msg.type) {
    case 'agent_response':
      console.log('Agent:', msg.payload.text);
      console.log('Commands:', msg.payload.iframeCommands);
      console.log('Suggestions:', msg.payload.suggestions);
      break;
    case 'typing_indicator':
      console.log('Typing:', msg.payload.isTyping);
      break;
    case 'lead_form':
      console.log('Show lead form:', msg.payload.fields);
      break;
    case 'error':
      console.error('Error:', msg.payload.code, msg.payload.message);
      break;
    case 'pong':
      // Heartbeat response
      break;
  }
};

// Send a message
ws.send(JSON.stringify({
  type: 'visitor_message',
  payload: { text: 'Show me the dashboard' }
}));

// Keep alive
setInterval(() => {
  ws.send(JSON.stringify({ type: 'heartbeat', payload: {} }));
}, 30000);

Client → Server Messages

Clientvisitor_message

Send a chat message from the visitor.

{
  "type": "visitor_message",
  "payload": { "text": "Show me the dashboard" }
}
Clientheartbeat

Keep the connection alive. Server responds with pong.

{
  "type": "heartbeat",
  "payload": {}
}
Clientiframe_event

Report an event from the demo iframe (click, navigation, etc.) for analytics.

{
  "type": "iframe_event",
  "payload": {
    "event": "click",
    "selector": "#btn",
    "url": "/dashboard"
  }
}

Server → Client Messages

Serveragent_response

Agent's reply with text, TTS audio reference, iframe commands, and suggested replies.

{
  "type": "agent_response",
  "payload": {
    "text": "Here's the dashboard! Let me show you the pipeline.",
    "speech": "Here's the dashboard. Let me show you the pipeline.",
    "iframeCommands": [
      { "action": "navigate", "url": "/dashboard" },
      { "action": "highlight", "selector": "[data-testid='pipeline-chart']" }
    ],
    "suggestions": ["Create a deal", "Show contacts", "Tell me about pricing"],
    "agentId": "demo"
  }
}

Iframe command actions:

  • navigate — Navigate to a URL
  • click — Click an element
  • type — Type text into an input
  • highlight — Visually highlight an element
  • scroll — Scroll to an element
  • wait — Wait for a selector to appear
  • select — Select a dropdown option
Servertyping_indicator

Agent is processing a response.

{
  "type": "typing_indicator",
  "payload": { "agentId": "demo", "isTyping": true }
}
Serverlead_form

Trigger the lead capture form in the widget.

{
  "type": "lead_form",
  "payload": {
    "fields": ["email", "company"],
    "cta": { "text": "Start Free Trial", "url": "https://example.com/signup" }
  }
}
Servererror

Error occurred during processing.

{
  "type": "error",
  "payload": {
    "code": "SESSION_EXPIRED",
    "message": "Session expired"
  }
}

Error codes:

AUTH_REQUIREDNo token provided
INVALID_TOKENToken is invalid or expired
SESSION_NOT_FOUNDSession does not exist
SESSION_EXPIREDSession has timed out
INVALID_JSONMessage is not valid JSON
EMPTY_MESSAGEMessage text is empty
UNKNOWN_TYPEUnrecognized message type
PDP_NOT_FOUNDPDP config not found for session
Serverpong

Response to heartbeat.

{
  "type": "pong",
  "payload": { "ts": 1711000000000 }
}

Connection Lifecycle

  1. Create a session via POST /api/v1/session to get sessionId and token
  2. Connect to wss://api.iraa.ai/ws/session/:sessionId?token=TOKEN
  3. Send visitor_message events to chat with the agent
  4. Receive typing_indicator followed by agent_response
  5. Execute iframe commands from agent_response.payload.iframeCommands
  6. Send periodic heartbeat to keep connection alive (recommended: every 30s)
  7. Handle lead_form events to show lead capture UI
  8. End session via POST /api/v1/session/:sessionId/end

Close Codes

CodeReason
4001Authentication failed (missing or invalid token)
4004Session not found
1000Normal closure