API
From a key to audio.
The same API that powers the extension and the apps. Base URL https://api.brauo.com. Your account dashboard is at /account; your key is at /account/key.
Authentication
Every request needs Authorization: Bearer brauo_sk_…. Keys are created on signup, shown once, and rotatable at /account/key. The server stores only a hash, so a lost key means rotating. Without a valid key the API returns 401 with code invalid_key.
Credits
1 credit = 1,000 characters with a Brauo Original voice (1x). Extra voices bill at 20x - each voice’s credit_multiplier is in the catalog. Replaying audio the platform already cached does not re-charge. Free accounts get a small daily allowance; paid plans are sold as listening hours at /pricing. Out of credits returns 402 quota_exceeded.
POST /v1/speak
Read a passage aloud as mp3. Request body: { "text": "…", "voice": "brauo-elena-es" }. Text up to 2,000 characters per request. Response is audio/mpeg (chunked), with headers X-Brauo-Request-Id and X-Brauo-Cache: hit|miss.
curl -X POST https://api.brauo.com/v1/speak \
-H "Authorization: Bearer brauo_sk_…" \
-d '{ "text": "Any page, read aloud…",
"voice": "brauo-elena-es" }'POST /v1/speak/realtime
For voice agents: raw PCM16 mono little-endian at 24 kHz, streamed while it synthesizes - first bytes before the sentence is done. Request { "text", "voice" }, text up to 500 characters (one conversational turn). Response audio/pcm with X-Brauo-Sample-Rate: 24000 and X-Brauo-Request-Id. Never cached. Hanging up mid-stream is normal (barge-in): synthesis stops and the turn is billed as delivered.
curl -N -X POST https://api.brauo.com/v1/speak/realtime \
-H "Authorization: Bearer brauo_sk_…" \
-d '{ "text": "One short turn at a time.",
"voice": "brauo-elena-es" }' \
| ffplay -f s16le -ar 24000 -ch_layout mono -GET /v1/voices
Public, no auth. Response shape (excerpt):
{
"voices": [
{
"id": "brauo-elena-es",
"language": "es",
"tier": "…",
"credit_multiplier": 1,
"badge": "Brauo Original"
}
]
}Live catalog (grouped by language):
Loading catalog…
GET /v1/account
Your balance: { "plan", "credits", "credit_chars", "key_prefix", "usage": { "allowance_chars", "used_chars", "period_end" } }. The usage object is present on paid plans. Also available: GET /v1/usage/history - recent requests with request_id, chars, and outcome (success | partial | failed).
POST /v1/translate
Document translation, free within daily caps: free accounts 3 jobs/day up to 30k characters each; paid 20/day up to 600k. Request { "text", "target_language" } returns 202 with a job id; poll GET /v1/translate/{id} until done. Listening to the result is priced like any speak.
Errors
Envelope: { "error": { "code": "…", "message": "…" } }.
| code | status |
|---|---|
| invalid_request | 400 |
| invalid_key | 401 |
| quota_exceeded | 402 |
| paid_voice_required | 403 |
| voice_not_found | 404 |
| provider_unavailable | 502 |
Status
Health check: https://api.brauo.com/health.