Audio API

Speech synthesis, transcription, translation and music generation on one OpenAI-compatible surface. Pay per call in USDC — no per-vendor contracts.

Speech synthesis across the ElevenLabs, Google and OpenAI TTS models, Whisper transcription and translation, and music generation — on an OpenAI-compatible surface.

Coverage

Text-to-speech across the ElevenLabs range (flash-v2.5, turbo-v2.5, multilingual-v2, v3 and sound effects) plus Google and OpenAI TTS models, Whisper transcription and translation, and MiniMax music generation.

Speech is metered per input character and quoted per 1000. Music is metered per track. Generated files are served from CDN and stay available for a limited window, so download rather than hotlink.

7 endpoints

Text to speech

Natural speech from text, with voice aliases or a raw voice id. The model and voice are body fields, never path segments.

MethodEndpointDescription
POST/audio/speechSynthesise speech; returns JSON carrying a CDN audio URL
POST/audio/sound-effectsGenerate a sound effect from a description

Transcription & translation

Whisper, over multipart form data. Transcription keeps the source language; translation returns English.

MethodEndpointDescription
POST/audio/transcriptionsSpeech to text in the source language
POST/audio/translationsSpoken audio in any language to English text

Music generation

Full-length tracks from a prompt, with lyrics or instrumental. Asynchronous: submit, then poll.

MethodEndpointDescription
POST/audio/generationsStart a music generation job
GET/audio/generations/{id}Poll a job; the read reuses the original payment

Voice roster

The voices available to /audio/speech, so a caller can list rather than guess.

MethodEndpointDescription
GET/marketplace/audio/voicesAvailable voices with their ids and aliases

Pricing

Speech is billed per 1000 input characters and varies by model — the fast tiers cost roughly half the studio-grade ones. Music is billed per track. Polling a music job is free: the GET reuses the payment the POST made.

Quick start

cURL

# Text to speech — returns JSON with a CDN URL, not raw audio bytes
curl "https://api.jarvisclaw.ai/v1/audio/speech" \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"model":"elevenlabs/flash-v2.5","input":"Hello!","voice":"sarah"}'
# -> {"data":[{"url":"https://cdn.jarvisclaw.ai/.../audio.mp3","format":"mp3"}]}

# Then fetch the file
curl -o output.mp3 "https://cdn.jarvisclaw.ai/.../audio.mp3"

# Transcription is multipart, not JSON
curl "https://api.jarvisclaw.ai/v1/audio/transcriptions" \
  -H "Authorization: Bearer sk-your-api-key" \
  -F file="@recording.mp3" \
  -F model="whisper-1"

# List the voices instead of guessing an id
curl "https://api.jarvisclaw.ai/v1/marketplace/audio/voices" \
  -H "Authorization: Bearer sk-your-api-key"

Python

import requests

BASE = "https://api.jarvisclaw.ai/v1"
headers = {"Authorization": "Bearer sk-your-api-key"}

# Speech: the response carries a URL, so download it
resp = requests.post(
    f"{BASE}/audio/speech",
    headers=headers,
    json={
        "model": "elevenlabs/flash-v2.5",
        "input": "Hello, welcome to JarvisClaw!",
        "voice": "sarah",
    },
).json()

audio = requests.get(resp["data"][0]["url"])
open("output.mp3", "wb").write(audio.content)

# Transcription: multipart form data
with open("recording.mp3", "rb") as f:
    text = requests.post(
        f"{BASE}/audio/transcriptions",
        headers=headers,
        files={"file": f},
        data={"model": "whisper-1", "language": "en"},
    ).json()["text"]

# Music: submit, then poll. The poll is free.
job = requests.post(
    f"{BASE}/audio/generations",
    headers=headers,
    json={"model": "auto/music", "prompt": "calm piano jazz"},
).json()

status = requests.get(
    f"{BASE}/audio/generations/{job['id']}", headers=headers
).json()

JavaScript

const BASE = 'https://api.jarvisclaw.ai/v1'
const headers = {
  Authorization: 'Bearer sk-your-api-key',
  'Content-Type': 'application/json',
}

// Speech
const speech = await fetch(`${BASE}/audio/speech`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    model: 'elevenlabs/flash-v2.5',
    input: 'Hello, welcome to JarvisClaw!',
    voice: 'sarah',
  }),
}).then((r) => r.json())

const mp3 = await fetch(speech.data[0].url).then((r) => r.arrayBuffer())

// Transcription — multipart, so no JSON content-type here
const form = new FormData()
form.append('file', fileBlob, 'recording.mp3')
form.append('model', 'whisper-1')

const { text } = await fetch(`${BASE}/audio/transcriptions`, {
  method: 'POST',
  headers: { Authorization: 'Bearer sk-your-api-key' },
  body: form,
}).then((r) => r.json())

Use cases

FAQ

Does /audio/speech return the audio file itself?

No. It returns JSON containing a CDN URL plus the format and character count. Fetch that URL to get the bytes — and download it, because the file is retained only for a limited window.

Is this OpenAI-compatible?

Yes for the shapes that matter: /audio/speech, /audio/transcriptions and /audio/translations accept the same fields, so the OpenAI SDK works by changing base_url.

How do I choose a voice?

Pass a voice alias such as sarah or george, or a raw provider voice id. GET /v1/marketplace/audio/voices lists what is available rather than leaving you to guess.

How is speech billed?

Per input character, quoted per 1000. Cost therefore scales with the text you send, and the model tier sets the rate — the fast tiers cost roughly half the studio ones.

Does polling a music job cost extra?

No. The GET reuses the payment made by the POST, so you can poll until the track is ready without being charged again.

What are the upload limits for transcription?

Files up to 25MB, in mp3, mp4, mpeg, mpga, m4a, wav or webm. Split longer recordings into segments under that size.

Documentation