Dashcam
API Reference

WebSocket API

Real-time event streaming for live dashboards.

WebSocket API

The Dashcam daemon serves a WebSocket endpoint on the same port as the HTTP API. This is how the dashboard receives real-time events, captures, window updates, and agent status changes without polling. If you are building a custom dashboard, an integration, or a monitoring script, this is the API to use.

Connecting

Open a WebSocket connection to:

ws://localhost:57580/ws

The connection upgrades from the same HTTP server that hosts the REST API and the dashboard. No additional configuration is required.

JavaScript
const ws = new WebSocket('ws://localhost:57580/ws');

ws.onopen = () => {
  console.log('Connected to Dashcam');
};

ws.onmessage = (message) => {
  const data = JSON.parse(message.data);
  console.log(data.type, data);
};

Channel System

Messages are organized into channels. When you connect, you receive nothing until you subscribe. Send a subscribe message to start receiving events on specific channels:

Client -> Server
{
  "type": "subscribe",
  "channels": ["events", "captures", "window", "agents", "live"]
}
ChannelDescription
eventsNew events as they are captured (tool use, messages, decisions)
capturesNew screenshots and videos
windowWindow state changes and timer updates
agentsAgent start/stop notifications
liveHeartbeat messages for connection health

Subscribe to all channels for the full live dashboard experience, or pick only the channels you need.

Server-to-Client Messages

After subscribing, the server pushes messages as events occur. Every message is a JSON object with a type field.

event

A new event was captured. Sent on the events channel.

{
  "type": "event",
  "data": {
    "id": "evt_01JQDEF",
    "session_id": "sess_01JQXYZ",
    "timestamp": "2026-03-20T10:15:23.456Z",
    "event_type": "tool_use",
    "agent_id": null,
    "summary": "Write src/auth/jwt.ts",
    "tool_name": "Write",
    "file_path": "src/auth/jwt.ts",
    "tokens_in": 1200,
    "tokens_out": 450,
    "duration_ms": 234
  }
}

capture

A new screenshot or video was saved. Sent on the captures channel.

{
  "type": "capture",
  "data": {
    "id": "cap_01JQGHI",
    "event_id": "evt_01JQDEF",
    "session_id": "sess_01JQXYZ",
    "timestamp": "2026-03-20T10:15:24.000Z",
    "capture_type": "screenshot",
    "file_path": "/captures/sess_01JQXYZ/1711234567890-full.png",
    "thumbnail_path": "/captures/sess_01JQXYZ/1711234567890-thumb.png",
    "width": 1920,
    "height": 1080
  }
}

window_update

The window state changed or the timer ticked. Sent on the window channel. These arrive approximately once per minute during an active window.

{
  "type": "window_update",
  "data": {
    "id": "win_01JQABC",
    "state": "ACTIVE",
    "started_at": "2026-03-20T09:00:00Z",
    "remaining_seconds": 11520,
    "elapsed_seconds": 6480,
    "session_count": 2,
    "event_count": 89
  }
}

session_update

A session's metadata changed (new summary, status transition, updated event count). Sent on the events channel.

{
  "type": "session_update",
  "data": {
    "id": "sess_01JQXYZ",
    "status": "completed",
    "total_events": 142,
    "summary": "Built auth system with JWT tokens and user dashboard",
    "estimated_cost_usd": 0.47
  }
}

agent_status

An agent started or stopped. Sent on the agents channel.

{
  "type": "agent_status",
  "data": {
    "session_id": "sess_01JQXYZ",
    "agent_id": "agent_frontend_01",
    "agent_type": "frontend",
    "status": "active",
    "started_at": "2026-03-20T10:00:00Z"
  }
}

live_heartbeat

Keep-alive message sent every 30 seconds on the live channel. Use this to detect stale connections.

{
  "type": "live_heartbeat",
  "timestamp": "2026-03-20T10:15:30.000Z"
}

Client-to-Server Messages

Clients can send messages to subscribe to channels or query historical data over the WebSocket connection.

subscribe

Subscribe to one or more channels. Can be sent multiple times to add channels.

Client -> Server
{
  "type": "subscribe",
  "channels": ["events", "captures"]
}

query_events

Request historical events for a session within a time range. The server responds with a batch of event messages.

Client -> Server
{
  "type": "query_events",
  "sessionId": "sess_01JQXYZ",
  "from": "2026-03-20T10:00:00Z",
  "to": "2026-03-20T11:00:00Z"
}

query_sessions

Request sessions for a given date. The server responds with a batch of session_update messages.

Client -> Server
{
  "type": "query_sessions",
  "date": "2026-03-20"
}

Example: Live Event Listener

A minimal script that connects, subscribes, and logs events as they arrive:

monitor.js
const ws = new WebSocket('ws://localhost:57580/ws');

ws.onopen = () => {
  ws.send(JSON.stringify({
    type: 'subscribe',
    channels: ['events', 'captures', 'window']
  }));
};

ws.onmessage = (msg) => {
  const { type, data } = JSON.parse(msg.data);

  switch (type) {
    case 'event':
      console.log(`[${data.timestamp}] ${data.event_type}: ${data.summary}`);
      break;
    case 'capture':
      console.log(`[${data.timestamp}] Screenshot: ${data.file_path}`);
      break;
    case 'window_update':
      const mins = Math.floor(data.remaining_seconds / 60);
      console.log(`Window: ${data.state} (${mins}m remaining)`);
      break;
  }
};

ws.onclose = () => console.log('Disconnected');
Terminal
node monitor.js
# [2026-03-20T10:15:23.456Z] tool_use: Write src/auth/jwt.ts
# [2026-03-20T10:15:24.000Z] Screenshot: /captures/sess_01JQXYZ/1711234567890-full.png
# Window: ACTIVE (192m remaining)

The WebSocket connection does not require authentication in v1. Anyone who can reach the daemon port can subscribe. Bind to 127.0.0.1 (the default) or use SSH tunnels to restrict access.

On this page