# Abena AI API
African‑language **Text‑to‑Speech** (speech from text) and **Speech Recognition** (text from speech), over plain HTTP.
Use it from a website, a phone app, a server, or just your terminal — **no special library required**.
> 🟢 **Start free:** no account or API key is required. Speech Recognition includes 25 free transcriptions; other free API endpoints include up to 20 requests. Sign in for 50 free Speech Recognition transcriptions.
- 🌍 Live playground:
- 🎙️ Speech Recognition playground:
- 📖 Full docs:
---
## Base URL
```
https://abena.mobobi.com/playground/api/v1
```
> ℹ️ **First request to a voice may take ~10–15 seconds.** The first time a voice is used, its model is loaded and prepared on our server (offline). After that the same voice responds in about a second.
---
## Text‑to‑Speech
Send text + a voice, get audio back. The audio comes as a **Base64‑encoded WAV** inside JSON, which is easy to use from any language and from the browser.
**Endpoint**
```
POST /tts/synthesize/
```
**Request body (JSON)**
| Field | Required | Description |
|---------|----------|-------------|
| `text` | yes | Text to speak (up to 500 characters). |
| `voice` | yes | A voice ID, e.g. `akua_eng`, `abena_twi_high`, `kobby_gpe` — see [Voices](#tts-voices). |
| `speed` | no | `1.0` normal, `0.5` slowest, `2.0` fastest. Default `1.0`. |
**Response (JSON)**
```json
{
"status": "success",
"voice": "abena_twi_high",
"audio_base64": "UklGRiQ...",
"duration_seconds": 2.91,
"mime_type": "audio/wav",
"quality": "high"
}
```
`abena_twi_high` always uses the High voice. If the voice service is temporarily at capacity, retry after the interval returned by the API.
**Example (curl)** — saves `speech.wav`, no API key needed:
```bash
curl -s -X POST https://abena.mobobi.com/playground/api/v1/tts/synthesize/ \
-H "Content-Type: application/json" \
-d '{"text": "Akwaaba, wo ho te sen?", "voice": "abena_twi_high", "speed": 1.0}' \
| python3 -c "import sys,json,base64; open('speech.wav','wb').write(base64.b64decode(json.load(sys.stdin)['audio_base64'])); print('Saved speech.wav')"
```
> 🗣️ **Twi tip:** use `abena_twi_high` for the newer, more natural single-speaker Twi voice. Use `abena_twi_lite` when you want the lighter voice, which can sound clearer on some short phrases. For longer Twi text, write naturally and use commas to break long ideas into short phrases.
### TTS Voices
Fetch the live list any time: `GET /tts/voices.json`. Older short IDs and playground model IDs like `akua`, `en-ng-chioma`, `en-ng-chioma-whispering`, `swahili`, and `nigerian_pidgin_s` are still accepted as aliases, but new integrations should use the language-suffixed IDs below. The old Twi ID `abena_twi` has been replaced by explicit High and Lite options.
| Voice ID | Name | Language | Country | Gender |
|------------|----------|---------------------------|----------|--------|
| `abena_twi_high` | Abena High | Twi (Akan, newer natural voice) 🇬🇭 | Ghana | Female |
| `abena_twi_lite` | Abena Lite | Twi (Akan, lighter voice) 🇬🇭 | Ghana | Female |
| `kobby_gpe` | Kobby | Ghanaian Pidgin English 🇬🇭| Ghana | Male |
| `akua_eng` | Akua | English (Ghanaian accent) 🇬🇭| Ghana | Female |
| `kwabena_eng` | Kwabena | English (Ghanaian accent) 🇬🇭| Ghana | Male |
| `chioma_eng` | Chioma | English (Nigerian accent, energetic) | Nigeria | Female |
| `chioma_whispering_eng` | Chioma | English (Nigerian accent, whispering) | Nigeria | Female |
| `mawuli_ewe` | Mawuli | Ewe | Ghana | Male |
| `james_pcm` | James | Nigerian Pidgin English | Nigeria | Male |
| `amani_swh` | Amani | Swahili | Kenya | Female |
| `abubakar_hau` | Abubakar | Hausa | Nigeria | Male |
| `folami_yor` | Folami | Yoruba | Nigeria | Female |
---
## Speech Recognition
Send an audio file, get the text back. Upload the file as a form field named `audio_file` (`multipart/form-data`).
**Endpoint**
```
POST /asr/transcribe/
```
**Form fields**
| Field | Required | Description |
|------------------|----------|-------------|
| `audio_file` | yes | Your audio file, up to **25 MB**. Twi: 60 seconds. Ghanaian English/Pidgin: 120 seconds. |
| `language` | no | `twi-en` (recommended), `twi-only`, `en`, or `gpe`. Default `twi-en`. |
| `reference_text` | no | If you know the correct text, include it to also get accuracy/WER scores. |
Supported audio formats: WAV/PCM, MP3, M4A/AAC, FLAC, OGG, and other common formats. For predictable batch evaluations, use mono 16-bit PCM WAV at 16 kHz; files already in that format are used directly. Other valid files are normalized before transcription.
**Response (JSON)**
```json
{
"text": "Mepɛ sɛ mede sika kɔ ma Kwame",
"transcription": "Mepɛ sɛ mede sika kɔ ma Kwame",
"language": "twi-en",
"duration_seconds": 3.2,
"credits_remaining": 24,
"credit_limit": 25
}
```
**Example (curl)**
```bash
curl -X POST https://abena.mobobi.com/playground/api/v1/asr/transcribe/ \
-F "audio_file=@recording.wav" \
-F "language=twi-en"
```
### ASR Languages
Fetch the live list any time: `GET /asr/voices.json`
| Code | Language | Country |
|-------|-------------------------|---------|
| `twi-en` | Akan Twi + English (Recommended) 🇬🇭 | Ghana |
| `twi-only` | Akan Twi (No English) 🇬🇭 | Ghana |
| `en` | English (Ghanaian accent) 🇬🇭 | Ghana |
| `gpe` | Ghanaian Pidgin English 🇬🇭| Ghana |
Use `twi-en` for Twi, English, and Twi-English code-switching. Choose `twi-only` only when the entire recording is spoken in Twi; English words may be missed. A `twi-only` response includes a short reminder in the `notice` field.
---
## Errors & Limits
Errors return JSON with a helpful `message` (TTS) or `error` (ASR) field.
| Status | Meaning | What to do |
|-------------|--------------------|------------|
| `200` | Success | Use the result. |
| `400` | Bad request | Check fields (missing `text`, unknown `voice`, `speed` out of range). |
| `401` | Authentication failed | Check the API key, or omit it to use the no-sign-in allowance. |
| `402` | Credits used | [Sign in](https://abena.mobobi.com/playground/sdk/dashboard/) for more free ASR credits or to manage your API allowance. |
| `413` | Too large | Shorten text (500 chars) or use audio no larger than 25 MB. |
| `429` | Too many requests | Slow down and retry shortly. |
| `500` | Server issue | Retry shortly; contact support if it persists. |
| `503` | At capacity | Wait for the `Retry-After` interval, then retry the same request. |
---
## Examples
Runnable examples live in [`examples/`](examples/):
- [`examples/index.html`](examples/index.html) — a complete web page. Open it in any browser; no install, no key.
- [`examples/tts.py`](examples/tts.py) — Python text‑to‑speech.
- [`examples/asr.py`](examples/asr.py) — Python speech recognition.
- [`examples/tts.js`](examples/tts.js) — Node.js / browser text‑to‑speech.
## Use From Any Language
The API is plain HTTP + JSON, so any language that can make a web request can use it. The examples below work with the free tier and do not require an API key.
### JavaScript
```javascript
const res = await fetch(
"https://abena.mobobi.com/playground/api/v1/tts/synthesize/",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
text: "Hello!",
voice: "akua_eng",
speed: 1.0
})
}
);
const data = await res.json();
new Audio("data:audio/wav;base64," + data.audio_base64).play();
```
### Python Text-to-Speech
Uses Python's built-in HTTP client, so there is no extra package to install.
```python
import base64, json
from urllib.request import Request, urlopen
payload = json.dumps({
"text": "Akwaaba, wo ho te sen?",
"voice": "abena_twi_high",
"speed": 1.0
}).encode("utf-8")
req = Request(
"https://abena.mobobi.com/playground/api/v1/tts/synthesize/",
data=payload,
headers={"Content-Type": "application/json", "Accept": "application/json"},
method="POST",
)
with urlopen(req, timeout=120) as res:
data = json.loads(res.read().decode("utf-8"))
with open("speech.wav", "wb") as f:
f.write(base64.b64decode(data["audio_base64"]))
print("Saved speech.wav")
```
### Python Speech Recognition
```python
import json, mimetypes, uuid
from pathlib import Path
from urllib.request import Request, urlopen
audio_path = Path("recording.wav")
boundary = "----abena-" + uuid.uuid4().hex
audio_bytes = audio_path.read_bytes()
content_type = mimetypes.guess_type(audio_path.name)[0] or "application/octet-stream"
body = (
f"--{boundary}\r\n"
'Content-Disposition: form-data; name="language"\r\n\r\n'
"twi-en\r\n"
f"--{boundary}\r\n"
f'Content-Disposition: form-data; name="audio_file"; filename="{audio_path.name}"\r\n'
f"Content-Type: {content_type}\r\n\r\n"
).encode("utf-8") + audio_bytes + f"\r\n--{boundary}--\r\n".encode("utf-8")
req = Request(
"https://abena.mobobi.com/playground/api/v1/asr/transcribe/",
data=body,
headers={
"Content-Type": f"multipart/form-data; boundary={boundary}",
"Accept": "application/json",
},
method="POST",
)
with urlopen(req, timeout=120) as res:
data = json.loads(res.read().decode("utf-8"))
print(data["text"])
```
## API Keys (Optional)
You do not need an API key for the free tier examples above. Just send a request and it works.
When you are ready to build beyond the no-account allowance, create a free account from your [dashboard](https://abena.mobobi.com/playground/sdk/dashboard/) and send your key one of these ways:
```
Authorization: Bearer YOUR_API_KEY # recommended
X-API-Key: YOUR_API_KEY
?api_key=YOUR_API_KEY # query string, handy for quick tests
```
---
## License
[MIT](LICENSE)