Transcription

Recorded calls can be transcribed with each speaker labelled. After the call you get the transcript, a short summary and outcome fields. During the call the transcript can stream to your own WebSocket server.

Turn on transcription

Set the account default in recording settings. Dial sessions and single calls take the same transcription field to override it.

PATCH/v1/recording_settings

ParametersTypeDescription
transcription off | post_call | live post_call transcribes after hang-up. live also streams the transcript during the call. Default off.
tonality boolean Tonality analysis on transcribed calls. Default false.
PATCH/v1/recording_settings
curl -X PATCH https://api.liveleg.dev/v1/recording_settings \
  -H "Authorization: Bearer $LIVELEG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "transcription": "post_call",
    "tonality": true
  }'

Transcripts cover the recorded audio only. On an all-party consent call, only the agent's side is transcribed until the lead gives consent. How each call is recorded is in Recording.

Transcripts after the call

Each turn has a speaker, a start and end time in milliseconds from the bridge, and the text. Speakers are agent, prospect and gatekeeper. transcript.ready arrives after hang-up. With redact=payment_card, spoken card numbers are removed from the text.

GET/v1/calls/{id}/transcript

GET/v1/calls/cal_8Jq2mT4x/transcript
curl https://api.liveleg.dev/v1/calls/cal_8Jq2mT4x/transcript \
  -H "Authorization: Bearer $LIVELEG_API_KEY"
Response
{
  "object": "transcript",
  "call_id": "cal_8Jq2mT4x",
  "language": "en-US",
  "duration_seconds": 262,
  "turns": [
    {
      "speaker": "prospect",
      "start_ms": 0,
      "end_ms": 1180,
      "text": "Hello, this is Dana."
    },
    {
      "speaker": "agent",
      "start_ms": 1420,
      "end_ms": 6050,
      "text": "Hi Dana, this is Jordan with Ridgeline Roofing. You asked for a quote on a roof inspection."
    },
    {
      "speaker": "prospect",
      "start_ms": 6300,
      "end_ms": 9920,
      "text": "I'm on a job right now. Can you call me Thursday after 2?"
    }
  ],
  "redactions": 0,
  "created_at": "2026-11-03T15:46:58.402Z"
}

Live transcript stream

With transcription=live, open a transcript stream on the call when call.bridged arrives. It uses the same endpoint as media streams with content=transcript. Turns spoken before the stream opened are sent first.

POST/v1/calls/{id}/streams

ParametersTypeDescription
urlrequired string Your WebSocket server, wss:// only.
content audio | transcript transcript sends transcript messages instead of audio. Default audio.
tracks agent | prospect | both Which speakers to send. Default both.
POST/v1/calls/cal_8Jq2mT4x/streams
curl https://api.liveleg.dev/v1/calls/cal_8Jq2mT4x/streams \
  -H "Authorization: Bearer $LIVELEG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "wss://coach.example.com/transcript",
    "content": "transcript",
    "tracks": "both"
  }'

Each message holds the current text of one turn. Messages with is_final false are updated as the speaker goes on. The last message for a turn has is_final true. The stream closes when the call ends.

WebSocket message
{
  "event": "transcript",
  "call_id": "cal_8Jq2mT4x",
  "sequence": 37,
  "speaker": "prospect",
  "turn_id": 4,
  "start_ms": 6300,
  "end_ms": 9920,
  "text": "I'm on a job right now. Can you call me Thursday after 2?",
  "is_final": true
}

Summary and outcome fields

After-call transcripts come with summary.ready. It holds a two or three sentence summary and fields you can write straight into your CRM.

Event
{
  "id": "evt_3Qw88Tp0",
  "type": "summary.ready",
  "created_at": "2026-11-03T15:47:02.118Z",
  "livemode": true,
  "data": {
    "call_id": "cal_8Jq2mT4x",
    "summary": "Owner answered. Busy on a job, asked for a call Thursday after 2 pm.",
    "outcome": "callback_requested",
    "callback_at": "2026-11-06T14:00:00-06:00",
    "opt_out_requested": false
  }
}
outcomeMeaning
interestedThe lead wants a next step: a quote, a meeting or a demo.
callback_requestedThe lead asked to be called at another time. callback_at holds the time when one was said.
not_interestedThe lead declined.
do_not_callThe lead asked not to be called again. opt_out_requested is true.
wrong_numberThe person is not the lead or the business.
gatekeeperThe agent spoke only with a receptionist or assistant.
no_conversationThe call ended before a conversation.

When a lead asks not to be called again, the number goes on your do-not-call list and dnc.added arrives with source call_phrase. callback_at does not schedule a call. Send it as a disposition to schedule one.

Tonality analysis

Tonality analysis scores each speaker on a transcribed call. Turn it on with tonality=true. tonality.ready arrives after the transcript.

FieldTypeDescription
speaker string agent, prospect or gatekeeper.
tone string friendly, neutral, tense or flat, for most of the call.
energy number 0 to 1, from voice volume and pace.
sentiment number -1 (negative) to 1 (positive), from words and voice.
talk_ratio number Share of the call's talk time spoken by this speaker, 0 to 1.
Event
{
  "id": "evt_3Qw91Mx2",
  "type": "tonality.ready",
  "created_at": "2026-11-03T15:47:20.640Z",
  "livemode": true,
  "data": {
    "call_id": "cal_8Jq2mT4x",
    "speakers": [
      {
        "speaker": "agent",
        "tone": "friendly",
        "energy": 0.71,
        "sentiment": 0.42,
        "talk_ratio": 0.58
      },
      {
        "speaker": "prospect",
        "tone": "neutral",
        "energy": 0.48,
        "sentiment": 0.15,
        "talk_ratio": 0.42
      }
    ]
  }
}

Search finds calls whose transcripts contain the words or phrase you send. Each result lists the matching turns with their times. Results are newest first and use the usual pagination.

GET/v1/transcripts

QueryTypeDescription
queryrequired string Words or a phrase in quotes.
speaker string Only turns by agent, prospect or gatekeeper.
agent_id string Only calls taken by this agent.
outcome string Only calls with this outcome.
created_after, created_before string Date range, ISO 8601.
GET/v1/transcripts
curl "https://api.liveleg.dev/v1/transcripts?query=%22roof+inspection%22&speaker=prospect&outcome=interested" \
  -H "Authorization: Bearer $LIVELEG_API_KEY"
Response
{
  "object": "list",
  "data": [
    {
      "call_id": "cal_7Hd1aP2c",
      "agent_id": "agt_114",
      "lead_id": "led_9Pq1",
      "outcome": "interested",
      "matches": [
        {
          "speaker": "prospect",
          "start_ms": 48210,
          "text": "We could do the roof inspection next week."
        }
      ]
    }
  ],
  "has_more": false
}

Retention and use

A transcript is kept as long as its recording: 1 year by default, configurable from 30 days to 10 years. Deleting the recording deletes the transcript, summary and tonality results. Deleted recordings and transcripts are removed from our systems, except where the law requires us to keep a copy. We use transcripts only to provide the service to the account that made the call. We do not use them to train models.

Prices

Transcripts, live transcripts and tonality analysis are billed per minute of transcribed call. Recording is part of the per-minute call rate.

Transcript, after the callSpeaker-labelled, with summary and outcome fields. $0.02/ min
Live transcript, during the callStreamed in real time. $0.04/ min
Tonality analysisTone, energy, sentiment and talk/listen ratio per speaker. $0.03/ min analyzed