Text-to-Speech
Synthesize audio from text via the OpenAI-compatible /v1/audio/speech endpoint, backed by Cloudflare Workers AI MeloTTS.
Endpoint
POST /v1/audio/speech
OpenAI-compatible text-to-speech. Returns raw audio bytes (mp3, wav, or opus). Drop-in compatible with the OpenAI client.audio.speech.create() API.
Request Body
| Field | Type | Default | Description |
|---|---|---|---|
model |
string | "auto" |
TTS model (see Providers). Use "auto" for health-aware routing. |
input |
string | required | Text to speak. 1–10,000 chars. |
voice |
string | "alloy" |
One of alloy, echo, fable, onyx, nova, shimmer (Workers AI MeloTTS). |
response_format |
string | "mp3" |
One of "mp3", "wav", "opus", "flac". Actual formats served depend on provider. |
speed |
number | 1.0 |
Playback speed multiplier, 0.25–4.0. Honoured by providers that expose it. |
project_id |
string | — | Body-level project tag. Alternative to x-gateway-project-id header. |
Required Header
| Header | Required | Description |
|---|---|---|
Authorization: Bearer <GATEWAY_API_KEY> |
yes | Gateway API key. |
x-gateway-project-id |
yes (or body project_id) |
1–64 chars [a-zA-Z0-9._:-]. |
x-gateway-force-provider |
no | Pin to workers_ai or groq. |
Providers
| Provider | Model | Voices | Status |
|---|---|---|---|
| Cloudflare Workers AI | @cf/myshell-ai/melotts |
alloy, echo, fable, onyx, nova, shimmer |
Enabled — no external key, uses Workers AI binding. |
| Groq PlayAI | playai-tts |
— | :warning: Disabled — Groq deprecated playai-tts on their free tier. Kept in the registry for future re-enablement but currently returns no_tts_provider. |
Response
Binary audio bytes. The Content-Type matches the served format:
| Format | Content-Type |
|---|---|
| mp3 | audio/mpeg |
| wav | audio/wav |
| opus | audio/opus |
Response Headers:
| Header | Description |
|---|---|
x-gateway-provider |
Provider that served the request (e.g. workers_ai). |
x-gateway-model |
Exact model used. |
x-gateway-project-id |
Echoes the resolved project id. |
Examples
curl https://ai-gateway.sassmaker.com/v1/audio/speech \
-H "Authorization: Bearer <GATEWAY_API_KEY>" \
-H "x-gateway-project-id: my_project" \
-H "Content-Type: application/json" \
-d '{
"model": "auto",
"input": "Hello world. This is the free AI gateway speaking.",
"voice": "nova",
"response_format": "mp3"
}' \
--output speech.mp3const response = await fetch('https://ai-gateway.sassmaker.com/v1/audio/speech', {
method: 'POST',
headers: {
'Authorization': 'Bearer <GATEWAY_API_KEY>',
'x-gateway-project-id': 'my_project',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'auto',
input: 'Hello world. This is the free AI gateway speaking.',
voice: 'nova',
response_format: 'mp3',
}),
});
const audioBlob = await response.blob();
const url = URL.createObjectURL(audioBlob);
new Audio(url).play();
console.log('Served by:', response.headers.get('x-gateway-provider'));import OpenAI from 'openai';
import fs from 'fs';
const client = new OpenAI({
baseURL: 'https://ai-gateway.sassmaker.com/v1',
apiKey: '<GATEWAY_API_KEY>',
defaultHeaders: { 'x-gateway-project-id': 'my_project' },
});
const mp3 = await client.audio.speech.create({
model: 'auto',
voice: 'shimmer',
input: 'Hello from Claude and the free AI gateway.',
});
const buffer = Buffer.from(await mp3.arrayBuffer());
await fs.promises.writeFile('speech.mp3', buffer);Error Codes
| Status | code |
Meaning |
|---|---|---|
| 400 | invalid_project_id |
Missing/invalid project_id. |
| 502 | provider_error |
All TTS candidates failed. Last upstream error is included in the message. |
| 503 | no_tts_provider |
No TTS binding/key configured. |