https://api.allmodels.io/oai
OpenAI-compatible
Already using the OpenAI SDK? Set its base URL to AllModels and keep calling audio.transcriptions.create or the realtime client, now with an AllModels model ID.
Transcribe with STT models from multiple providers through AllModels. Stream audio over WebSocket, use an OpenAI- or ElevenLabs-compatible SDK, and switch models without rebuilding your transcription pipeline.
AllModels is an independent service and is not affiliated with, endorsed by, or sponsored by the providers whose models it routes to.
A unified speech-to-text (STT) API is a single integration that can transcribe audio with models from many different providers. Instead of writing one client for Deepgram, another for AssemblyAI, another for Soniox and another for OpenAI, your application talks to one endpoint with one API key. The model you choose decides which provider transcribes the audio. AllModels is a unified STT API of this kind: you send a model ID such as deepgram/nova-3, assemblyai/universal-3-5-pro-realtime or soniox/stt-rt-v5, and AllModels routes the audio to that provider and returns the transcript.
Every model in the AllModels STT catalogue has a provider/model ID. You authenticate once with an AllModels API key, which replaces the separate keys and billing accounts you would otherwise keep with each provider. AllModels then offers three ways to call the same models:
wss://api.allmodels.io/v1/stt. You send raw audio frames as they are captured and receive stt.transcript.partial and stt.transcript.final events in one normalized format, whichever provider is behind the model.https://api.allmodels.io/oai. Point the official OpenAI SDK at this base URL and keep calling audio.transcriptions.create for files, or its realtime client for live audio.https://api.allmodels.io/el. Point the official ElevenLabs SDK at this base URL and keep calling its speech-to-text methods, including realtime transcription.All three reach the same catalogue. If your codebase already uses the OpenAI or ElevenLabs SDK, you can move to AllModels by changing the base URL and API key.
For microphones, calls and voice agents, stream audio over a WebSocket and read partial transcripts while the speaker is still talking. When the complete recording already exists, upload it in one HTTP request and get the full transcript back. To use a different STT model, change the model ID; your API key, endpoint and client code stay the same.
Choose a client, a mode and a language. Highlighted lines are the AllModels base URL and the model values you change to try another model.
Connect to wss://api.allmodels.io/v1/stt, send 16 kHz PCM audio as binary frames and read partial and final transcripts. STT docs.
import { readFile } from "node:fs/promises";
import WebSocket from "ws";
const url = new URL("wss://api.allmodels.io/v1/stt");
url.searchParams.set("model", "deepgram/nova-3");
url.searchParams.set("audio_format", "pcm_16000");
url.searchParams.set("language", "en");
url.searchParams.set("commit_strategy", "manual");
const ws = new WebSocket(url, {
headers: { Authorization: `Bearer ${process.env.ALLMODELS_API_KEY}` }
});
ws.on("message", (data) => {
const event = JSON.parse(data.toString());
if (event.type === "stt.transcript.partial") console.log("partial:", event.text);
if (event.type === "stt.transcript.final") {
console.log("final:", event.text);
ws.send(JSON.stringify({ type: "stt.session.close" }));
}
});
ws.on("open", async () => {
const audio = await readFile("speech-16khz.pcm");
for (let offset = 0; offset < audio.length; offset += 3200) {
ws.send(audio.subarray(offset, offset + 3200));
}
ws.send(JSON.stringify({ type: "stt.audio.commit" }));
});Connect to wss://api.allmodels.io/v1/stt, send 16 kHz PCM audio as binary frames and read partial and final transcripts. STT docs.
import asyncio
import json
import os
from pathlib import Path
from urllib.parse import urlencode
import websockets
async def main():
query = urlencode({
"model": "deepgram/nova-3",
"audio_format": "pcm_16000",
"language": "en",
"commit_strategy": "manual",
})
headers = {"Authorization": f"Bearer {os.environ['ALLMODELS_API_KEY']}"}
async with websockets.connect(
f"wss://api.allmodels.io/v1/stt?{query}", additional_headers=headers
) as ws:
audio = Path("speech-16khz.pcm").read_bytes()
for offset in range(0, len(audio), 3200):
await ws.send(audio[offset:offset + 3200])
await ws.send(json.dumps({"type": "stt.audio.commit"}))
async for message in ws:
event = json.loads(message)
if event["type"] == "stt.transcript.partial":
print("partial:", event["text"])
elif event["type"] == "stt.transcript.final":
print("final:", event["text"])
break
asyncio.run(main())Already have the recording? POST it to https://api.allmodels.io/oai/audio/transcriptions and read the transcript. STT docs.
import { readFile } from "node:fs/promises";
const form = new FormData();
form.set("model", "deepgram/nova-3");
form.set("language", "en");
form.set("file", new Blob([await readFile("call.wav")], { type: "audio/wav" }), "call.wav");
const response = await fetch("https://api.allmodels.io/oai/audio/transcriptions", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.ALLMODELS_API_KEY}` },
body: form
});
if (!response.ok) throw new Error(await response.text());
const transcript = await response.json();
console.log(transcript.text);Already have the recording? POST it to https://api.allmodels.io/oai/audio/transcriptions and read the transcript. STT docs.
import os
import requests
with open("call.wav", "rb") as audio:
response = requests.post(
"https://api.allmodels.io/oai/audio/transcriptions",
headers={"Authorization": f"Bearer {os.environ['ALLMODELS_API_KEY']}"},
data={"model": "deepgram/nova-3", "language": "en"},
files={"file": ("call.wav", audio, "audio/wav")},
timeout=60,
)
response.raise_for_status()
print(response.json()["text"])Set the OpenAI SDK base URL to https://api.allmodels.io/oai, open a realtime transcription session and send 24 kHz PCM audio. OpenAI realtime docs.
import { once } from "node:events";
import { readFile } from "node:fs/promises";
import OpenAI from "openai";
import { OpenAIRealtimeWebSocket } from "openai/realtime/websocket";
const client = new OpenAI({
apiKey: process.env.ALLMODELS_API_KEY,
baseURL: "https://api.allmodels.io/oai"
});
const realtime = await OpenAIRealtimeWebSocket.create(client, {
model: "openai/gpt-realtime-whisper"
});
if (realtime.socket.readyState !== 1) await once(realtime.socket, "open");
realtime.on("conversation.item.input_audio_transcription.delta", ({ delta }) => {
process.stdout.write(delta);
});
realtime.on("conversation.item.input_audio_transcription.completed", ({ transcript }) => {
console.log("\nfinal:", transcript);
realtime.close();
});
realtime.send({
type: "session.update",
session: {
type: "transcription",
audio: {
input: {
format: { type: "audio/pcm", rate: 24000 },
transcription: { model: "openai/gpt-realtime-whisper", language: "en" },
turn_detection: null
}
}
}
});
const audio = await readFile("speech-24khz.pcm");
for (let offset = 0; offset < audio.length; offset += 4800) {
realtime.send({
type: "input_audio_buffer.append",
audio: audio.subarray(offset, offset + 4800).toString("base64")
});
}
realtime.send({ type: "input_audio_buffer.commit" });Set the OpenAI SDK base URL to https://api.allmodels.io/oai, open a realtime transcription session and send 24 kHz PCM audio. OpenAI realtime docs.
import asyncio
import base64
import os
from pathlib import Path
from openai import AsyncOpenAI
async def main():
client = AsyncOpenAI(
api_key=os.environ["ALLMODELS_API_KEY"],
base_url="https://api.allmodels.io/oai",
)
async with client.realtime.connect(
model="openai/gpt-realtime-whisper",
extra_query={"intent": "transcription"},
) as connection:
await connection.session.update(session={
"type": "transcription",
"audio": {
"input": {
"format": {"type": "audio/pcm", "rate": 24000},
"transcription": {"model": "openai/gpt-realtime-whisper", "language": "en"},
"turn_detection": None,
}
},
})
audio = Path("speech-24khz.pcm").read_bytes()
for offset in range(0, len(audio), 4800):
chunk = base64.b64encode(audio[offset:offset + 4800]).decode("ascii")
await connection.input_audio_buffer.append(audio=chunk)
await connection.input_audio_buffer.commit()
async for event in connection:
if event.type == "conversation.item.input_audio_transcription.delta":
print(event.delta, end="", flush=True)
elif event.type == "conversation.item.input_audio_transcription.completed":
print("\nfinal:", event.transcript)
break
asyncio.run(main())Set the OpenAI SDK base URL to https://api.allmodels.io/oai and transcribe a complete file with audio.transcriptions.create. OpenAI transcription docs.
import { createReadStream } from "node:fs";
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.ALLMODELS_API_KEY,
baseURL: "https://api.allmodels.io/oai"
});
const transcript = await client.audio.transcriptions.create({
file: createReadStream("call.wav"),
model: "deepgram/nova-3",
language: "en"
});
console.log(transcript.text);Set the OpenAI SDK base URL to https://api.allmodels.io/oai and transcribe a complete file with audio.transcriptions.create. OpenAI transcription docs.
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["ALLMODELS_API_KEY"],
base_url="https://api.allmodels.io/oai",
)
with open("call.wav", "rb") as audio:
transcript = client.audio.transcriptions.create(
file=audio,
model="deepgram/nova-3",
language="en",
)
print(transcript.text)Set the ElevenLabs SDK base URL to https://api.allmodels.io/el and stream 16 kHz PCM audio through its realtime speech-to-text client. ElevenLabs realtime docs.
import { readFile } from "node:fs/promises";
import { AudioFormat, CommitStrategy, ElevenLabsClient, RealtimeEvents } from "@elevenlabs/elevenlabs-js";
const client = new ElevenLabsClient({
apiKey: process.env.ALLMODELS_API_KEY,
baseUrl: "https://api.allmodels.io/el"
});
const connection = await client.speechToText.realtime.connect({
modelId: "deepgram/nova-3",
audioFormat: AudioFormat.PCM_16000,
sampleRate: 16000,
languageCode: "en",
commitStrategy: CommitStrategy.MANUAL
});
connection.on(RealtimeEvents.PARTIAL_TRANSCRIPT, ({ text }) => console.log("partial:", text));
connection.on(RealtimeEvents.COMMITTED_TRANSCRIPT, ({ text }) => {
console.log("final:", text);
connection.close();
});
connection.on(RealtimeEvents.SESSION_STARTED, async () => {
const audio = await readFile("speech-16khz.pcm");
for (let offset = 0; offset < audio.length; offset += 3200) {
connection.send({ audioBase64: audio.subarray(offset, offset + 3200).toString("base64") });
}
connection.commit();
});Set the ElevenLabs SDK base URL to https://api.allmodels.io/el and stream 16 kHz PCM audio through its realtime speech-to-text client. ElevenLabs realtime docs.
import asyncio
import base64
import os
from pathlib import Path
from elevenlabs import AudioFormat, CommitStrategy, ElevenLabs, RealtimeEvents
async def main():
client = ElevenLabs(
api_key=os.environ["ALLMODELS_API_KEY"],
base_url="https://api.allmodels.io/el",
)
connection = await client.speech_to_text.realtime.connect({
"model_id": "deepgram/nova-3",
"audio_format": AudioFormat.PCM_16000,
"sample_rate": 16000,
"language_code": "en",
"commit_strategy": CommitStrategy.MANUAL,
})
finished = asyncio.Event()
def on_committed(event):
print("final:", event["text"])
finished.set()
connection.on(RealtimeEvents.PARTIAL_TRANSCRIPT, lambda event: print("partial:", event["text"]))
connection.on(RealtimeEvents.COMMITTED_TRANSCRIPT, on_committed)
audio = Path("speech-16khz.pcm").read_bytes()
for offset in range(0, len(audio), 3200):
chunk = base64.b64encode(audio[offset:offset + 3200]).decode("ascii")
await connection.send({"audio_base_64": chunk})
await connection.commit()
await finished.wait()
await connection.close()
asyncio.run(main())Set the ElevenLabs SDK base URL to https://api.allmodels.io/el and transcribe a complete file. The JavaScript SDK checks model IDs, so use an ID it recognizes such as scribe_v2. ElevenLabs transcription docs.
import { File } from "node:buffer";
import { readFile } from "node:fs/promises";
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
const client = new ElevenLabsClient({
apiKey: process.env.ALLMODELS_API_KEY,
baseUrl: "https://api.allmodels.io/el"
});
const bytes = await readFile("call.wav");
const transcript = await client.speechToText.convert({
file: new File([bytes], "call.wav", { type: "audio/wav" }),
modelId: "scribe_v2",
languageCode: "en"
});
console.log(transcript.text);Set the ElevenLabs SDK base URL to https://api.allmodels.io/el and transcribe a complete file with any AllModels STT model ID. ElevenLabs transcription docs.
import os
from elevenlabs.client import ElevenLabs
client = ElevenLabs(
api_key=os.environ["ALLMODELS_API_KEY"],
base_url="https://api.allmodels.io/el",
)
with open("call.wav", "rb") as audio:
transcript = client.speech_to_text.convert(
file=audio,
model_id="deepgram/nova-3",
language_code="en",
)
print(transcript.text)Compatible interfaces
https://api.allmodels.io/oai
Already using the OpenAI SDK? Set its base URL to AllModels and keep calling audio.transcriptions.create or the realtime client, now with an AllModels model ID.
https://api.allmodels.io/el
Already using the ElevenLabs SDK? Set its base URL to AllModels and keep using its convert and realtime speech-to-text methods, now with an AllModels model ID.
Read the ElevenLabs transcription docsQuick answers
A unified STT API gives applications one integration surface for multiple transcription models. With AllModels, the chosen model ID determines the provider while authentication and the core request flow stay the same.
Yes. The native interface streams over WebSocket at /v1/stt and returns partial and final transcripts as normalized stt.* events. The OpenAI and ElevenLabs SDKs stream through their own realtime clients. Streaming support varies by model.
Yes. Common settings use the standard fields, and any provider-specific setting, such as diarization settings, goes in provider_options and is passed directly to the provider.
Browse the STT catalogue to compare available models, streaming support, pricing and API examples before changing the model ID in your application.
provider/model ID.