Text to Speech API Python Tutorial (2026): Audexum Quickstart Guide
Learn how to call a text-to-speech API in Python using the requests library. Full code examples for voice selection, WAV output, error handling, and pricing comparison.
Integrating text-to-speech into a Python project takes less than 20 lines of code. This guide walks through everything: authentication, choosing a voice, saving WAV output, handling errors, and picking the right plan for your usage.
All examples use the Audexum TTS API, which supports 43 voices across 33 languages and has a free tier with no credit card required.
Prerequisites
You only need the requests library. No SDK, no framework.
pip install requestsGet a free API key at audexum.com/signup. Keys follow the format sk_live_abc123xyz. The free plan gives you 10,000 characters per month with no card required.
First API Call
The endpoint accepts a JSON body with text, voice_id, and optionally language. It returns raw WAV audio.
import requests
API_KEY = "sk_live_abc123xyz"
API_URL = "https://audexum.com/api/v1/tts"
response = requests.post(
API_URL,
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json={
"text": "Hello, this is a test of the Audexum text-to-speech API.",
"voice_id": "en_us_female_01",
},
)
if response.status_code == 200:
with open("output.wav", "wb") as f:
f.write(response.content)
print("Saved output.wav")
else:
print(f"Error {response.status_code}: {response.text}")Run it and you get output.wav in the current directory. That is the complete working implementation.
Selecting a Voice
Audexum has 43 voices across American English, British English, Spanish, French, German, Japanese, Korean, Arabic, Hindi, Bulgarian, Italian, Portuguese, and more. List available voices with a GET request:
import requests
API_KEY = "sk_live_abc123xyz"
voices = requests.get(
"https://audexum.com/api/v1/voices",
headers={"Authorization": f"Bearer {API_KEY}"},
).json()
for voice in voices:
print(f"{voice['voice_id']:30s} {voice['language']:10s} {voice['gender']}")Example output:
en_us_female_01 en-US female
en_us_male_01 en-US male
en_gb_female_01 en-GB female
de_female_01 de female
ja_female_01 ja femalePass the voice_id string directly in your synthesis request.
Saving the WAV File
The response body is raw PCM WAV — no base64 decoding needed. Write it to disk with standard file I/O:
import requests
from pathlib import Path
def synthesize(text: str, voice_id: str, output_path: str, api_key: str) -> Path:
response = requests.post(
"https://audexum.com/api/v1/tts",
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
},
json={"text": text, "voice_id": voice_id},
)
response.raise_for_status()
path = Path(output_path)
path.write_bytes(response.content)
return path
# Usage
output = synthesize(
text="Welcome to our application.",
voice_id="en_us_female_01",
output_path="welcome.wav",
api_key="sk_live_abc123xyz",
)
print(f"Audio saved to {output} ({output.stat().st_size} bytes)")If you need MP3 instead of WAV, pass "format": "mp3" in the JSON body.
Error Handling
Handle rate limits, invalid voices, and authentication errors explicitly:
import requests
from requests.exceptions import RequestException
def safe_synthesize(text: str, voice_id: str, api_key: str) -> bytes | None:
try:
response = requests.post(
"https://audexum.com/api/v1/tts",
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
},
json={"text": text, "voice_id": voice_id},
timeout=30,
)
if response.status_code == 401:
raise ValueError("Invalid API key. Check your sk_live_ token.")
if response.status_code == 402:
raise RuntimeError("Character quota exceeded. Upgrade your plan or wait for reset.")
if response.status_code == 422:
raise ValueError(f"Invalid request: {response.json().get('detail')}")
response.raise_for_status()
return response.content
except RequestException as e:
print(f"Network error: {e}")
return NoneStatus Codes Reference
| Code | Meaning | Action |
|---|---|---|
| 200 | Success | Write response body to file |
| 401 | Bad API key | Check the Authorization header |
| 402 | Quota exceeded | Upgrade plan or wait for monthly reset |
| 422 | Bad request body | Check voice_id and text fields |
| 429 | Rate limited | Retry with exponential backoff |
| 500 | Server error | Retry once, then contact support |
Batch Processing
For batches of strings, stay under the rate limit with a small delay between requests:
import time
import requests
from pathlib import Path
def batch_synthesize(items: list[dict], api_key: str, delay: float = 0.2):
"""
items: [{"text": "...", "voice_id": "...", "output": "file.wav"}, ...]
"""
results = []
for item in items:
response = requests.post(
"https://audexum.com/api/v1/tts",
headers={"Authorization": f"Bearer {api_key}"},
json={"text": item["text"], "voice_id": item["voice_id"]},
)
if response.ok:
Path(item["output"]).write_bytes(response.content)
results.append({"file": item["output"], "status": "ok"})
else:
results.append({"file": item["output"], "status": response.status_code})
time.sleep(delay)
return resultsPricing Comparison
Before committing to a plan, here is how the major TTS APIs compare on price per character:
| Provider | Free Tier | Paid Entry | Cost per 1M chars | Card Required for Free |
|---|---|---|---|---|
| Audexum | 10K chars/mo | €4 / 100K | ~€8 (PAYG) | No |
| ElevenLabs | 10K chars/mo | ~$5 / 30K | ~$11 | Yes (some plans) |
| OpenAI TTS | None | Pay-as-you-go | ~$15 | Yes |
| Murf.ai | Limited (watermarked) | ~$19/mo | Varies | Yes |
| Google Cloud TTS | 1M chars/mo (WaveNet 0) | Pay-as-you-go | $16 (WaveNet) | Yes |
Audexum is several times cheaper than ElevenLabs and roughly 2× cheaper than OpenAI TTS at scale. The PAYG option at €8/1M chars is useful for projects with unpredictable volume.
Plan Summary
| Plan | Characters/mo | Price | Best For |
|---|---|---|---|
| Free | 10,000 | €0 | Prototypes, testing |
| Starter | 100,000 | €4 | Small apps, bots |
| Pro | 500,000 | €12 | Production apps |
| Scale | 2,000,000 | €30 | High-volume pipelines |
| PAYG | Unlimited | €8/1M | Bursty or unpredictable load |
Next Steps
The full Python implementation fits in under 30 lines. The free tier is enough to build and test a complete integration before you spend anything.
Get your API key at audexum.com/signup and check the API reference for the full list of parameters including speed, pitch, and output format controls.
- Related: Cheapest text-to-speech API in 2026
- Related: ElevenLabs alternative with a free tier
- Related: TTS API for Discord bots
By Petar, founder of Audexum. Running a bootstrapped TTS SaaS gives you strong opinions about API design.