Dictation Session Streaming
Stream audio to an active Dictation session for real-time transcription
curl --request GET \
--url https://sdp.suki.ai/ws/transcribe \
--header 'sdp_suki_token: <sdp_suki_token>' \
--header 'sdp_provider_id: <sdp_provider_id>' \
--header 'transcription_session_id: <transcription_session_id>'import requests
url = "https://sdp.suki.ai/ws/transcribe"
headers = {
"transcription_session_id": "<transcription_session_id>",
"sdp_suki_token": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {
transcription_session_id: '<transcription_session_id>',
sdp_suki_token: '<api-key>'
}
};
fetch('https://sdp.suki.ai/ws/transcribe', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sdp.suki.ai/ws/transcribe",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"sdp_suki_token: <api-key>",
"transcription_session_id: <transcription_session_id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://sdp.suki.ai/ws/transcribe"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("transcription_session_id", "<transcription_session_id>")
req.Header.Add("sdp_suki_token", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://sdp.suki.ai/ws/transcribe")
.header("transcription_session_id", "<transcription_session_id>")
.header("sdp_suki_token", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://sdp.suki.ai/ws/transcribe")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["transcription_session_id"] = '<transcription_session_id>'
request["sdp_suki_token"] = '<api-key>'
response = http.request(request)
puts response.read_body"<string>""<string>""<string>""<string>""<string>""<string>"Related guides
Dictation Implementation Guide
Dictation Streaming Wire Format
Read Transcript Frames from Dictation Session
Audio Streaming vs Dictation Streaming
Prerequisites
Complete these steps before opening the WebSocket./ws/transcribe while another speech session is still finishing often leads to handshake failures (FailedPrecondition). After AUDIO_END and EOF, wait about 5 seconds before you open the next WebSocket. Refer to Stream Dictation audio guide for more information.- Authenticate and obtain
sdp_suki_token. - Create a Dictation session with POST
/api/v1/transcription/session/create. A successful create returns 201 Created; keep thetranscription_session_idfrom the response. - Authenticate and open the WebSocket on
wss://sdp.suki-stage.com/ws/transcribe. To stream audio, you must first establish an authenticated WebSocket connection. The authentication method you use depends on your client type: browser or non-browser.
- Stream audio in chunks for the best latency and throughput.
- For partial and final inbound transcript frames,
EOF, and session state rules, refer to Dictation transcript frames.
Inbound transcript messages
The server sends JSON text frames with top-leveltranscript, is_final, transcript_id, and lang_id. Use snake_case is_final to identify whether the
transcript is a partial result or a final result. After the audio stream ends, the server sends { "transcript": { "transcript": "EOF" } } and then closes the WebSocket connection.
words and speaker IDs on finals, and client-side filtering rules.Authentication
Authentication is applied during the WebSocket handshake. The method depends on your client type. Use theSec-WebSocket-Protocol header for browser clients, and sdp_suki_token and transcription_session_id headers for non-browser clients.
Browser clients
If you are connecting from a browser, you must use theSec-WebSocket-Protocol header during the WebSocket handshake.
The header must specify the SukiAmbientAuth protocol, followed by the token and the transcription session ID in the following format.
Sec-WebSocket-Protocol: SukiAmbientAuth,<sdp_suki_token>,<transcription_session_id>
Non-browser clients
If you are connecting from a non-browser client, such as a mobile or server-side application, you must provide the token and session ID as separate HTTP headers in the initial WebSocket upgrade request.sdp_suki_token: Session token from login.sdp_provider_id: Provider identifier. Optional for standard partners; Required for Single Auth Token authentication.transcription_session_id: The ID for the current session.
- All messages must be sent as JSON text frames over the WebSocket connection.
- Do not send raw binary data or use HTTP endpoints for streaming audio.
Full code examples
For end-to-end Dictation streaming examples, start with these tutorials:Authorizations
Suki access token (suki_token) from Login or Register. Expires after one hour.
Headers
Required FOR BROWSER CLIENTS ONLY. Sent during WebSocket handshake. Browsers must use the same subprotocol the grpc-wsproxy maps to Authorization: 'SukiAmbientAuth,<sdp_suki_token>,<transcription_session_id>' (comma-separated; token second, transcription session id third). Other names (e.g. SukiTranscriptionAuth) are not mapped and typically yield 401.
Required for non-browser clients only. UUID from Create Transcription Session.
Optional for standard partners.
Required for:
- Bearer authentication. Use the same
provider_idreturned by the Login or Register API. - Single Auth Token authentication. Include the same
provider_idon every request assdp_provider_id.
"provider-123"
Response
Switching Protocols - Indicates successful WebSocket handshake.
The response is of type string.
Was this page helpful?
curl --request GET \
--url https://sdp.suki.ai/ws/transcribe \
--header 'sdp_suki_token: <sdp_suki_token>' \
--header 'sdp_provider_id: <sdp_provider_id>' \
--header 'transcription_session_id: <transcription_session_id>'import requests
url = "https://sdp.suki.ai/ws/transcribe"
headers = {
"transcription_session_id": "<transcription_session_id>",
"sdp_suki_token": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {
transcription_session_id: '<transcription_session_id>',
sdp_suki_token: '<api-key>'
}
};
fetch('https://sdp.suki.ai/ws/transcribe', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sdp.suki.ai/ws/transcribe",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"sdp_suki_token: <api-key>",
"transcription_session_id: <transcription_session_id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://sdp.suki.ai/ws/transcribe"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("transcription_session_id", "<transcription_session_id>")
req.Header.Add("sdp_suki_token", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://sdp.suki.ai/ws/transcribe")
.header("transcription_session_id", "<transcription_session_id>")
.header("sdp_suki_token", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://sdp.suki.ai/ws/transcribe")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["transcription_session_id"] = '<transcription_session_id>'
request["sdp_suki_token"] = '<api-key>'
response = http.request(request)
puts response.read_body"<string>""<string>""<string>""<string>""<string>""<string>"