curl --request POST \
--url https://users.rime.ai/v1/rime-tts \
--header 'Accept: audio/webm;codecs=opus' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--output output.webm \
--fail \
--data '{
"text": "Hello from Rime!",
"modelId": "coda",
"speaker": "astra",
"lang": "en",
"samplingRate": 24000
}'
import requests
url = "https://users.rime.ai/v1/rime-tts"
payload = {
"speaker": "astra",
"text": "Hello from Rime!",
"modelId": "coda",
"samplingRate": 24000
}
headers = {
"Accept": "audio/webm;codecs=opus",
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
with requests.post(url, headers=headers, json=payload, stream=True) as response:
response.raise_for_status()
with open("output.webm", "wb") as f:
for chunk in response.iter_content(chunk_size=4096):
if chunk:
f.write(chunk)
const fs = require("fs");
const options = {
method: 'POST',
headers: {
Accept: 'audio/webm;codecs=opus',
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: '{"speaker":"astra","text":"Hello from Rime!","modelId":"coda","samplingRate":24000}'
};
fetch('https://users.rime.ai/v1/rime-tts', options)
.then(response => response.arrayBuffer())
.then(buffer => {
fs.writeFileSync("output.webm", Buffer.from(buffer));
console.log("Audio saved to output.webm");
})
.catch(err => console.error(err));
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://users.rime.ai/v1/rime-tts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\n \"speaker\": \"astra\",\n \"text\": \"Hello from Rime!\",\n \"modelId\": \"coda\",\n \"samplingRate\": 24000\n}",
CURLOPT_HTTPHEADER => [
"Accept: audio/webm;codecs=opus",
"Authorization: Bearer YOUR_API_KEY",
"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 (
"io"
"net/http"
"os"
"strings"
)
func main() {
url := "https://users.rime.ai/v1/rime-tts"
payload := strings.NewReader("{\n \"speaker\": \"astra\",\n \"text\": \"Hello from Rime!\",\n \"modelId\": \"coda\",\n \"samplingRate\": 24000\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Accept", "audio/webm;codecs=opus")
req.Header.Add("Authorization", "Bearer YOUR_API_KEY")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
_ = os.WriteFile("output.webm", body, 0644)
}
HttpResponse<byte[]> response = Unirest.post("https://users.rime.ai/v1/rime-tts")
.header("Accept", "audio/webm;codecs=opus")
.header("Authorization", "Bearer YOUR_API_KEY")
.header("Content-Type", "application/json")
.body("{\n \"speaker\": \"astra\",\n \"text\": \"Hello from Rime!\",\n \"modelId\": \"coda\",\n \"samplingRate\": 24000\n}")
.asBytes();
Files.write(Paths.get("output.webm"), response.getBody());
Coda API reference
Streaming HTTP
Coda streaming HTTP endpoint: synthesize speech with Rime’s flagship model and stream audio back.
curl --request POST \
--url https://users.rime.ai/v1/rime-tts \
--header 'Accept: audio/webm;codecs=opus' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--output output.webm \
--fail \
--data '{
"text": "Hello from Rime!",
"modelId": "coda",
"speaker": "astra",
"lang": "en",
"samplingRate": 24000
}'
import requests
url = "https://users.rime.ai/v1/rime-tts"
payload = {
"speaker": "astra",
"text": "Hello from Rime!",
"modelId": "coda",
"samplingRate": 24000
}
headers = {
"Accept": "audio/webm;codecs=opus",
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
with requests.post(url, headers=headers, json=payload, stream=True) as response:
response.raise_for_status()
with open("output.webm", "wb") as f:
for chunk in response.iter_content(chunk_size=4096):
if chunk:
f.write(chunk)
const fs = require("fs");
const options = {
method: 'POST',
headers: {
Accept: 'audio/webm;codecs=opus',
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: '{"speaker":"astra","text":"Hello from Rime!","modelId":"coda","samplingRate":24000}'
};
fetch('https://users.rime.ai/v1/rime-tts', options)
.then(response => response.arrayBuffer())
.then(buffer => {
fs.writeFileSync("output.webm", Buffer.from(buffer));
console.log("Audio saved to output.webm");
})
.catch(err => console.error(err));
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://users.rime.ai/v1/rime-tts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\n \"speaker\": \"astra\",\n \"text\": \"Hello from Rime!\",\n \"modelId\": \"coda\",\n \"samplingRate\": 24000\n}",
CURLOPT_HTTPHEADER => [
"Accept: audio/webm;codecs=opus",
"Authorization: Bearer YOUR_API_KEY",
"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 (
"io"
"net/http"
"os"
"strings"
)
func main() {
url := "https://users.rime.ai/v1/rime-tts"
payload := strings.NewReader("{\n \"speaker\": \"astra\",\n \"text\": \"Hello from Rime!\",\n \"modelId\": \"coda\",\n \"samplingRate\": 24000\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Accept", "audio/webm;codecs=opus")
req.Header.Add("Authorization", "Bearer YOUR_API_KEY")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
_ = os.WriteFile("output.webm", body, 0644)
}
HttpResponse<byte[]> response = Unirest.post("https://users.rime.ai/v1/rime-tts")
.header("Accept", "audio/webm;codecs=opus")
.header("Authorization", "Bearer YOUR_API_KEY")
.header("Content-Type", "application/json")
.body("{\n \"speaker\": \"astra\",\n \"text\": \"Hello from Rime!\",\n \"modelId\": \"coda\",\n \"samplingRate\": 24000\n}")
.asBytes();
Files.write(Paths.get("output.webm"), response.getBody());
The Rime API authenticates every request with a bearer token in the
Authorization header: Authorization: Bearer YOUR_API_KEY. See API authentication for how to create a key.
The endpoint streams audio in the format you name in the Accept header. If Accept is missing or a wildcard, the API streams headerless 16-bit PCM, which audio players won’t open. If it names a type the API can’t stream, the API returns 406 with the list of supported types.
Audio formats
Set theAccept header to one of the following values:
| Format | Accept Header | Notes |
|---|---|---|
| Opus (WebM) | audio/webm;codecs=opus | Recommended. Smaller files than MP3 at comparable quality. WebM streams natively in browsers. |
| Opus (OGG) | audio/ogg;codecs=opus | Opus in an OGG container. Smaller files than MP3 at comparable quality. |
| MP3 | audio/mpeg | Lower compression rate than Opus. Highest compatibility across devices and players. |
| WAV | audio/wav | Uncompressed. RIFF WAVE header with 16-bit little-endian linear PCM samples. Streams natively in browsers. |
| PCM | audio/L16 | Headerless 16-bit little-endian linear PCM. |
| G.711 μ-law | audio/PCMU | Headerless stream of audio bytes. |
Deprecated aliases
The API still accepts these for backward compatibility. Use the RFC types above in new code.| Deprecated | Use instead |
|---|---|
audio/mp3 | audio/mpeg |
audio/pcm | audio/L16 |
audio/x-mulaw | audio/PCMU |
Variable parameters
string
required
Must be a Coda voice. See the voice catalog.
string
required
The text you’d like spoken. The API accepts up to 1,000 characters per request.
string
Set to
coda to select the Coda voice lineup. Without it, the API uses Mist v3.string
default:"en"
If provided, the language must match the language spoken by the provided speaker. Pass a BCP 47 language tag:
The 3-letter ISO 639-2 codes that older integrations send (
| Tag | Language |
|---|---|
en | English |
es | Spanish |
fr | French |
pt | Portuguese |
de | German |
ja | Japanese |
ar | Arabic |
hi | Hindi |
it | Italian |
eng, spa, fra, por, ger, jpn, ara, hin, ita) remain accepted, and will stay accepted.See the voices documentation for which speakers support each language.number
default:"24000"
The sampling rate (Hz).
number
default:"1.0"
The time scaling factor. Accepted range is 0.4 to 2.5. Values outside this range are clamped without an error.Values above 1.0 slow the audio down, and values below 1.0 speed it up.
curl --request POST \
--url https://users.rime.ai/v1/rime-tts \
--header 'Accept: audio/webm;codecs=opus' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--output output.webm \
--fail \
--data '{
"text": "Hello from Rime!",
"modelId": "coda",
"speaker": "astra",
"lang": "en",
"samplingRate": 24000
}'
import requests
url = "https://users.rime.ai/v1/rime-tts"
payload = {
"speaker": "astra",
"text": "Hello from Rime!",
"modelId": "coda",
"samplingRate": 24000
}
headers = {
"Accept": "audio/webm;codecs=opus",
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
with requests.post(url, headers=headers, json=payload, stream=True) as response:
response.raise_for_status()
with open("output.webm", "wb") as f:
for chunk in response.iter_content(chunk_size=4096):
if chunk:
f.write(chunk)
const fs = require("fs");
const options = {
method: 'POST',
headers: {
Accept: 'audio/webm;codecs=opus',
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: '{"speaker":"astra","text":"Hello from Rime!","modelId":"coda","samplingRate":24000}'
};
fetch('https://users.rime.ai/v1/rime-tts', options)
.then(response => response.arrayBuffer())
.then(buffer => {
fs.writeFileSync("output.webm", Buffer.from(buffer));
console.log("Audio saved to output.webm");
})
.catch(err => console.error(err));
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://users.rime.ai/v1/rime-tts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\n \"speaker\": \"astra\",\n \"text\": \"Hello from Rime!\",\n \"modelId\": \"coda\",\n \"samplingRate\": 24000\n}",
CURLOPT_HTTPHEADER => [
"Accept: audio/webm;codecs=opus",
"Authorization: Bearer YOUR_API_KEY",
"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 (
"io"
"net/http"
"os"
"strings"
)
func main() {
url := "https://users.rime.ai/v1/rime-tts"
payload := strings.NewReader("{\n \"speaker\": \"astra\",\n \"text\": \"Hello from Rime!\",\n \"modelId\": \"coda\",\n \"samplingRate\": 24000\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Accept", "audio/webm;codecs=opus")
req.Header.Add("Authorization", "Bearer YOUR_API_KEY")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
_ = os.WriteFile("output.webm", body, 0644)
}
HttpResponse<byte[]> response = Unirest.post("https://users.rime.ai/v1/rime-tts")
.header("Accept", "audio/webm;codecs=opus")
.header("Authorization", "Bearer YOUR_API_KEY")
.header("Content-Type", "application/json")
.body("{\n \"speaker\": \"astra\",\n \"text\": \"Hello from Rime!\",\n \"modelId\": \"coda\",\n \"samplingRate\": 24000\n}")
.asBytes();
Files.write(Paths.get("output.webm"), response.getBody());

