> ## Documentation Index
> Fetch the complete documentation index at: https://developers.mihu.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Native API

> Transcribe files and live audio with the Umay API

## Parameters (both endpoints)

| Parameter | Default | Meaning |
| - | - | - |
| `model` | — | `umay` (offline, most accurate; files) or `umay-stream` (streaming; live calls) |
| `language` | — | `tr`, `en`, `de`, `fr`, `it`, `ru`, `es` |
| `normalize` | `true` | Damga Pro ITN on final text: "bin iki yüz elli lira" → "1.250 TL"; `false` = spoken words |
| `dialect_correction` | `true` | Turkish, with `normalize=true`: regional/colloquial forms in standard Turkish ("istiyom gari" → "istiyorum artık"); `false` keeps them as spoken |
| `place_correction` | `true` | Turkish, with `normalize=true`: misheard or split place names corrected ("Baba Eski" → "Babaeski"); `false`: as heard |
| `abbreviations` | `false` | Turkish, with `normalize=true`: `false` writes units out ("43 dakika", "30 gigabayt"), `true` abbreviates ("43 dk", "30 GB"). "bir dakika" / "bir saniye" (a moment) always stay words |
| `mode` | `fast` | `normal`: files with `model=umay` use the language model where the model has one; `fast`: never. Other models and languages are the same in both modes; live streams never use it. Any other value → `400` |
| `hint_context` | none | Built-in hint lists (tr): `mugla`, `izmir`, `manisa`, `aydin`, `denizli`; comma-separated for several; `none` = no list (also accepted as `hint-context`) |
| `hints` | none | Own phrases (names, places) to favour, comma/newline separated; `phrase :3` gives one phrase its own boost |
| `hints_score` | `2.0` | Boost for phrases without their own |
| `gender_detection` | `false` | Gender of the speaker(s) with confidence `percent` (50–100) |
| `diarize` | `false` | Speaker label per final text (`S1`, `S2`, …) |
| `max_speakers` | `8` | Upper bound for diarization |
| `speaker_lock` | `false` | Only the first speaker's speech becomes text; other voices come as `ignored`. Each `final` / `ignored` (file: each segment) carries `similarity`: that voice against `S1` (about −1 to 1), so you can apply your own rule |
| `lock_threshold` | `0.5` (`0.55` with `reference_voiceprint`) | With `speaker_lock`: the `similarity` a segment needs to count as `S1` (0–1; higher = stricter). Without `speaker_lock` → `400` |
| `voice_isolation` | `false` | Removes other voices before recognition (tr, de, fr, it, es, ru); switches on only after another voice is heard — a single speaker, even in loud noise, gets the same text as without the option |
| `reference_voiceprint` | none | Id of a [stored voiceprint](https://developers.mihu.ai/stt/voiceprints.md): with `voice_isolation`, `speaker_lock` or `diarize`, speaker `S1` is that person from the first second — even if someone else speaks first. Off unless sent |

Older names (`itn`, `lm`, `gender`, `hotwords`, `hotword_set`, `hotwords_score`) are still accepted; when both
are sent, the name above wins. Hints work in Turkish; other languages answer `400` to `hints` / `hint_context`.

## File: `POST /v1/audio/transcriptions`

```bash theme={null}
curl https://stt.eu.mihu.ai/v1/audio/transcriptions -H "Authorization: Bearer $KEY" \
  -F file=@call.wav -F model=umay -F language=tr -F gender_detection=true -F hint_context=mugla
```

Any common format (WAV, MP3, …); resampled to 16 kHz. Long files are cut at quiet points and joined. Instead of
uploading, `file_url=https://…` lets the server download the file (see below). For long recordings (calls, meetings)
send `webhook_url` and get the result later: [Asynchronous transcription and webhooks](https://developers.mihu.ai/stt/async.md).

```json theme={null}
{"text": "Adresiniz Şirinyer Mahallesi, Cumhuriyet Caddesi No: 17.", "model": "umay", "language": "tr", "duration": 7.2,
 "processing_time": 0.16,
 "speakers": [{"speaker": "S1", "gender": "female", "percent": 97, "speech_seconds": 6.8}]}
```

With `diarize=true` the reply also has `segments`: `[{"speaker": "S1", "start": 0.4, "end": 3.1, "text": "..."}]`.

## Live: `WS /v1/stream`

```
wss://stt.eu.mihu.ai/v1/stream?model=umay-stream&language=tr&api_key=<KEY>&gender_detection=true&hint_context=mugla
```

**Client → server**

* Binary frames: raw PCM, 16 kHz, mono, signed 16-bit little-endian; \~100 ms per frame (3 200 bytes).
  Telephony audio (8 kHz μ-law/A-law) must be converted to 16 kHz PCM first.
* Text frame `{"event": "flush"}`: the client's VAD says the person stopped → final text now (optional; the server also
  ends a sentence after \~0.8 s of silence).
* Text frame `{"event": "end"}`: call finished → last final, `usage`, then the server closes.

**Server → client** (JSON text frames)

| `type` | Example | Meaning |
| - | - | - |
| `partial` | `{"type":"partial","text":"adresiniz şirin","segment":0}` | Running text while the person speaks (no ITN) |
| `final` | `{"type":"final","text":"Adresiniz Şirinyer Mahallesi.","segment":0,"start":0.4,"end":3.1,"speaker":"S1"}` | Sentence done, ITN applied; `start`/`end` in seconds; `speaker` only with `diarize` |
| `speaker` | `{"type":"speaker","speaker":"S1","gender":"female","percent":97}` | With `gender_detection`: \~2 s after speech starts, updated later; never delays text |
| `ignored` | `{"type":"ignored","text":"...","speaker":"S2","similarity":0.12}` | With `speaker_lock`: speech of other voices (the `final` of the locked person carries `similarity` too, e.g. `0.78`) |
| `usage` | `{"type":"usage","audio_seconds":42.1}` | At the end |

`segment` increases by one after each `final`. Send the `final` text to the language model, show `partial` only as live text.

**Close codes**: `1013` server busy (live-call limit reached; retry after \~1 s) · `4400` bad parameter (e.g. language) ·
`1000` normal end.

## Python example

```python theme={null}
import asyncio, json, websockets

async def transcribe(chunks):                      # chunks: 100 ms of 16 kHz mono int16 PCM bytes
    url = "wss://stt.eu.mihu.ai/v1/stream?model=umay-stream&language=tr&api_key=KEY&gender_detection=true"
    async with websockets.connect(url, max_size=None) as ws:
        async def read():
            async for m in ws:
                d = json.loads(m)
                if d["type"] == "final":
                    print("FINAL", d["text"])
                elif d["type"] == "speaker":
                    print("GENDER", d["gender"], d["percent"])
        reader = asyncio.create_task(read())
        for chunk in chunks:
            await ws.send(chunk)
        await ws.send(json.dumps({"event": "end"}))
        await reader
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.