DocsOpen Moon AI
Browse the docs

Audio (speech and transcription)

Reference for POST /v1/audio/speech, which reads a text aloud, and POST /v1/audio/transcriptions, which transcribes a recording, in the OpenAI format.

On this page

Two endpoints in the format of the OpenAI Audio API: one turns text into speech, the other turns a recording into text. The audio you send is processed in memory and never written to our servers. Moon Blur does not apply to the text read aloud or to the audio (X-Moon-Blur: not_applied).

Read a text aloudLink to the Read a text aloud section

HTTP
POST https://api.realmoon.ai/v1/audio/speech
  • Authentication: an sk-moon-… key with the inference scope (see Authentication).
  • Body: JSON, 256 KB at most.
  • Response: the audio file itself.

ParametersLink to the Parameters section

ParameterTypeRequiredDescription
modelstringyesA speech model from GET /v1/models?type=speech.
inputstringyesThe text to read, 4,096 characters at most. Split a longer text into several requests.
voicestringnoThe ID of one of the model’s voices: letters, digits, spaces and _ . : ( ) + -, 128 characters at most. Empty: the model’s default voice (default_voice in /v1/models).
response_formatstringnomp3 (default). Gemini voices also accept wav and pcm (response_formats in /v1/models).
instructionsstringnoReading style (tone, pace), 500 characters at most. Gemini voices only.
speednumbernoOnly 1 is accepted.
languagestringnoAccepted, with no effect.

Any other parameter is rejected with 400 unknown_parameter.

ExampleLink to the Example section

cURL
curl https://api.realmoon.ai/v1/audio/speech \
  -H "Authorization: Bearer $MOONAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "mistralai/voxtral-mini-tts-2603", "voice": "fr_marie_neutral", "input": "Hello and welcome."}' \
  -o hello.mp3
Python
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.realmoon.ai/v1", api_key=os.environ["MOONAI_API_KEY"])

with client.audio.speech.with_streaming_response.create(
    model="mistralai/voxtral-mini-tts-2603",
    voice="fr_marie_neutral",
    input="Hello and welcome.",
) as response:
    print("Credits:", response.headers.get("x-moon-credits"))
    response.stream_to_file("hello.mp3")
JavaScript
import fs from 'node:fs';
import OpenAI from 'openai';

const client = new OpenAI({ baseURL: 'https://api.realmoon.ai/v1', apiKey: process.env.MOONAI_API_KEY });

const speech = await client.audio.speech.create({
  model: 'mistralai/voxtral-mini-tts-2603',
  voice: 'fr_marie_neutral',
  input: 'Hello and welcome.',
});
fs.writeFileSync('hello.mp3', Buffer.from(await speech.arrayBuffer()));

ResponseLink to the Response section

The response body is the audio file:

response_formatContent-TypeContent
mp3audio/mpegMP3
wavaudio/wavWAV, 16-bit, 24 kHz, mono
pcmaudio/pcmRaw PCM, 16-bit, 24 kHz, mono
HeaderValue
X-Moon-CreditsCredits charged for the request.
X-Moon-Request-IdThe request ID, for /v1/generation.
X-Moon-Prompt-Storagenone.
X-Moon-Blurnot_applied.

Speech modelsLink to the Speech models section

List as of November 5, 2026; the current list, with prices, comes from GET /v1/models?type=speech.

ModelDefault voiceFormats
mistralai/voxtral-mini-tts-2603fr_marie_neutralmp3
mistralai/voxtral-mini-tts-3-0nonemp3
microsoft/mai-voice-2.1-flashfr-FR-Soleil:MAI-Voice-2.1-Flashmp3
microsoft/mai-voice-2.1nonemp3
elevenlabs/eleven-flash-v2.5, eleven-multilingual-v2, eleven-v3nonemp3
fish-audio/s2.1-pro, deepgram/aura-2, qwen/qwen-audio-3.0-tts-flash, hexgrad/kokoro-82mnonemp3
google/gemini-3.8-flash-lite-tts, google/gemini-3.8-flash-ttsSulafatmp3, wav, pcm

CostsLink to the Costs section

Most voices are billed per character of text read (billing: per_character). Gemini voices are billed on the text sent and on the length of the audio actually produced. The request holds the price of the text before the call; a request that fails or is cut off by our timeout costs nothing.

ErrorsLink to the Errors section

HTTPcodeMeaning
400missing_required_parametermodel or input is missing.
400unknown_parameterUnknown parameter.
400unsupported_valueA response_format the model does not offer.
400unsupported_parameterspeed other than 1, instructions on a non-Gemini voice, or a voice, language or format the model rejects (with a hint).
400string_above_max_lengthText longer than 4,096 characters.
400nullMalformed voice, instructions longer than 500 characters, invalid JSON body.
404model_not_foundUnknown model, or one that does not serve this endpoint.
413request_too_largeBody larger than 256 KB.
429too_many_concurrentAlready 8 speech requests in flight for this workspace.
429upstream_rate_limitedThe model is overloaded: retry after Retry-After (10 seconds).
502, 504upstream_error, upstream_timeoutThe model failed, produced no audio, or did not respond in time.

Transcribe a recordingLink to the Transcribe a recording section

HTTP
POST https://api.realmoon.ai/v1/audio/transcriptions
  • Authentication: an sk-moon-… key with the inference scope.
  • Body: multipart/form-data only, with the Content-Length header. The file goes in the file field.
  • Response: the transcription, as JSON or plain text.

