OATDA Speech Generation
Generate spoken audio from text through OATDA's unified audio API.
When to Use
Use this skill when the user wants to:
- Convert text to speech or audio
- Create voiceovers, announcements, narration, or accessibility audio
- Use TTS models from OpenAI, xAI, Google and others through OATDA
- Use the OATDA
generate_speechcapability
HTTP vs MCP (read this first)
| Path | Response | Use when |
|---|---|---|
MCP generate_speech |
Text with AUDIO_URL: (HMAC ?exp=&sig=, ~1h TTL) + metadata in structuredContent (download_url, format, duration_seconds, costs) |
Already connected to OATDA MCP (Cursor, etc.) |
HTTP POST /api/v1/llm/speech |
Raw audio bytes (Content-Disposition: attachment) |
Shell/scripts: curl --output speech.mp3 |
Upstream providers (OpenAI TTS, xAI Grok TTS) do not return a hosted download URL for speech. xAI returns raw bytes (curl ... --output hello.mp3 in their docs). OATDA MCP mirrors TTS into a short-lived signed download so editors can fetch without a browser session.
MCP agents: After generate_speech, extract AUDIO_URL: from the tool text (or structuredContent.download_url) and download with curl - no login required. Do not expect MCP AudioContent / base64 audio blocks (removed). URL expires in ~1 hour.
Shell/scripts: Prefer HTTP with --output (see step 4), or MCP signed URL + curl.
Prerequisites
The user needs an OATDA API key. Check in this order:
$OATDA_API_KEYenvironment variable~/.oatda/credentials.jsonconfig file
If neither exists, tell the user:
You need an OATDA API key. Get one at https://oatda.com, then set it:
export OATDA_API_KEY=your_key_here
Step-by-Step Instructions
1. Resolve the API key
# Check env var first; if empty, auto-load from credentials file
if [[ -z "$OATDA_API_KEY" ]]; then
export OATDA_API_KEY=$(cat ~/.oatda/credentials.json 2>/dev/null | jq -r '.profiles[.defaultProfile].apiKey' 2>/dev/null)
fi
# Verify key exists (show first 8 chars only)
echo "${OATDA_API_KEY:0:8}"
If the output is empty or null, stop and ask the user to configure their API key.
IMPORTANT:
- Never print the full API key. Only show the first 8 characters for verification.
- The key resolution script and subsequent
curlcommands must run in the same shell session. Each separate bash/terminal invocation starts with an isolated environment where previously exported variables are lost. Either run all commands in one session, or chain them.
2. Determine the model and voice
⚠️ Model availability changes over time. Always call
list_modelswithtype="audio"(or/api/v1/llm/models?type=audio) to verify the exact model ID, available voices, and supported parameters before generating speech.
If the user provides provider/model format directly (e.g. openai/gpt-4o-mini-tts or xai/grok-tts), split on / to get separate provider and model values for the JSON body.
Use list_models results to determine:
- Available voices (from
supported_params.voice.values) - Supported response formats
- Optional parameters like
languageorinstructions - Any per-model constraints
If the user does not specify a model, query list_models first and offer a choice from the currently available TTS models.
3. Optional: discover available audio models
curl -s -X GET "https://oatda.com/api/v1/llm/models?type=audio" \
-H "Authorization: Bearer $OATDA_API_KEY" | jq '.audio_models[] | {id, supported_params}'
Use supported_params to confirm model-specific options before sending optional fields.
4. Make the HTTP API call (preferred)
The speech endpoint returns binary audio, not JSON and not a URL. Always save with --output (same pattern as xAI's official TTS examples).
curl -s -X POST "https://oatda.com/api/v1/llm/speech" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OATDA_API_KEY" \
-d '{
"provider": "<PROVIDER>",
"model": "<MODEL>",
"input": "<TEXT_TO_SPEAK>",
"voice": "alloy",
"response_format": "mp3",
"speed": 1.0
}' \
--output speech.mp3
Replace <PROVIDER>, <MODEL>, and <TEXT_TO_SPEAK> with actual values.
Parameters:
input: Text to convert to speech, max 15000 charactersvoice: Voice name, e.g.alloy,nova,shimmerresponse_format:mp3,opus,aac,flac,wav,pcm,mulaw, oralawspeed: 0.25 to 4.0, default 1.0instructions: Optional style/tone instructions for supported modelslanguage: Optional language code for supported models
5. Present the result
If the request succeeds, tell the user the absolute or workspace path to the saved file, e.g.:
Speech generated successfully:
speech.mp3(binary MP3, ready to play)
If you need to inspect the response headers, use curl -D headers.txt while still saving the body to an audio file.
MCP generate_speech
- Call with
model(verify exact ID vialist_modelswithtype="audio"),text, optionalvoice,response_format. - Tool result text contains
AUDIO_URL: https://.../api/v1/oneagent/generated/<uuid>?exp=...&sig=...(also instructuredContent.download_url). - Download without login:
curl -fsSL -o speech.mp3 '<AUDIO_URL from tool result>'
- Do not look for an MCP
audiocontent block / base64 payload - that contract was removed. - URL is audio-only and expires in ~1 hour (Redis TTL). Image/video MCP delivery is unchanged (provider URLs).
xAI example (HTTP)
curl -s -X POST "https://oatda.com/api/v1/llm/speech" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OATDA_API_KEY" \
-d '{
"provider": "xai",
"model": "grok-tts",
"input": "Hallo, das ist ein Test mit Grok TTS.",
"voice": "eve",
"language": "de",
"response_format": "mp3"
}' \
--output grok-speech.mp3
6. Handle errors
| HTTP Status | Meaning | Action |
|---|---|---|
| 401 | Invalid API key | Tell user to check their key at https://oatda.com/dashboard/api-keys |
| 402 | Insufficient credits | Tell user to check balance at https://oatda.com/dashboard/usage |
| 400 | Bad request / model not supported | Check model format and use /oatda:oatda-list-models with type=audio |
| 429 | Rate limited or monthly cap | Wait briefly and retry once, or ask user to check caps |
| 500 | Provider error | Show the error message if returned |
Full Example
User asks: "Convert this text to speech with alloy voice using OpenAI TTS"
curl -s -X POST "https://oatda.com/api/v1/llm/speech" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OATDA_API_KEY" \
-d '{
"provider": "openai",
"model": "gpt-4o-mini-tts",
"input": "Welcome to OATDA, one API to direct all.",
"voice": "alloy",
"response_format": "mp3",
"speed": 1.0
}' \
--output speech.mp3
Note: The model ID above is an example. Always verify the current model ID via
list_modelsbefore use.
Tips
- The endpoint is
/api/v1/llm/speech. - Use
input, notprompt, for text-to-speech requests. - HTTP: response body = audio bytes; always use
curl --output <file>. Not a JSON URL. - MCP: signed
AUDIO_URLin tool text /structuredContent.download_url; download with curl (no session). Expires ~1h. - TTS is not like image generation:
grok-imagine-imagemay return an HTTPS URL; HTTPgrok-ttsreturns raw bytes. MCP speech adds OATDA's short-lived signed mirror. - For model discovery, use
/api/v1/llm/models?type=audioor MCPlist_modelswithtype="audio". - Keep text under 15000 characters (stricter limits may apply per model).
- NEVER expose the full API key in output.
- MCP tool name:
generate_speech(signed download URL, not AudioContent base64). - Related skills:
/oatda:oatda-list-models,/oatda:oatda-transcribe-audio,/oatda:oatda-translate-audio.