Docs/DevThrottle API/Speech
API

Speech

3 min read

OpenAI-compatible text to speech - the same endpoint DevThrottle's own spoken replies use. Send text, get audio bytes back. It is included in Pro and the 14-day Pro trial with no usage charge: the same entitlement that speaks replies in the app covers the calls you make with your own key. Every call needs a dt_ key.

POST/audio/speech
Synthesise speech from text. JSON in, audio bytes out - streamed, not buffered.

Request

ParameterTypeRequiredDescription
modelstringRequiredA speech model id from GET /models?type=speech. Unknown models are rejected outright - there is no silent substitution.
inputstringRequiredThe text to speak. Maximum 4,000 characters; longer text returns 400 input_too_long, and the error states the limit.
voicestringOptionalA voice id from the model's voices list in GET /models?type=speech. Omit it and the model's default voice is used.
response_formatstringOptionalmp3 (default), opus, flac, wav, or pcm. Anything else returns 400 unsupported_response_format.

Only those four fields are sent on: anything else in the body is dropped rather than forwarded, so a field that is not documented here has no effect.

Example
curl https://devthrottle.com/api/v1/audio/speech   -H "Authorization: Bearer $DEVTHROTTLE_API_KEY"   -H "Content-Type: application/json"   -d '{
    "model": "MODEL_ID_FROM_/models?type=speech",
    "input": "Your session finished."
  }'   --output speech.mp3

Response

The audio itself, not JSON: raw bytes with the Content-Type of the format that was synthesised (audio/mpeg for mp3, and the matching type for the others). The bytes stream as they arrive, so a client can start playing before synthesis finishes. An error, by contrast, is always the OpenAI-shaped JSON body - so branch on the status code, not on the content type.

Voices

Voices belong to the model, so the catalog is where you read them: GET /models?type=speech returns each model's voices (the ids you can send), voiceDetails (the same ids with the language each one speaks, so you can offer only the voices that match a user's language), and defaultVoice. Fetch them rather than hard-coding: which voices exist is a property of the model being served.

Who can call it, and how it is paid

Speech comes with Pro and the 14-day Pro trial. It never spends credits, on any path - so an account with no active subscription or trial is declined with 402 and subscription_required, and loading credits does not change that. Included AI features also share a monthly fair-use limit; an account that reaches it gets 402 with fair_use_limit_reached until it resets at the start of the next month. Every call still appears in Usage.

Status codes

  • 400 - invalid_request_error (the body was not valid JSON), missing_model, missing_input, invalid_input, unknown_model, input_too_long, or unsupported_response_format.
  • 401 - invalid_api_key.
  • 402 - subscription_required or fair_use_limit_reached, as above.
  • 404 - not_found: wrong path or wrong method (this endpoint is POST only).
  • 500 - internal_error.
  • 502 - upstream_error: the speech service could not be reached.

When the speech service answers with an error of its own, that status reaches you unchanged - a 429 arrives as a 429, with its Retry-After when it sent one - while the body is replaced with DevThrottle's own wording. Treat any non-2xx as an error rather than switching only on the list above; the full shape is on errors and limits.

Note
Audio you never received is never metered: if synthesis fails, or the stream breaks mid-clip, the attempt is recorded as a failure and nothing is charged against your account.