The Hakim TTS family
Three tiers, one API. Pick a tier by setting model on POST /v1/audio/speech. Names are
Arabic adjectives that ladder up alongside the capability set:
- Hakim Saree' v1.3 (
hakim-fast-v1) · swift. Sub-120 ms streaming TTFB, 32 supported languages. The default for new code. Speed-tuned; no inline tags, no voice prompting. - Hakim Faseeh v2 (
hakim-v2) · eloquent. Premium quality, non-verbal tag support, 41 languages. Use when naturalness matters more than the lowest latency. - Hakim Mulhim v3 (
hakim-v3) · inspiring. Premium quality, tags plus voice generation from a free-form prompt, 41 languages. The full capability set; pair withvoice_prompton/v1/audio/speechor withPOST /v1/audio/voices/designto conjure a fresh voice from text.
Capability matrix
| Capability | Saree' | Faseeh | Mulhim |
|---|---|---|---|
| Streaming TTFB ≤ 120 ms | ✅ | · | · |
| Premium quality | · | ✅ | ✅ |
Non-verbal tags ([laugh], [breath], …) | · | ✅ | ✅ |
Voice prompt (voice_prompt field) | · | · | ✅ |
Voice design endpoint (/v1/audio/voices/design) | · | · | ✅ |
| Languages supported | 32 | 41 | 41 |
Pricing
Usage is billed per input character, in credits. The premium tiers use more credits per character than the default tier:
| Tier | Model | Credits per character |
|---|---|---|
| Saree' | hakim-fast-v1 | 1.0 |
| Faseeh | hakim-v2 | 1.5 |
| Mulhim | hakim-v3 | 2.0 |
Billing is computed on the text the model actually receives. Unsupported tags and prompts are
stripped first, so text that is ignored is never billed. The same rates apply on
POST /v1/audio/speech and on the realtime stream,
where you can also pick the tier per session or per utterance with model.
Picking a tier
A few common shapes:
- Live agent / IVR / voicebot · pick
hakim-fast-v1. The streaming TTFB budget matters more than expressive flourishes. - Podcasts, audiobooks, branded narration · pick
hakim-v2and use non-verbal tags (laughs, sighs, hesitations) to add realism. - Creative or marketing video where voice identity is the differentiator · pick
hakim-v3and either setvoice_prompton the speech call or design a voice from scratch and pin it to your library.
Graceful degradation
The API parser strips capabilities your tier doesn't advertise rather than rejecting the
request. A [laugh] tag inside input on hakim-fast-v1 plays clean · the bracketed token
is removed before synthesis, the audio is unchanged from "hello world" with the tag absent,
and the response carries x-hakim-warnings: tags_stripped_by_model_capability.
Same posture for an unsupported voice_prompt (dropped + flagged via
voice_prompt_dropped_by_model_capability). The exception is POST /v1/audio/voices/design,
which does reject with 422 · there's no graceful fallback when the prompt is the whole
request.
Sniff the x-hakim-warnings header to detect the strip:
curl -i https://api.tryhakim.ai/v1/audio/speech \
-H "Authorization: Bearer $HAKIM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "hakim-fast-v1",
"input": "Hello [laugh] world",
"voice": "layla-egyptian"
}' \
--output speech.mp3 \
| grep -i x-hakim-warnings
# x-hakim-warnings: tags_stripped_by_model_capability
Legacy id
hakim-flash-v1 is the pre-launch codename of the speed tier; the API still accepts it and
normalises every request body, audit log, and metric label to the canonical hakim-fast-v1.
New code should pick the canonical id; legacy integrations don't need to change.
Cookbook
A collection of common patterns. Each recipe names the tier it needs up front so you can scan and pick.
Recipe 1 · Pick the right tier (decision tree)
Three honest questions in order:
- Is your latency budget under 300 ms wall-clock? (voicebots, IVR, in-game characters, interactive agents) → Saree' v1.3. The streaming TTFB is the binding spec.
- Are you embedding non-verbal cues (
[laugh],[breath],[whisper], …) in narration, or do you need premium-quality prosody on long-form audio (podcasts, audiobooks, video voiceover)? → Faseeh v2. - Are you generating a voice from a free-form description rather than picking one off the shelf? → Mulhim v3.
If two answers say yes, pick the tier furthest up the ladder; you can always
override per request. The default if you don't pass model is hakim-fast-v1.
# Saree' (default) · streaming voicebot
curl https://api.tryhakim.ai/v1/audio/speech \
-H "Authorization: Bearer $HAKIM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"hakim-fast-v1","input":"Press one for sales.","voice":"alex","response_format":"pcm","stream":true}'
# Faseeh · premium narration with tags
curl https://api.tryhakim.ai/v1/audio/speech \
-H "Authorization: Bearer $HAKIM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"hakim-v2","input":"Wait. [breath] Did that just happen?","voice":"layla-egyptian","response_format":"mp3"}'
# Mulhim · voice design from a prompt
curl https://api.tryhakim.ai/v1/audio/voices/design \
-H "Authorization: Bearer $HAKIM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"description":"warm raspy elderly woman, low-pitched","sample_text":"Welcome to the test of voice design.","save_as_voice":{"name":"Grandma Demo"}}'
Recipe 2 · Bilingual content (Arabic + English in one sentence)
Tier: any. Code-switching is a model-side capability, not a tier-gated feature. Every Hakim voice can read mixed Arabic + English without explicit language hints · the renderer picks up the script and stays in the chosen voice without flipping mid-sentence.
curl https://api.tryhakim.ai/v1/audio/speech \
-H "Authorization: Bearer $HAKIM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "hakim-fast-v1",
"input": "السلام عليكم، this is Aya. Welcome to the platform.",
"voice": "cmokbc2b1001pvu39wmj61b7h",
"response_format": "mp3"
}' \
--output bilingual.mp3
Tips:
- Pick the language for the dominant register. A 70/30 Arabic/English clip reads more natural on a Khaleeji or Egyptian voice than on a French one, even if the speaker would technically pronounce both correctly.
- Punctuation matters. A comma inside the code-switch zone gives the
renderer a beat to settle into the second language.
Hello، this is Aya(Arabic comma) andHello, this is Aya(Latin comma) both work; pick the one your localisation pipeline emits. - For tags ([laugh] etc.), use Faseeh or Mulhim · tags are stripped on Saree' with a warning header but the speech still plays.
Recipe 3 · Clone an employee's voice and reuse across tiers
Tier: any. A cloned voice is a Voice row, addressable by its
voice id on every tier the same way a preset voice is. Clone once on Faseeh's
audio quality bar, then reuse the same voice id on Saree' for runtime
synthesis when latency matters.
# 1. Capture the consent + sample (one-time, ~10 s of clean audio)
curl -X POST https://api.tryhakim.ai/v1/audio/voices/clone \
-H "Authorization: Bearer $HAKIM_API_KEY" \
-F "name=Sarah, narrator" \
-F "language=ar" \
-F "consent_confirmed=true" \
-F "file=@./sarah-10s.wav"
# Returns: { "voice": { "id": "voi_01HX...", "status": "processing" } }
# 2. (Wait a few seconds, or subscribe to `voice_clone.ready` via webhook)
# 3. Use the cloned voice on whichever tier fits the task:
curl https://api.tryhakim.ai/v1/audio/speech \
-H "Authorization: Bearer $HAKIM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "hakim-fast-v1",
"input": "Welcome to your dashboard.",
"voice": "voi_01HX...",
"stream": true
}'
The cloned voice carries the same dialect, register, and timbre across all three tiers. What changes is the tier's posture: same voice, faster first byte on Saree', tag-aware prosody on Faseeh, prompt-overlay on Mulhim. See the voice cloning reference for the consent + retention contract.
Recipe 4 · Graceful tier downgrade for old integrations
Tier: Saree' (the always-on default). When a request from an older client
includes a voice_prompt field or an inline [laugh] tag, the API strips the
unsupported bits and returns 200 · your audio still plays. The
x-hakim-warnings response header tells you what was dropped:
curl -i https://api.tryhakim.ai/v1/audio/speech \
-H "Authorization: Bearer $HAKIM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "hakim-fast-v1",
"input": "Hello [laugh] world",
"voice": "alex",
"voice_prompt": "elderly woman with raspy voice"
}' \
--output speech.mp3 \
| grep -i x-hakim-warnings
# x-hakim-warnings: tags_stripped_by_model_capability, voice_prompt_dropped_by_model_capability
Sniff the header in your client to detect strips and promote to Faseeh / Mulhim
on the next call if your product surface expects the full capability set.
Server-Sent Events streaming clients receive the same header on the initial
200 OK.
Recipe 5 · Migrate from another vendor's tag set
Tier: Faseeh or Mulhim (Saree' strips tags silently). Map common non-verbal tokens from other vendors to Hakim's allowlist:
| Other vendor token | Hakim equivalent | Notes |
|---|---|---|
<break time="500ms"/> | [breath] | SSML pause, but tighter to natural breath cadence |
<emphasis> | (inline **) | Use Markdown bold inside Faseeh / Mulhim input |
[Question-ah] | [ask] | Question intonation cue |
[Surprise-yo] | [wow] | Surprise cue |
<say-as interpret-as="cardinal">42</say-as> | (literal) | We disambiguate inline numerics automatically |
[Laughter] / [Chuckle] | [laugh] | Hakim's single laugh token covers both registers |
Anything outside the allowlist is silently stripped and surfaced via
x-hakim-warnings: tags_stripped_by_model_capability. Run a one-off
preprocessing pass in your code to rewrite tokens before sending; the
diff is a regex per vendor.
Recipe 6 · A/B a new tier without changing your client
If you ship Saree' today and want to try Faseeh on a slice of traffic, pass
model per request from your backend. The wire shape is identical:
import { HakimClient } from '@hakim/node';
const client = new HakimClient({ apiKey: process.env.HAKIM_API_KEY });
async function speak(text: string, userId: string): Promise<ReadableStream> {
// Cohort 10% of users to the premium tier; everyone else stays on Saree'.
const tier = hash(userId) % 100 < 10 ? 'hakim-v2' : 'hakim-fast-v1';
const { stream } = await client.audio.speech.stream({
model: tier,
input: text,
voice: 'layla-egyptian',
response_format: 'mp3',
});
return stream;
}
Quality posture is the marketing pitch on Faseeh / Mulhim, so measure the listen-through rate rather than only TTFB. A 50 ms cost on first audio is trivial if it lifts retention on a 20-minute podcast.
Next steps
- Non-verbal tags · full token list with examples for Faseeh + Mulhim.
- Voice design · the design endpoint, prompt structure, and the save-as-voice flow on Mulhim.
- Streaming · chunked HTTP audio for sub-120 ms TTFB on Saree'.
- Errors · the
x-hakim-warningsheader, retry strategy, and idempotency keys.