- ›
/audio— speech to text, text to speech, and native audio conversations behind one Naïve key - ›
Automatic routing— send `auto` and Naïve ranks every eligible model, with fallbacks when a provider fails - ›
Speech to speech is not transcribe-then-speak— the model hears the audio itself, including tone and hesitation - ›
Billed in credits— by audio duration, input characters, or both, at the exact upstream cost - ›
Route traces on every call— see which candidates were considered, filtered, and attempted - ›
Opt-in by design— audio egresses voice to a third-party subprocessor, so a workspace must enable it deliberately
Today we're launching /audio — speech to text, text to speech, and native audio conversations behind a single Naïve key. Automatic routing across a managed catalog of speech models, fallbacks when a provider fails, exact-cost billing in credits, and a route trace on every call so you can see exactly what happened. The same key that sends email, issues cards, and reaches 300+ language models now hears and speaks.
The problem: speech is three integrations, not one
Agents that touch the real world end up needing audio. A support agent transcribes calls. A voice agent answers them. A content agent narrates. And each of those is a separate vendor relationship:
- Different providers win at different things. The best transcription model for English meetings isn't the best one for Portuguese phone audio, and neither is the best voice for dramatic narration. Picking one vendor means being wrong most of the time.
- They fail, and failure is per-provider. Speech APIs rate-limit, reject formats, and go down. Every one of those is a bespoke retry path you write yourself.
- Speech-to-speech is not a pipeline. Stitching transcription into an LLM into synthesis loses everything that made the audio worth listening to — tone, hesitation, urgency. And it's slow.
For a platform where an agent already has a phone number, an inbox, and a card behind one key, making it hold three more speech accounts is backwards. Until now.
How /audio works
One endpoint per modality, and a model selection you don't have to make. Send auto and Naïve ranks every eligible model for the request, applies your constraints, and falls through to the next candidate if one fails.
import { readFile } from "node:fs/promises";
const bytes = await readFile("meeting.wav");
const t = await naive.audio.transcribeFile(bytes, "wav", {
language: "en", // skips detection — faster and more accurate
diarize: true, // speaker labels, normalized to spk_N
timestamps: "word",
});
console.log(t.text);
console.log(t.route.mode, t.route.candidates); // "auto", 33
console.log(t.credits_used);Pass language whenever you know it. On an automatic route it skips language detection entirely — lower latency on every request, and the model transcribes against the language you named instead of guessing.
Routing you can inspect
Every response carries a route object. This isn't decoration — it's the audit trail for a decision Naïve made on your behalf:
"route": {
"mode": "auto",
"reason": "Route alias stt/auto ranked by balanced",
"candidates": 33,
"attempts": [
{ "provider": "groq", "status": "skipped", "error_code": "provider_unavailable" },
{ "provider": "deepinfra", "status": "skipped", "error_code": "unsupported_media" },
{ "provider": "fal", "status": "success", "latency_ms": 1108 }
]
}Two providers failed; the third served the request. Your code never saw it. That's the whole value of a router — but you can still read exactly what happened, per request, after the fact.
Constrain it when you need to:
await naive.audio.transcribe({
input_audio: { data: base64, format: "wav" },
model: "stt/auto",
provider: {
only: ["deepgram", "groq"],
require_features: true, // don't silently degrade
max_price: { per_min: 0.01 },
region: ["us", "global"],
},
});Synthesis, steered by capability
For text to speech, you usually don't want to name a model — you want to name what matters. Send a feature and Naïve ranks eligible voices for it:
const { audio, request_id } = await naive.audio.speech({
model: "tts/auto",
feature: "Acting", // or Expressiveness, Long-form, Acoustic quality…
input: "Deliver this like the opening of a thriller.",
voice: "auto",
response_format: "mp3",
});
await writeFile("line.mp3", Buffer.from(audio));Omit feature entirely and it's inferred from your text, instructions, language, and length.
Speech to speech: the model actually listens
This is the one that isn't a pipeline. The model receives your audio directly — not a transcript of it — and answers in speech. It hears tone, hesitation, and emphasis, and you get both transcripts back alongside the reply audio.
const reply = await naive.audio.converse({
model: "s2s/auto",
voice: "auto",
input_audio: { data: base64Question, format: "wav", channels: 1 },
output_audio: { format: "wav" },
instructions: "Answer the speaker briefly.",
});
console.log(reply.input_transcript); // what it heard
console.log(reply.transcript); // what it said
await writeFile("answer.wav", Buffer.from(reply.audio.data, "base64"));Long recordings, queued
Anything long belongs on the async path. Queue it, get a request id, poll it:
naive audio transcribe podcast.wav --async
# → req_k7a2be (queued)
naive audio transcription req_k7a2be
# → succeeded, with the transcriptThe credit charge lands once, on the poll that first sees succeeded — polling again never double-charges.
Call it from the CLI or raw REST
naive audio transcribe call.mp3 --language en --diarize
naive audio speak "Your order shipped this morning." -o update.mp3
naive audio converse question.wav -o answer.wavcurl -X POST https://api.usenaive.ai/v1/audio/transcriptions \
-H "Authorization: Bearer $NAIVE_API_KEY" \
-F "model=auto" \
-F "language=en" \
-F "file=@meeting.wav"Opt-in, and pinned by default
/audio sends tenant voice to a third-party router that selects among many speech providers per request. That's a real subprocessor relationship, so we treat it like one:
- The primitive is opt-in. A fresh workspace has
audiodisabled. You enable it deliberately on an Account Kit — the same standard we hold/brainto. - Requests are region-pinned to US and global by default, so audio doesn't leave those regions unless you say so.
- Transcription sets a minimal retention policy by default, so nothing sits upstream longer than the request needs.
All three are defaults, not ceilings. Pass your own provider.region or retention and yours wins.
What you can build with /audio
Transcribe every support call, in any language — Point /audio at your recordings with diarize on and get speaker-labelled transcripts with word timings. Pair it with /phone to close the loop from call to record.
Give an agent a voice on the same balance — Synthesis is one call, steered by the capability you care about. No voice vendor account, no separate invoice.
Build voice agents that hear tone — Speech to speech means the model responds to how something was said, not just what. Ask for Emotion Alignment and it notices when a "yes, fine" isn't fine.
Meter speech spend per customer — In a multi-tenant build, scope /audio to a tenant user and read the exact per-request cost to bill inference downstream alongside /billing.
Compose with the rest of the stack — Transcribe with /audio, reason with /llm, cut with /clips — audio, text, and media generation all behind one key.
Get started
Drop this starter prompt into any coding agent to wire up Naïve:
Read https://usenaive.ai/skill.md and use it to set up Naïve in my project.
- Read the docs: usenaive.ai/docs/getting-started/audio
- CLI reference: usenaive.ai/docs/cli/audio
- SDK reference: usenaive.ai/docs/sdk/sub-clients/audio
- Quickstart: usenaive.ai/docs/getting-started/quickstart
- Join the community on Discord
What is /audio?+
How does automatic routing work?+
Is speech-to-speech just transcription plus synthesis?+
How is it billed?+
Which languages does it support?+
Where does my audio go?+
How do I get started with /audio?+
OpenAI-compatible chat completions across 300+ models with provider routing and fallbacks — streaming included, no per-provider keys, billed in Naïve credits at the exact upstream cost. Plus a drop-in OpenRouter proxy so your existing code just changes a base URL.
Clip long-form video into captioned, ready-to-post shorts in one call, and keep every generated or uploaded asset in a managed media library — the production layer for an autonomous content business.
Provision a real US phone number for any AI Employee — send and receive SMS — with carrier (10DLC) registration handled at provisioning. Inbound works immediately; outbound unlocks automatically on campaign approval.