Documentation Menu
Event Streaming (SSE)
Subscribe to real-time agent events via Server-Sent Events. Get notified when your agent receives messages, executes tools, or encounters errors.
On this page
Real-Time Events
The SSE endpoint streams events from your agent in real time. Use it to:
- Monitor your agent’s activity from external dashboards
- Trigger workflows when specific events occur
- Log agent actions to external systems
- Build custom notifications
Connecting
curl -N https://app.brainroad.com/api/v1/events \
-H "Authorization: Bearer brk_your_key_here"
The -N flag disables buffering so events appear immediately.
Authentication
SSE uses API keys (not gateway tokens). Create one from Dashboard → API → API Keys.
Event Format
event: connected
data: {"agentId":"abc123","message":"Subscribed to events"}
event: activity
data: {"id":42,"agentId":"abc123","eventType":"message.received","category":"communication","status":"completed","title":"New WhatsApp message from John","detail":{"from":"+1234567890"},"costTokens":null,"costUsd":null,"source":"webhook","createdAt":"2026-03-09T12:00:00.000Z","resolvedAt":null,"resolvedBy":null}
The first event is always connected with your agent ID. Subsequent events are activity with the full event payload.
Event Fields
| Field | Type | Description |
|---|---|---|
id | number | Unique event ID |
agentId | string | Your agent’s ID |
eventType | string | Specific event type (e.g., message.received, tool.executed, agent.started) |
category | string | Event category (see below) |
status | string | completed, pending_approval, approved, rejected, failed |
title | string | Human-readable event summary |
detail | object/null | Event-specific data (parsed from JSON) |
costTokens | number/null | Token usage, if applicable |
costUsd | number/null | Cost in USD (converted from micro-dollars) |
source | string | Where the event originated: api, webhook, or log |
createdAt | string | ISO 8601 timestamp |
resolvedAt | string/null | When a pending event was resolved |
resolvedBy | string/null | Who resolved a pending event |
Filtering by Category
Add a category query parameter to receive only specific event types:
# Only communication events (messages received/sent)
curl -N "https://app.brainroad.com/api/v1/events?category=communication" \
-H "Authorization: Bearer brk_your_key_here"
# Only errors
curl -N "https://app.brainroad.com/api/v1/events?category=error" \
-H "Authorization: Bearer brk_your_key_here"
Available categories: lifecycle, communication, tool_use, coding, social, config, error
Keepalive
The server sends a comment (: keepalive) every 30 seconds to prevent connection timeouts. Your SSE client library handles these automatically.
Example: Node.js
import EventSource from "eventsource";
const es = new EventSource(
"https://app.brainroad.com/api/v1/events",
{ headers: { Authorization: "Bearer brk_your_key_here" } }
);
es.addEventListener("activity", (event) => {
const data = JSON.parse(event.data);
console.log(`[${data.category}] ${data.title}`);
if (data.costUsd) {
console.log(` Cost: $${data.costUsd.toFixed(4)}`);
}
});
es.addEventListener("connected", (event) => {
console.log("Subscribed:", JSON.parse(event.data));
});
es.onerror = () => {
console.log("Connection lost, reconnecting...");
};
Example: Python
import json
import sseclient # pip install sseclient-py
import requests
response = requests.get(
"https://app.brainroad.com/api/v1/events",
headers={"Authorization": "Bearer brk_your_key_here"},
stream=True,
)
client = sseclient.SSEClient(response)
for event in client.events():
if event.event == "connected":
print("Connected:", json.loads(event.data))
elif event.event == "activity":
data = json.loads(event.data)
print(f"[{data['category']}] {data['title']}")
Example: Browser (fetch)
const response = await fetch("https://app.brainroad.com/api/v1/events", {
headers: { Authorization: "Bearer brk_your_key_here" },
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const text = decoder.decode(value);
for (const line of text.split("\n")) {
if (line.startsWith("data: ")) {
const data = JSON.parse(line.slice(6));
console.log(data);
}
}
}