Skip to content

Limits and quotas

Limit Value When it is exceeded
Text per request in mp3, wav, pcm 4,096 billable characters 400 input_too_long
Text per request in aac, opus, flac One chunk, about 900 billable characters 400 input_too_long_for_format
Chunk size 900 billable characters, cut at sentence ends Longer text is spoken in several chunks and joined
Request body 1 MB 413 request_too_large
speed 0.7 to 1.3 400 invalid_speed
Requests per minute, per API key 60 unless you set another, from 1 to 600 429 rate_limited with Retry-After
Requests in progress at once 8 per account, across all your keys 429 too_many_concurrent_requests
Monthly spending cap Optional, per key 402 key_spend_cap_reached

The per-key and per-account limits are the API’s own, shared with chat, images and video: see Rate limits and quotas for how they count and how to retry. Listing voices and models is free: it never spends from the wallet.

Limits and prices count billable characters: each character counts 1, spaces, punctuation and line breaks included, and each Chinese, Japanese or Korean character counts 3, because it speaks about three times as much audio. So 4,096 billable characters is 4,096 characters of English, or about 1,365 of Japanese. Each response says how many it counted in x-aderra-characters.

Voices are generated by a voice service that all Aderra customers share. Under heavy load it can refuse a request with 429 provider_busy. Nothing is charged. Wait a moment and retry, with a growing delay between attempts.

The OpenAI SDKs already retry 429 with backoff (2 retries by default). For batch jobs, allow more:

client = OpenAI(base_url="https://api.aderra.ai/v1",
api_key=os.environ["ADERRA_API_KEY"], max_retries=5)
const client = new OpenAI({
baseURL: 'https://api.aderra.ai/v1',
apiKey: process.env.ADERRA_API_KEY,
maxRetries: 5,
});

If you send many requests at once, keep fewer than 8 in progress per account, or the extra ones get 429 too_many_concurrent_requests.

Split the text at sentence ends into pieces of at most 4,096 billable characters, speak each piece, and join the audio. MP3 files join by putting their bytes one after another; this helper also drops the tag at the start of every file but the first, as Aderra does when it joins chunks:

speak_long.py
import os, re
from openai import OpenAI
client = OpenAI(base_url="https://api.aderra.ai/v1",
api_key=os.environ["ADERRA_API_KEY"], max_retries=5)
LIMIT = 4096
CJK = re.compile("[぀-ヿ㐀-䶿一-鿿가-힯豈-﫿ヲ-゚]")
def billable(text):
"""Characters as Aderra counts them: Chinese, Japanese and Korean count 3."""
return sum(3 if CJK.match(ch) else 1 for ch in text)
def split_text(text, limit=LIMIT):
"""Pieces of at most `limit` billable characters, cut after sentence ends."""
pieces, current = [], ""
for sentence in re.split(r"(?<=[.!?。!?\n])", text):
if billable(current + sentence) > limit:
pieces.append(current)
current = ""
while billable(sentence) > limit: # one sentence over the limit (rare)
end, n = 0, 0
while n + billable(sentence[end]) <= limit:
n += billable(sentence[end])
end += 1
space = sentence.rfind(" ", 0, end)
end = space + 1 if space > 0 else end
pieces.append(sentence[:end])
sentence = sentence[end:]
current += sentence
pieces.append(current)
return [p.strip() for p in pieces if p.strip()]
def without_id3(mp3):
"""Drops a leading ID3 tag, so the joined file has only the first one."""
if len(mp3) < 10 or mp3[:3] != b"ID3":
return mp3
size = (mp3[6] & 127) << 21 | (mp3[7] & 127) << 14 | (mp3[8] & 127) << 7 | mp3[9] & 127
return mp3[10 + size + (10 if mp3[5] & 16 else 0):]
def speak_long(text, voice, path):
with open(path, "wb") as out:
for i, piece in enumerate(split_text(text)):
audio = client.audio.speech.create(
model="aderra-voice-1", voice=voice, input=piece)
mp3 = audio.read()
out.write(mp3 if i == 0 else without_id3(mp3))
# speak_long(open("chapter.txt").read(), "Daniel", "chapter.mp3")
  • Each piece is a separate request, billed for its own characters: splitting does not change the total price.
  • Each piece is spoken on its own, so the intonation starts afresh at every join. Cutting at sentence ends keeps the joins natural; cutting at paragraph ends is better still, if your text has them.
  • For exact joins in any tool, ask for pcm instead, join the bytes, and wrap them once in a WAV header (see Audio formats).