Live Call Transcription¶
Overview¶
The Live Call Transcription WebSocket streams the transcript of a call while it is in progress. An external system (a supervisor dashboard, a CRM, a quality tool) opens one connection per call and receives each phrase as it is recognised, for the agent and for the customer separately.
The transcript is produced by the agent's web client: when live transcription is on for the call, the web client sends the audio of each side to the speech-to-text provider, and every result is also delivered to the subscribers of that call. Nothing is stored; a subscriber only receives what is said after it connects.
Requirements¶
| Requirement | Details |
|---|---|
| Live transcription on the account | Config → Accounts → (account) → Calls: transcription enabled. Use Automatic mode so every call is transcribed; in Manual mode only the calls where the agent turns transcription on are streamed. See AI Transcription. |
| The agent answers in the web client | Calls answered on a desk phone, a SIP softphone or the mobile apps are not transcribed live and produce no messages. |
| Credentials | An API key or a login token of a user of the account who is an administrator or a call center supervisor. Other users get 403. |
Endpoint¶
wss://your-domain:9443/ws/v1/calls/{call_id}/transcription
Method: GET (WebSocket upgrade).
{call_id} identifies the call (see Which call ID to use). URL-encode it.
Authentication¶
Use one of:
| Method | How |
|---|---|
| API key (server to server) | Header X-API-Key: <api_key>. If the key belongs to a parent (reseller) account and the call belongs to a sub-account, also send X-Account-ID: <sub-account id>. |
| Login token | Header Authorization: Bearer <token>, or the query parameter ?token=<token> when the client cannot set headers (browsers). |
Warning
Do not put an API key in a web page. Browsers cannot send the X-API-Key header on a WebSocket, and anything in the page is visible to its users. Connect from your server and relay the messages to the browser.
Responses before the upgrade¶
| Status | Meaning |
|---|---|
101 |
Connected. |
400 |
No account could be determined for the credentials. |
401 |
Missing or invalid credentials. |
403 |
The user is neither an administrator nor a call center supervisor. |
Messages¶
Every message is a JSON text frame with a type.
subscribed¶
Sent once, right after connecting.
{"type": "subscribed", "call_id": "f933ebf4-4433-47d4-aa4b-e90790d3c7a1"}
transcript¶
One phrase of one side of the call.
{
"type": "transcript",
"call_id": "f933ebf4-4433-47d4-aa4b-e90790d3c7a1",
"side": "agent",
"transcript": "thanks for calling, how can I help you",
"confidence": 0.98,
"is_final": true,
"start": 12.4,
"duration": 2.1
}
| Field | Description |
|---|---|
side |
agent (the user on the web client) or customer (the other party). |
transcript |
The recognised text. |
is_final |
false for an interim result that may still change; true once the phrase is settled. Interim results for a phrase are followed by its final result, which replaces them. Omitted when false. |
confidence |
0 to 1, as reported by the speech-to-text provider. |
start, duration |
Seconds from the moment that side started being transcribed. |
Fields with an empty or zero value are omitted.
ended¶
That side of the call stopped being transcribed (the call ended or the agent turned transcription off). One ended arrives per side.
{"type": "ended", "call_id": "f933ebf4-4433-47d4-aa4b-e90790d3c7a1", "side": "customer"}
The connection is not closed by the server after ended; close it when you are done with the call.
Keep-alive¶
The server sends a WebSocket ping every 54 seconds and closes connections that do not answer it within 60 seconds. Standard WebSocket clients answer pings automatically. Messages sent by the client are ignored.
Which call ID to use¶
The ID is the one the agent's web client knows the call by:
| Call | call_id |
|---|---|
| Queue call | The call ID of the caller's leg — the same ID recordings and CDRs of that call are linked to. |
| Any other call | The call ID of the agent's leg, i.e. of the web client's own call. |
A subscription to an ID that never matches simply receives no transcript messages. A subscription can be opened before the call is transcribed; messages start as soon as they are produced.
Example (Python)¶
import asyncio, json, os
import websockets
async def follow(call_id: str) -> None:
url = f"wss://{os.environ['DOMAIN']}:9443/ws/v1/calls/{call_id}/transcription"
headers = {"X-API-Key": os.environ["API_KEY"]}
async with websockets.connect(url, additional_headers=headers) as ws:
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "transcript" and msg.get("is_final"):
print(f"{msg['side']}: {msg['transcript']}")
asyncio.run(follow("f933ebf4-4433-47d4-aa4b-e90790d3c7a1"))
Limitations¶
- Only calls transcribed live in the web client are streamed. There is no server-side transcription of calls answered on other devices.
- Nothing is replayed: phrases spoken before the subscription opened are not sent. The full transcript of a recorded call is available afterwards with the recording (see AI Transcription).
- A subscriber that falls more than 64 messages behind loses messages until it catches up.
- Language and provider are the ones set for live transcription on the account.