Switch from OpenAI text to speech and Whisper
OpenAI is removing tts-1 and whisper-1 from its API. Point the OpenAI SDK at Paxa, and your model and voice names keep working.
Switching from OpenAI? Change the base URL and the key, and your model and voice names keep working.
tts-1,tts-1-hd, andgpt-4o-mini-ttsleave OpenAI's API on January 6, 2027.whisper-1,gpt-4o-transcribe, andgpt-4o-mini-transcribeleave on February 26, 2027, along withgpt-4o-transcribe-diarize. Paxa does not take that name; speaker labels are served on POST /v1/stt.
The details are on OpenAI's deprecations page. For speech, OpenAI points to its Realtime API, which works differently from /v1/audio/speech.
The Paxa API serves POST /v1/audio/speech and POST /v1/audio/transcriptions in OpenAI's shape and accepts OpenAI's model and voice names. Where your code or tool lets you set a base URL, two settings switch it.
| Setting | Value |
|---|---|
| Base URL | https://api.paxalabs.com/v1 |
| API key | A Paxa key from the dashboard |
Model names, voice names, and request bodies stay as they are. A new account starts with 100 free credits.
Text to speech#
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.paxalabs.com/v1",
api_key=os.environ["PAXA_API_KEY"],
)
with client.audio.speech.with_streaming_response.create(
model="tts-1",
voice="alloy",
input="สวัสดีครับ ยินดีต้อนรับสู่ Paxa Labs",
) as response:
response.stream_to_file("speech.mp3")import { writeFile } from "node:fs/promises";
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.paxalabs.com/v1",
apiKey: process.env.PAXA_API_KEY,
});
const response = await client.audio.speech.create({
model: "tts-1",
voice: "alloy",
input: "สวัสดีครับ ยินดีต้อนรับสู่ Paxa Labs",
});
await writeFile("speech.mp3", Buffer.from(await response.arrayBuffer()));curl -X POST https://api.paxalabs.com/v1/audio/speech \
-H "Authorization: Bearer $PAXA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "tts-1",
"input": "สวัสดีครับ ยินดีต้อนรับสู่ Paxa Labs",
"voice": "alloy"
}' \
--output speech.mp3import { readFile, writeFile } from "node:fs/promises";
import { createOpenAI } from "@ai-sdk/openai";
import { generateSpeech, transcribe } from "ai";
const paxa = createOpenAI({
baseURL: "https://api.paxalabs.com/v1",
apiKey: process.env.PAXA_API_KEY,
});
const { audio } = await generateSpeech({
model: paxa.speech("tts-1"),
voice: "alloy",
text: "สวัสดีครับ ยินดีต้อนรับสู่ Paxa Labs",
});
await writeFile("speech.mp3", audio.uint8Array);
const { text } = await transcribe({
model: paxa.transcription("whisper-1"),
audio: await readFile("meeting.m4a"),
});Speech to text#
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.paxalabs.com/v1",
api_key=os.environ["PAXA_API_KEY"],
)
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=open("meeting.m4a", "rb"),
)
print(transcript.text)response_formatisjson(the default),verbose_json,text,srt, orvtt.languagepasses a hint, and without one the model detects the language.- A recording runs up to 60 minutes and 25 MiB.
- Paxa STT Lite is a Research preview.
Which voice speaks#
When a request names an OpenAI voice, one of our voices speaks it. Every one of them speaks English, Thai, and Mandarin, mixed sentences included. Each response names the voice that spoke in its x-voice-id header.
| You send | Paxa voice | Role |
|---|---|---|
| alloy | Foi Thong (foithong) | Narrator |
| ash | Khanom Krok (khanomkrok) | Lead voice |
| ballad | Oliang (oliang) | Late-night radio |
| cedar | Khao Tom (khaotom) | Family man |
| coral | Cookie (cookie) | Support agent |
| echo | Massaman (massaman) | Leading man |
| fable | Espresso (espresso) | Long-form reader |
| marin | Salim (salim) | Girl next door |
| nova | Nom Yen (nomyen) | Lead voice |
| onyx | Thong Ek (thongek) | News anchor |
| sage | Bai Toey (baitoey) | Mentor |
| shimmer | Tako (tako) | Friendly reader |
| verse | Latte (latte) | Brand films |
To choose a voice yourself, send its id instead, for example "khanomkrok". GET /v1/voices lists all 50, and the voice library plays them.
Model names map the same way. tts-1, tts-1-hd, gpt-4o-mini-tts, gpt-4o-mini-tts-2025-03-20, gpt-4o-mini-tts-2025-12-15 run on paxa-tts-flash-v2, and whisper-1, gpt-4o-transcribe, gpt-4o-mini-transcribe, gpt-4o-mini-transcribe-2025-03-20, gpt-4o-mini-transcribe-2025-12-15 run on paxa-stt-lite-v1-preview.
In tools you already use#
Most tools with an OpenAI speech option let you change the base URL. Menu names vary by version.
- In Open WebUI, open Admin Panel, Settings, Audio. Choose the OpenAI engine for text to speech and for speech to text, set the base URL to
https://api.paxalabs.com/v1, and paste your Paxa key. - In n8n, create an OpenAI credential for audio alone, with Base URL
https://api.paxalabs.com/v1and your Paxa key, and use it in the OpenAI node's audio actions. Keep your existing credential for chat, because Paxa serves speech and transcription only. - In Home Assistant's OpenAI TTS custom integration, choose the custom option, set the URL to
https://api.paxalabs.com/v1/audio/speech, and keep your model and voice. - In LibreChat, set the
urlof the speech and transcription settings inlibrechat.yamltohttps://api.paxalabs.com/v1/audio/speechandhttps://api.paxalabs.com/v1/audio/transcriptions. LibreChat posts to the URL as written. - In SillyTavern, choose the OpenAI Compatible TTS provider and set the endpoint to
https://api.paxalabs.com/v1/audio/speech.
The integration guides walk through Open WebUI, LibreChat, Home Assistant, and SillyTavern step by step, along with AnythingLLM, LiveKit Agents, and Strands Agents.
A tool that reads OPENAI_BASE_URL moves all of its OpenAI calls to Paxa, chat included, and Paxa does not serve chat. Set it only for a tool that uses OpenAI for audio alone.
What differs from OpenAI#
- The formats are mp3 (the default), opus, wav, pcm, mulaw, and alaw. pcm is 24 kHz 16-bit mono. aac and flac answer 400.
- Speed runs from 0.5 to 1.5, and a value outside that range answers 400.
instructionsis ignored. To steer the delivery, write direction tags into the text, such as[whispering] see you tomorrowor[cheerful] welcome back!.- Streaming is on by default, and
"stream": falsereturns a complete file. - Streaming sends raw audio bytes under an audio content type, also when a request sets
"stream_format": "sse". A client that parses events reads the content type first. - A request the schema refuses answers 400 validation with
path, the field at fault, andreason, a stable code for what is wrong with it. - An unknown model or voice answers 400 unknown_model or 400 unknown_voice.
- A speech request carries up to 5,000 characters.
- Speech costs 10 credits per 1,000 characters, and transcription 8.33 credits per minute. See pricing.
More than a drop-in#
- Every voice speaks English, Thai, and Mandarin, mixed sentences included.
- Direction tags steer the delivery and add sounds such as
[laughs]and[sighs], and<emph>marks a span. - The native API adds word timestamps and a live socket that takes text as it is written.
Questions#
Does alloy sound the same?#
No. Our voices answer to OpenAI's names, and the table above shows which voice speaks each one. Listen before you switch, or pick any voice by id.
What if my tool has no base URL setting?#
Then it needs a native Paxa integration. Tell us which tool.
Can I keep OpenAI for chat?#
Yes. Point only your audio calls at Paxa.
What happens with a name you do not map?#
An unknown voice or model answers 400 unknown_voice or unknown_model. Nothing switches silently.