/v1/media/samples serves one sample clip per speech and transcription model, made through the Albastov API. Both
routes need no key. Every cloning model speaks the sample line in the shared synthetic voice
vo_hVAiUiqrYyvgKKkBvgzHnh, kokoro speaks the line in its built-in voice af_heart, and parakeet transcribes
the clip of the shared voice.
List samples
GET /v1/media/samples returns the sample line and the newest sample of each model, recommended models first.
Headers
| Name | Description |
|---|---|
Cache-Control | Response. public, max-age=60 |
Request
curl
curl https://api.albastov.com/v1/media/samplesPython
import json
import urllib.request
with urllib.request.urlopen(urllib.request.Request("https://api.albastov.com/v1/media/samples", headers={"User-Agent": "my-app/1.0"}), timeout=30) as res:
samples = json.load(res)
print(samples["text"])
for s in samples["samples"]:
print(s["model"], s["duration_s"], s["url"])JavaScript
const res = await fetch("https://api.albastov.com/v1/media/samples");
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const { text, samples } = await res.json();
console.log(text);
for (const s of samples) console.log(s.model, s.duration_s, s.url);Response
{
"text": "The river bends past the old mill, where a narrow footbridge crosses to the orchard on the far bank, and the path climbs gently into the hills.",
"samples": [
{
"model": "omnivoice",
"url": "https://api.albastov.com/v1/media/samples/omnivoice-0c943a261a69d4ec.mp3",
"content_type": "audio/mpeg",
"bytes": 123692,
"duration_s": 7.66,
"gen_s": 6.3,
"voice": "vo_hVAiUiqrYyvgKKkBvgzHnh",
"created_at": "2026-11-01T04:00:48.067Z"
},
{
"model": "parakeet",
"url": "https://api.albastov.com/v1/media/samples/parakeet-7d74d019c0b0b3c7.mp3",
"content_type": "audio/mpeg",
"bytes": 228140,
"duration_s": 14.26,
"gen_s": 4.06,
"voice": "vo_hVAiUiqrYyvgKKkBvgzHnh",
"created_at": "2026-11-01T04:04:31.261Z",
"transcript": "Morning light reached the harbour slowly. A cargo ship waited by the pier while gulls circled above the cranes. On the quay a clerk checked the last list of crates, folded it twice, and walked back toward the office as the tide began to turn."
}
]
}The response above is shortened to two samples.
| Field | Value |
|---|---|
text | The line every speech model speaks |
samples[].model | The model id |
samples[].url | The clip; the file name carries the file's hash, so a new sample gets a new URL |
samples[].content_type, bytes, duration_s | The clip's type, size and length in seconds |
samples[].gen_s | Seconds the model took to make the sample |
samples[].voice | The voice the model spoke in; for a transcription model, the voice of the transcribed clip |
samples[].transcript | The transcript, on transcription models only |
samples[].created_at | RFC 3339 time |
A model that leaves the model list keeps its sample in the list, after the current models.
Get a sample file
GET /v1/media/samples/{file} returns one sample clip.
Parameters
| Name | Type | Description |
|---|---|---|
file required | string | The file name from samples[].url, such as kokoro-486457742609d56d.mp3, in the path |
Headers
| Name | Description |
|---|---|
Range | Request. A byte range, such as bytes=0-1023; the answer is 206 with Content-Range |
Content-Type | Response. The clip's audio type, such as audio/mpeg |
Cache-Control | Response. public, max-age=31536000, immutable |
Request
A sample's file name changes when the sample is made again. The example reads the current Kokoro sample's URL from the list, then downloads the file.
curl
URL=$(curl https://api.albastov.com/v1/media/samples \
| python3 -c 'import json, sys; print(next(s["url"] for s in json.load(sys.stdin)["samples"] if s["model"] == "kokoro"))')
curl "$URL" --output kokoro.mp3Python
import json
import urllib.request
with urllib.request.urlopen(urllib.request.Request("https://api.albastov.com/v1/media/samples", headers={"User-Agent": "my-app/1.0"}), timeout=30) as res:
url = next(s["url"] for s in json.load(res)["samples"] if s["model"] == "kokoro")
with urllib.request.urlopen(urllib.request.Request(url, headers={"User-Agent": "my-app/1.0"}), timeout=30) as res, open("kokoro.mp3", "wb") as f:
f.write(res.read())JavaScript
import { writeFile } from "node:fs/promises";
const list = await (await fetch("https://api.albastov.com/v1/media/samples")).json();
const { url } = list.samples.find((s) => s.model === "kokoro");
const res = await fetch(url);
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
await writeFile("kokoro.mp3", Buffer.from(await res.arrayBuffer()));Response
200 with the clip as the body; 206 for a byte range.
Errors
| Status | Code | Meaning |
|---|---|---|
| 404 | not_found | No sample with the file name |