The Speak AI API exposes 3 live transcription endpoints under the base URL https://api.speakai.co/v1. Every request needs the x-speakai-key and x-access-token headers described in Authentication.
Live transcription turns a running audio or video session into a transcript while the session is still going. The three REST endpoints below open the session, feed it, and close it.
A session runs in three steps. Create the media record with POST /live-transcription/create, mint a handshake token with POST /live-transcription/token, then send transcribed words to POST /live-transcription/update/{mediaId} as they arrive.
When the session ends, send the finished recording to the same update endpoint. Speak AI transcodes it and runs the full analysis, so a live session ends up with the same transcript, speakers, and insights as an uploaded file.
The audio itself streams over a separate WebSocket connection that the handshake token authorizes. That connection is not part of the REST API and its host is not documented here.
Supported languages
Pass one of these codes as sourceLanguage when you create the session.
| value | name |
|---|---|
| en-US | English (US) |
| en-AU | English (Australia) |
| en-GB | English (British) |
| en-IN | English (Indian) |
| en-IE | English (Irish) |
| en-NZ | English (New Zealand) |
| en-AB | English (Scottish) |
| en-ZA | English (South African) |
| en-ES | English + Spanish (Multiple) |
| fr-FR | French |
| fr-CA | French (Canada) |
| es-ES | Spanish |
| es-MX | Spanish (Mexico) |
| bg-BG | Bulgarian |
| ca-ES | Catalan |
| zh-CN | Chinese (Simplified) |
| zh-TW | Chinese (Traditional) |
| zh-HK | Chinese (Cantonese, Traditional) |
| cs-CZ | Czech |
| da-DK | Danish |
| nl-NL | Dutch |
| et-EE | Estonian |
| nl-BE | Flemish |
| fi-FI | Finnish |
| de-CH | German (Swiss) |
| de-DE | German |
| el-GR | Greek |
| hi-IN | Hindi |
| hi-Latn | Hindi (Latin) |
| hu-HU | Hungarian |
| id-ID | Indonesian |
| it-IT | Italian |
| ja-JP | Japanese |
| ko-KR | Korean |
| lt-LT | Lithuanian |
| lv-LV | Latvian |
| ms-MY | Malay |
| nb-NO | Norwegian |
| pl-PL | Polish |
| pt-BR | Portuguese (Brazilian) |
| pt-PT | Portuguese (Portugal) |
| ro-RO | Romanian |
| ru-RU | Russian |
| sk-SK | Slovak |
| sv-SE | Swedish |
| taq | Tamasheq |
| th-TH | Thai |
| tr-TR | Turkish |
| uk-UA | Ukrainian |
| vi-VN | Vietnamese |
What can you do with the live transcription endpoints?
Speak AI groups these 3 endpoints under the live transcription resource. Each entry below links to the full reference for that endpoint further down this page.
Create a live transcription session
/live-transcription/createCreate the media record that a live transcription session writes into, and get back the mediaId the streaming connection needs.
Call this first. The record is created in the liveTranscript state with its processing progress already at 100, so it appears in the folder straight away and fills with words as the session runs.
Every field in the body is optional. When folderId is left out, Speak AI stores the record in the first folder on the account.
Sessions that already exist
Pass meetingAssistantId to attach the session to a scheduled meeting assistant event. When that event already has a media record, Speak AI returns the existing mediaId instead of creating a second one, so the call is safe to repeat.
Request body
Field types and names come from the request body the spec records. The spec does not mark request body fields as required, so read this as the shape the endpoint accepts rather than a required field list.
| Field | Type | Description |
|---|---|---|
name |
string | Name for the media record. A meeting assistant event overrides this with its own title. |
mediaType |
string | Recording MIME type, for example audio/webm or video/mp4. Speak AI keeps the part before the slash, and stores anything it does not recognise as audio. |
sourceLanguage |
string | Language code for the session. Defaults to en-us. |
folderId |
string | Folder to store the record in. Defaults to the first folder on the account. |
tag |
string | Single tag stored on the record. |
uploadType |
string | How the session was started. Speak AI sets this itself for meeting assistant and embedded recorder sessions. |
meetingAssistantId |
string | Id of a scheduled meeting assistant event to attach the session to. |
recorderToken |
string | Token of a recorder, when the session comes from an embedded recorder. Speak AI then takes the folder and the source language from the recorder. |
curl -X POST 'https://api.speakai.co/v1/live-transcription/create' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
-H 'Content-Type: application/json' \
-d '{
"name": "Weekly customer call",
"mediaType": "audio/webm",
"sourceLanguage": "en-us",
"folderId": "your_folder_id_here"
}'200 OK
Response body, application/json.
| Field | Type |
|---|---|
status |
string |
data |
object |
data.mediaId |
string |
data.folderId |
string |
data.userId |
string |
data.message |
string |
Example response (Session created), application/json.
{
"status": "success",
"data": {
"mediaId": "3f8d1ec6ca39",
"folderId": "your_folder_id_here",
"userId": "609d7de35bde285f4c98ca63",
"message": "Live transcript media created successfully"
}
}Example response (Meeting assistant event already had a record), application/json.
{
"status": "success",
"data": {
"mediaId": "3f8d1ec6ca39",
"folderId": "your_folder_id_here",
"userId": "609d7de35bde285f4c98ca63",
"message": "Existing live transcript media returned successfully"
}
}500 Internal Server Error
Response body, application/json.
| Field | Type |
|---|---|
status |
string |
requestId |
string |
code |
integer |
message |
string |
hints |
string[] |
Example response (Internal server error), application/json.
{
"status": "failed",
"requestId": "ca665625-645e-438a-867d-366a6e3f133a",
"code": 500,
"message": "Something went wrong. Please try again later.",
"hints": [
"Something went wrong. Please try again later."
]
}Mint a live transcription handshake token
/live-transcription/tokenMint the short-lived token that opens a live transcription streaming connection for the calling session.
The token is scoped to live transcription only. It is rejected anywhere else in the API, so it cannot stand in for an access token.
This endpoint takes no request body. The response carries the token and the number of seconds it stays valid for.
Rate limit
This endpoint is limited to 5 requests per 60 seconds per IP address. Going over returns 429 with a plain text body, so mint one token per session and reuse it until it expires.
curl -X POST 'https://api.speakai.co/v1/live-transcription/token' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'200 OK
Response body, application/json.
| Field | Type |
|---|---|
status |
string |
data |
object |
data.token |
string |
data.expiresIn |
string |
Example response (Token minted), application/json.
{
"status": "success",
"data": {
"token": "eyJhbGciOiJIUzI1NiJ9.test-live-token.0000000000",
"expiresIn": "18000s"
}
}429 Too Many Requests
Example response (Rate limited), text/plain.
Too many token requests from this IP, please try again after a minute500 Internal Server Error
Response body, application/json.
| Field | Type |
|---|---|
status |
string |
requestId |
string |
code |
integer |
message |
string |
hints |
string[] |
Example response (Internal server error), application/json.
{
"status": "failed",
"requestId": "ca665625-645e-438a-867d-366a6e3f133a",
"code": 500,
"message": "Something went wrong. Please try again later.",
"hints": [
"Something went wrong. Please try again later."
]
}Update a live transcription session
/live-transcription/update/{mediaId}Append transcribed words to a live transcription session, and hand Speak AI the finished recording when the session ends.
Send words while the session runs. Speak AI merges them into sentences by speaker and language and appends them to the transcript already on the record.
Send aws once, after the recording is uploaded. That moves the record into the preparingAnalysis state, triggers transcoding, and starts the same analysis an uploaded file gets. Include totalDuration with it so the duration is right when the uploaded file does not report one.
Both fields are optional and they can be sent in the same call.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
mediaId |
path | string | Yes | Id returned by POST /live-transcription/create. |
Request body
Field types and names come from the request body the spec records. The spec does not mark request body fields as required, so read this as the shape the endpoint accepts rather than a required field list.
| Field | Type | Description |
|---|---|---|
words |
object[] | Words transcribed since the last call, in order. |
words[].id |
integer | Position of the word in the session. |
words[].text |
string | The word itself. |
words[].confidence |
number | Recogniser confidence for the word, from 0 to 1. |
words[].language |
string | Language code the word was recognised in. |
words[].speakerId |
string | Speaker the word is attributed to. |
words[].instances |
object | Where the word sits in the recording. |
words[].email |
string | Email of the speaker, when the session knows it. |
words[].userId |
string | Speak AI user id of the speaker, when the session knows it. |
aws |
object | Location of the finished recording. Send this once, at the end of the session. |
aws.bucket |
string | |
aws.key |
string | |
aws.location |
string | |
totalDuration |
number | Length of the session in seconds, used when the uploaded file reports a duration of 0. |
Deeper nested fields are not listed. See the example response below for the full shape.
curl -X POST 'https://api.speakai.co/v1/live-transcription/update/3f8d1ec6ca39' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
-H 'Content-Type: application/json' \
-d '{
"words": [
{
"id": 1,
"text": "hello",
"confidence": 0.95,
"language": "en",
"speakerId": "speaker-1",
"instances": {
"startInSec": 1.2,
"endInSec": 1.5
}
}
]
}'200 OK
Response body, application/json.
| Field | Type |
|---|---|
status |
string |
message |
string |
Example response (Words appended), application/json.
{
"status": "success",
"message": "Live transcription updated successfully"
}404 Not Found
Response body, application/json.
| Field | Type |
|---|---|
status |
string |
requestId |
string |
code |
integer |
message |
string |
hints |
string[] |
Example response (No media record for that id), application/json.
{
"status": "failed",
"requestId": "3fcf7e0c-a977-4c37-bae5-a72485206cd0",
"code": 404,
"message": "Media does not exist!",
"hints": [
"The requested operation failed because a resource associated with the request could not be found."
]
}500 Internal Server Error
Response body, application/json.
| Field | Type |
|---|---|
status |
string |
requestId |
string |
code |
integer |
message |
string |
hints |
string[] |
Example response (Internal server error), application/json.
{
"status": "failed",
"requestId": "ca665625-645e-438a-867d-366a6e3f133a",
"code": 500,
"message": "Something went wrong. Please try again later.",
"hints": [
"Something went wrong. Please try again later."
]
}Related pages
- API reference for the base URL, authentication, and the error format.
- Authenticate with the Speak AI API using access tokens
- Upload audio and video to Speak AI and read insights
- Analyze text notes with the Speak AI text endpoints
- Export Speak AI transcripts and insights to a file
Get an API key on the Speak AI developer page.