REST endpoints
Synthesize speech
POST
/
speak
Handler for the /speak endpoint
curl --request POST \
--url https://api.sayna.ai/speak \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"text": "Hello, world!",
"tts_config": {
"model": "aura-asteria-en",
"provider": "deepgram",
"audio_format": "linear16",
"auth": {},
"connection_timeout": 30,
"pronunciations": [
{
"pronunciation": "A P I",
"word": "API"
}
],
"request_timeout": 60,
"sample_rate": 24000,
"speaking_rate": 1,
"voice_id": "aura-asteria-en"
}
}
'import requests
url = "https://api.sayna.ai/speak"
payload = {
"text": "Hello, world!",
"tts_config": {
"model": "aura-asteria-en",
"provider": "deepgram",
"audio_format": "linear16",
"auth": {},
"connection_timeout": 30,
"pronunciations": [
{
"pronunciation": "A P I",
"word": "API"
}
],
"request_timeout": 60,
"sample_rate": 24000,
"speaking_rate": 1,
"voice_id": "aura-asteria-en"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
text: 'Hello, world!',
tts_config: {
model: 'aura-asteria-en',
provider: 'deepgram',
audio_format: 'linear16',
auth: {},
connection_timeout: 30,
pronunciations: [{pronunciation: 'A P I', word: 'API'}],
request_timeout: 60,
sample_rate: 24000,
speaking_rate: 1,
voice_id: 'aura-asteria-en'
}
})
};
fetch('https://api.sayna.ai/speak', 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://api.sayna.ai/speak",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'text' => 'Hello, world!',
'tts_config' => [
'model' => 'aura-asteria-en',
'provider' => 'deepgram',
'audio_format' => 'linear16',
'auth' => [
],
'connection_timeout' => 30,
'pronunciations' => [
[
'pronunciation' => 'A P I',
'word' => 'API'
]
],
'request_timeout' => 60,
'sample_rate' => 24000,
'speaking_rate' => 1,
'voice_id' => 'aura-asteria-en'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sayna.ai/speak"
payload := strings.NewReader("{\n \"text\": \"Hello, world!\",\n \"tts_config\": {\n \"model\": \"aura-asteria-en\",\n \"provider\": \"deepgram\",\n \"audio_format\": \"linear16\",\n \"auth\": {},\n \"connection_timeout\": 30,\n \"pronunciations\": [\n {\n \"pronunciation\": \"A P I\",\n \"word\": \"API\"\n }\n ],\n \"request_timeout\": 60,\n \"sample_rate\": 24000,\n \"speaking_rate\": 1,\n \"voice_id\": \"aura-asteria-en\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sayna.ai/speak")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"text\": \"Hello, world!\",\n \"tts_config\": {\n \"model\": \"aura-asteria-en\",\n \"provider\": \"deepgram\",\n \"audio_format\": \"linear16\",\n \"auth\": {},\n \"connection_timeout\": 30,\n \"pronunciations\": [\n {\n \"pronunciation\": \"A P I\",\n \"word\": \"API\"\n }\n ],\n \"request_timeout\": 60,\n \"sample_rate\": 24000,\n \"speaking_rate\": 1,\n \"voice_id\": \"aura-asteria-en\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sayna.ai/speak")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"text\": \"Hello, world!\",\n \"tts_config\": {\n \"model\": \"aura-asteria-en\",\n \"provider\": \"deepgram\",\n \"audio_format\": \"linear16\",\n \"auth\": {},\n \"connection_timeout\": 30,\n \"pronunciations\": [\n {\n \"pronunciation\": \"A P I\",\n \"word\": \"API\"\n }\n ],\n \"request_timeout\": 60,\n \"sample_rate\": 24000,\n \"speaking_rate\": 1,\n \"voice_id\": \"aura-asteria-en\"\n }\n}"
response = http.request(request)
puts response.read_bodyKick off one-shot synthesis jobs for short responses. This endpoint reuses the same provider layer and cache that powers the streaming WebSocket experience.
Reuse identical
tts_config inputs to hit the cache and avoid extra provider round-trips.Authorizations
Authentication token for protected endpoints. Can be provided as Authorization: Bearer <token> or ?api_key=<token>. Required when AUTH_REQUIRED is enabled.
Body
application/json
Request body for the speak endpoint
The text to synthesize
Example:
"Hello, world!"
TTS configuration, including an optional provider auth override.
Show child attributes
Show child attributes
Response
Audio generated successfully
Previous
LiveKit tokenGenerates a LiveKit JWT token for a participant to join a specific room.
When authentication is enabled (`auth.id` is present), this handler:
1. Creates the room if it doesn't exist
2. Sets `room.metadata.auth_id` to the authenticated tenant's ID
3. Issues the token only after metadata is verified/set
# Arguments
* `state` - Shared application state containing LiveKit configuration
* `request` - Token request with room name and participant details
# Returns
* `Response` - JSON response with token or error status
# Errors
* 400 Bad Request - Invalid request data (empty fields)
* 403 Forbidden - Room exists with a different tenant's `auth_id`
* 500 Internal Server Error - LiveKit service not configured, room creation failed, or token generation failed
Next
⌘I
Handler for the /speak endpoint
curl --request POST \
--url https://api.sayna.ai/speak \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"text": "Hello, world!",
"tts_config": {
"model": "aura-asteria-en",
"provider": "deepgram",
"audio_format": "linear16",
"auth": {},
"connection_timeout": 30,
"pronunciations": [
{
"pronunciation": "A P I",
"word": "API"
}
],
"request_timeout": 60,
"sample_rate": 24000,
"speaking_rate": 1,
"voice_id": "aura-asteria-en"
}
}
'import requests
url = "https://api.sayna.ai/speak"
payload = {
"text": "Hello, world!",
"tts_config": {
"model": "aura-asteria-en",
"provider": "deepgram",
"audio_format": "linear16",
"auth": {},
"connection_timeout": 30,
"pronunciations": [
{
"pronunciation": "A P I",
"word": "API"
}
],
"request_timeout": 60,
"sample_rate": 24000,
"speaking_rate": 1,
"voice_id": "aura-asteria-en"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
text: 'Hello, world!',
tts_config: {
model: 'aura-asteria-en',
provider: 'deepgram',
audio_format: 'linear16',
auth: {},
connection_timeout: 30,
pronunciations: [{pronunciation: 'A P I', word: 'API'}],
request_timeout: 60,
sample_rate: 24000,
speaking_rate: 1,
voice_id: 'aura-asteria-en'
}
})
};
fetch('https://api.sayna.ai/speak', 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://api.sayna.ai/speak",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'text' => 'Hello, world!',
'tts_config' => [
'model' => 'aura-asteria-en',
'provider' => 'deepgram',
'audio_format' => 'linear16',
'auth' => [
],
'connection_timeout' => 30,
'pronunciations' => [
[
'pronunciation' => 'A P I',
'word' => 'API'
]
],
'request_timeout' => 60,
'sample_rate' => 24000,
'speaking_rate' => 1,
'voice_id' => 'aura-asteria-en'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sayna.ai/speak"
payload := strings.NewReader("{\n \"text\": \"Hello, world!\",\n \"tts_config\": {\n \"model\": \"aura-asteria-en\",\n \"provider\": \"deepgram\",\n \"audio_format\": \"linear16\",\n \"auth\": {},\n \"connection_timeout\": 30,\n \"pronunciations\": [\n {\n \"pronunciation\": \"A P I\",\n \"word\": \"API\"\n }\n ],\n \"request_timeout\": 60,\n \"sample_rate\": 24000,\n \"speaking_rate\": 1,\n \"voice_id\": \"aura-asteria-en\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sayna.ai/speak")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"text\": \"Hello, world!\",\n \"tts_config\": {\n \"model\": \"aura-asteria-en\",\n \"provider\": \"deepgram\",\n \"audio_format\": \"linear16\",\n \"auth\": {},\n \"connection_timeout\": 30,\n \"pronunciations\": [\n {\n \"pronunciation\": \"A P I\",\n \"word\": \"API\"\n }\n ],\n \"request_timeout\": 60,\n \"sample_rate\": 24000,\n \"speaking_rate\": 1,\n \"voice_id\": \"aura-asteria-en\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sayna.ai/speak")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"text\": \"Hello, world!\",\n \"tts_config\": {\n \"model\": \"aura-asteria-en\",\n \"provider\": \"deepgram\",\n \"audio_format\": \"linear16\",\n \"auth\": {},\n \"connection_timeout\": 30,\n \"pronunciations\": [\n {\n \"pronunciation\": \"A P I\",\n \"word\": \"API\"\n }\n ],\n \"request_timeout\": 60,\n \"sample_rate\": 24000,\n \"speaking_rate\": 1,\n \"voice_id\": \"aura-asteria-en\"\n }\n}"
response = http.request(request)
puts response.read_body