API reference · WebSocket
Stream events
WS/v1/stream
The live record over one WebSocket, filtered on the server, after your plan's delay.
On this page
Auth. None. Without a token the call is served as Free (the Free delay and request budget, shared per IP); send Authorization: Bearer lb_… for your plan's.
Limits. Counts toward your plan's concurrent streams, WebSocket and SSE together (1, 5 or 20). Served at your plan's delay (+60 s Free, +10 s Builder, +2 s Standard).
Parameters
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
events | string | no | Comma-separated event ids (ev_…). Empty: every event your plan allows. |
phrases | string | no | Comma-separated phrase keys; filters phrase_detected only. |
types | string | no | Comma-separated event types; default everything but transcript_delta. |
subjects | string | no | Comma-separated typed-fact subjects (fact_extracted). |
context | string | no | Context kinds to opt in to: on_air, topic, near_miss, typed or all. |
token | string | no | Your token, for browsers that cannot set headers on the upgrade. Elsewhere use Authorization. |
Request
# any WebSocket client, for example websocat
websocat -H "Authorization: Bearer $LANGBOT_API_TOKEN" \
"wss://api.langbot.ai/v1/stream?phrases=tariff&types=phrase_detected"from langbot import LangbotClient
async with LangbotClient() as lb:
async for evt in lb.stream(phrases=["tariff"], types=["phrase_detected"]):
print(evt.event_id, evt.phrase, evt.t_spoken)import { LangbotClient } from "@langbotai/sdk";
const lb = new LangbotClient();
for await (const evt of lb.stream({ phrases: ["tariff"], types: ["phrase_detected"] })) {
console.log(evt.event_id, evt.phrase, evt.t_spoken);
}Response
101 Switching Protocols
{"type":"hello","seq":48212,"ts":1793566860000,"filters":{"events":[],"phrases":["tariff"],"types":["phrase_detected"],"subjects":[],"context":[]},"delay_ms":60000,"plan":"anonymous","effective_plan":"free","user_id":null,"agent":null}
{"id":"evt_01M6CQ02PR3SVZ3TV7FCXH7E09","type":"phrase_detected","event_id":"ev_kxexamplemention_26nov01","phrase":"tariff","t_spoken":1793566809000,"t_emitted":1793566809076,"verdict":{"counts":true,"reason":"mention 1 (1 needed)","role":null},"…":"…"}
{"type":"ping","ts":1793566880000}hello comes first, then events and control frames, one JSON object per message. Ops, backpressure, reconnects and close codes: Protocol.
Errors
| Status | code | When |
|---|---|---|
| 1008 | rate_limited | Your plan's concurrent streams are all open (an error frame, then close 1008). |
| 1008 | token_invalid | The token was not recognised (an error frame, then close 1008). |
| 1008 | validation_error | types or context named an unknown value. |
| 401 | token_invalid | A token was sent and not recognised. Send a valid one, or none to call anonymously. |
| 422 | validation_error | A parameter failed validation; detail[].loc names it. |
| 429 | rate_limited | Over your request budget; wait Retry-After seconds. |
Every error body is {"detail": …, "code": "…"}; branch on code. All codes: Errors.