ParametersLink to the Parameters section

FieldTypeRequiredDescription
filefileyesThe recording: wav, mp3, flac, m4a (or mp4), ogg, webm or aac. 25 MB and 20 minutes at most.
modelstringyesA transcription model from GET /v1/models?type=transcription.
languagestringnoISO 639-1 language code (fr, en…). Improves the transcription.
promptstringnoContext or expected vocabulary (proper names, acronyms), 1,000 characters at most.
response_formatstringnojson (default), text or verbose_json.
temperature, timestamp_granularities[]noAccepted, with no effect.

Any other field is rejected with 400 unknown_parameter. A recording longer than 20 minutes is rejected (400 audio_too_long): split it into pieces. For a compressed file, the duration counted is at least what its size implies.

ExampleLink to the Example section

cURL
curl https://api.realmoon.ai/v1/audio/transcriptions \
  -H "Authorization: Bearer $MOONAI_API_KEY" \
  -F model=mistralai/voxtral-mini-transcribe \
  -F language=en \
  -F file=@meeting.m4a
Python
with open("meeting.m4a", "rb") as audio:
    transcript = client.audio.transcriptions.create(
        model="mistralai/voxtral-mini-transcribe",
        file=audio,
        language="en",
    )
print(transcript.text)
JavaScript
const transcript = await client.audio.transcriptions.create({
  model: 'mistralai/voxtral-mini-transcribe',
  file: fs.createReadStream('meeting.m4a'),
  language: 'en',
});
console.log(transcript.text);

ResponseLink to the Response section

response_format: json
{
  "text": "Hi everyone, we will start with the budget.",
  "usage": { "type": "duration", "seconds": 312.4, "credits": 0 }
}

The credits value is made up.

FieldTypeDescription
textstringThe transcribed text.
usage.typestringAlways duration.
usage.secondsnumberThe audio duration counted, in seconds.
usage.creditsintegerCredits charged.
taskstringWith verbose_json: transcribe.
languagestring or nullWith verbose_json: the detected or requested language.
durationnumber or nullWith verbose_json: the duration in seconds.

With response_format: "text", the response is the text alone, as text/plain. In every case, the X-Moon-Credits header gives the credits charged, and X-Moon-Request-Id the request ID.

Transcription modelsLink to the Transcription models section

List as of November 5, 2026; the current list, with prices per minute, comes from GET /v1/models?type=transcription.

  • mistralai/voxtral-mini-transcribe, mistralai/voxtral-mini-transcribe-3-0, mistralai/voxtral-small-transcribe-3-0
  • openai/whisper-large-v3-turbo, openai/whisper-large-v3, openai/gpt-4o-mini-transcribe, openai/gpt-4o-transcribe
  • elevenlabs/scribe-v2, deepgram/nova-3, assemblyai/universal-3-6-pro
  • nvidia/parakeet-tdt-0.6b-v3, qwen/qwen3-asr-1.7b

CostsLink to the Costs section

Transcription is billed at the actual cost reported by the provider, based on the audio duration (or, failing that, the list price). Before the call, the request holds at least the price of one minute, with a margin. A transcription that fails costs nothing.

ErrorsLink to the Errors section

HTTPcodeMeaning
400invalid_content_typeRequest sent as something other than multipart/form-data.
400missing_required_parametermodel or file is missing.
400unknown_parameterUnknown field.
400unsupported_valueUnknown response_format.
400unsupported_formatAudio format not recognized.
400audio_too_longRecording longer than 20 minutes.
400unsupported_parameterA language or format the model rejects (with a hint).
400nullMalformed language, prompt longer than 1,000 characters, empty file, unexpected file field.
404model_not_foundUnknown model, or one that does not serve this endpoint.
411length_requiredUpload without a Content-Length header.
413file_too_large, request_too_largeFile larger than 25 MB, or body too large.
429too_many_concurrentAlready 4 transcriptions in flight for this workspace.
429upstream_rate_limitedThe model is overloaded: retry after Retry-After (10 seconds).
502, 504upstream_error, upstream_timeoutThe model failed or did not respond in time.

Key, balance and spend cap errors, common to both endpoints, are in Errors.

LimitsLink to the Limits section

LimitSpeechTranscription
Size4,096 characters, 256 KB body25 MB file, 20 minutes of audio
Requests in flight per workspace84
Wait for the model’s response85 seconds at most85 seconds at most

See alsoLink to the See also section

  • Models: the default_voice, response_formats and max_file_mb fields.
  • Privacy: what Moon AI keeps from audio requests.

Moon AI

Moon AI in action

0:00

Explore

Screenshots of chat.realmoon.ai taken on October 29, 2026, with fictional data.

Moon AI

Your preferences

Visits counted without cookies.

Our server counts visits without cookies or trackers. Your theme and your answer about ad measurement are remembered on this device.

Ad measurement

With your consent, our ad networks’ trackers (Google) measure our ads, from the visit to the sign-up and then to the first subscription and its amount, and may show you our ads. Your answer is valid for 13 months; you can change it here at any time.

No answer saved on this device.

After you decline, no tag is loaded anymore and the site deletes the cookies they had set on realmoon.ai. Those on the ad networks’ own domains are managed with them or in your browser.

The Moon AI app has its own privacy settings.