API Reference
The Mawj Speech to Text API converts Arabic speech to text. Upload an audio file and get back the transcript, with timestamps for each segment and word.
Base URL:
https://mawj-stt.prod.mawj.space
Requests use multipart/form-data. Responses are JSON.
Authentication
Send your API key in the Authorization header of every request:
Authorization: Bearer <api-key>
Rate limits
Each API key has these limits:
- Requests per minute
- Concurrent requests: requests being processed at the same time
- Audio minutes: the total minutes of audio the key can transcribe, if your key has this limit. Failed requests are not counted, and a file longer than the minutes left is rejected.
Successful responses include these headers:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Requests allowed per minute. |
| X-RateLimit-Remaining | Requests remaining before the limit is reached. |
If you exceed a limit, the API returns 429 Too Many Requests. For the
per-minute limit, the Retry-After header gives the number of seconds to wait.
A file longer than your key's total audio minutes returns 413 Content Too Large.
Errors
Errors return a JSON body with a detail message:
{ "detail": "Invalid or missing API key" }
| Status | Meaning |
|---|---|
| 400 Bad Request | The file could not be read as audio. |
| 401 Unauthorized | The API key is missing or invalid. |
| 413 Content Too Large | The file is longer than your key's total audio minutes. |
| 422 Unprocessable Entity | A field is missing or invalid, for example hotword_weight outside 1–100. |
| 429 Too Many Requests | A limit was reached. |
| 500 Internal Server Error | Transcription failed. You can retry the request. |
| 503 Service Unavailable | The service is starting. Retry shortly. |
Transcribe audio
Transcribes an audio file.
Request
| Field | Type | Description |
|---|---|---|
| filerequired | file | The audio file: WAV, FLAC, MP3, OGG, WebM, or M4A. |
| hotwordsoptional | string | Words to boost, as a comma-separated list (الرياض,جدة) or a JSON array (["الرياض", "جدة"]). See Hotwords. |
| hotword_weightoptional | number | How strongly hotwords are boosted, from 1 to 100. Default 10. |
| word_timestampsoptional | boolean | Include timestamps for each word. Default true. |
Examples
curl -X POST "https://mawj-stt.prod.mawj.space/api/v1/audio/transcribe" \
-H "Authorization: Bearer $MAWJ_API_KEY" \
-F "file=@audio.wav" \
-F "hotwords=موج"
import requests
with open("audio.wav", "rb") as audio:
response = requests.post(
"https://mawj-stt.prod.mawj.space/api/v1/audio/transcribe",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"file": audio},
data={"hotwords": "موج"},
)
response.raise_for_status()
print(response.json()["text"])
import { openAsBlob } from "node:fs";
const form = new FormData();
form.append("file", await openAsBlob("audio.wav"), "audio.wav");
form.append("hotwords", "موج");
const response = await fetch("https://mawj-stt.prod.mawj.space/api/v1/audio/transcribe", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.MAWJ_API_KEY}` },
body: form,
});
const result = await response.json();
console.log(result.text);
Hotwords
Hotwords help the model recognize specific words, such as names and places.
- Write hotwords in Arabic. Other entries are ignored.
- If a hotword is still missed, increase
hotword_weight. If it appears where it wasn't said, decrease it.
Response
{
"text": "مرحبا بكم في موج",
"filename": "audio.wav",
"processing_time_ms": 52.4,
"segments": [
{
"start": 0.28,
"end": 1.96,
"text": "مرحبا بكم في موج",
"confidence": 0.95,
"words": [
{ "word": "مرحبا", "start": 0.28, "end": 0.71, "conf": 0.97 },
{ "word": "بكم", "start": 0.74, "end": 1.02, "conf": 0.95 },
{ "word": "في", "start": 1.06, "end": 1.18, "conf": 0.93 },
{ "word": "موج", "start": 1.22, "end": 1.46, "conf": 0.94 }
]
}
],
"metadata": {
"model_name": "mawj_telephony_model",
"language": "ar",
"segments_count": 1,
"total_duration": 2.1,
"word_timestamps": true,
"speed_ratio": 40.1,
"device": "cuda",
"num_words": 4,
"queue_wait_ms": 0.0
}
}
| Field | Type | Description |
|---|---|---|
| text | string | The full transcript. |
| filename | string | Name of the uploaded file. |
| processing_time_ms | number | Time the server spent transcribing, in milliseconds. |
| segments | array | The transcript split into segments. See below. |
| metadata | object | Details about the request. See below. |
Segments
| Field | Type | Description |
|---|---|---|
| start | number | Start time, in seconds. |
| end | number | End time, in seconds. Can be up to 0.5 seconds after the last word. |
| text | string | Text of the segment. |
| confidence | number | Confidence, from 0 to 1. |
| words | array | null | Each word with its text (word), start and end times, and confidence (conf). null when word_timestamps is false. |
Metadata
| Field | Type | Description |
|---|---|---|
| model_name | string | The model used: mawj_telephony_model. |
| language | string | Always ar. |
| total_duration | number | Audio length, in seconds. |
| speed_ratio | number | Seconds of audio processed per second. |
| segments_count | integer | Number of segments. |
| num_words | integer | Number of words. |
| word_timestamps | boolean | Whether word timestamps were requested. |
| device | string | cuda (GPU) or cpu. |
| queue_wait_ms | number | Time spent waiting before processing started, in milliseconds. |
Health check
Returns the service status. No API key is needed.
{
"status": "healthy",
"model": "mawj_telephony_model",
"auth_required": true
}