diff --git a/CLAUDE.md b/CLAUDE.md
index 48148e1..56dc4c3 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -41,7 +41,7 @@ aai.settings.api_key = "your-key"
- `aai.TranscriptionConfig` — All transcription options: `speech_models`, `speaker_labels`, `sentiment_analysis`, `entity_detection`, `auto_chapters`, `content_safety`, `language_detection`, `summarization`, `word_boost`, `disfluencies`
- `aai.Transcript` — Result object with `.text`, `.status`, `.utterances`, `.words`, `.chapters`, `.entities`, `.sentiment_analysis`. Methods: `get_sentences()`, `get_paragraphs()`, `export_subtitles_srt()`, `export_subtitles_vtt()`
- `aai.SyncTranscriber` — Synchronous pre-recorded transcription: audio in, transcript out, one request (no polling). Methods: `transcribe()`, `transcribe_async()`
-- `aai.SyncTranscriptionConfig` — Sync options: `model` (default `u3-sync-pro`), `prompt`, `keyterms_prompt`, `conversation_context`, `language_codes`, `timestamps`, `sample_rate`, `channels`
+- `aai.SyncTranscriptionConfig` — Sync options: `model` (default `universal-3-5-pro`), `prompt`, `keyterms_prompt`, `conversation_context`, `language_codes`, `timestamps`, `sample_rate`, `channels`
- `aai.SyncTranscriptResponse` — Sync result: `.text`, `.words` (`SyncWord` with `confidence` always, `start`/`end` only when `timestamps=True`), `.confidence`, `.audio_duration_ms`, `.session_id`, `.request_time_ms`
- `assemblyai.streaming.v3.StreamingClient` — Real-time streaming with event-based API (threaded)
- `assemblyai.streaming.v3.AsyncStreamingClient` — Asyncio-native counterpart; same options/events
@@ -161,8 +161,8 @@ server (`bad_audio`, `audio_too_short`, `audio_too_large`, `capacity_exceeded`,
`inference_timeout`, …) — and `.retry_after` (seconds) on 429/503. Audio limits: 80 ms–120 s,
≤40 MB, 16-bit, mono/stereo, sample rate ∈ {8000, 16000, 22050, 24000, 32000, 44100, 48000}.
-**Model**: `config.model` defaults to `"u3-sync-pro"` and is sent as the `X-AAI-Model`
-routing header (`aai.SyncSpeechModel.u3_sync_pro`).
+**Model**: `config.model` defaults to `"universal-3-5-pro"` and is sent as the `X-AAI-Model`
+routing header (`aai.SyncSpeechModel.universal_3_5_pro`).
**Pre-warming the connection**: the sync API is one request/response, so a `transcribe()`
that connects on demand pays the full DNS + TCP + TLS handshake on the critical path —
diff --git a/README.md b/README.md
index 34b267d..e9b9d8a 100644
--- a/README.md
+++ b/README.md
@@ -388,6 +388,136 @@ while page.page_details.before_id_of_prev_url is not None:
---
+### **Sync STT Transcription Examples**
+
+`aai.SyncTranscriber` posts a whole audio file and returns the finished transcript in one round trip — no job id, no polling, no status to check. Use it for short clips where you want the answer inline; use `aai.Transcriber` for long-form audio, URLs, or the rich audio-intelligence features (speaker labels, chapters, sentiment, …) the sync API doesn't expose.
+
+
+ Transcribe a local file synchronously
+
+```python
+import assemblyai as aai
+
+aai.settings.api_key = ""
+
+result = aai.SyncTranscriber().transcribe("./call.wav")
+
+print(result.text)
+for word in result.words:
+ print(word.text, word.confidence)
+```
+
+The input can be a local file path, raw `bytes`, or a binary file object — but not a URL. Pass a path/bytes, or use `aai.Transcriber` for URL ingestion.
+
+
+
+
+ Configure the transcription
+
+```python
+import assemblyai as aai
+
+aai.settings.api_key = ""
+
+config = aai.SyncTranscriptionConfig(
+ prompt="Transcribe verbatim. Preserve disfluencies.", # max 4096 chars
+ keyterms_prompt=["AssemblyAI", "Lemur", "U3-Pro"], # max 2048 chars total
+ conversation_context=[
+ # prior turns from the same conversation, oldest first
+ "I'd like to book a flight to Denver.",
+ "Sure, what date were you thinking?",
+ ],
+)
+
+result = aai.SyncTranscriber().transcribe("./call.wav", config=config)
+print(result.text)
+```
+
+Raw S16LE PCM audio needs `sample_rate` and `channels`; WAV reads them from its header.
+
+```python
+config = aai.SyncTranscriptionConfig(sample_rate=16000, channels=1)
+result = aai.SyncTranscriber().transcribe(raw_pcm_bytes, config=config)
+```
+
+
+
+
+ Set the transcription language
+
+`language_codes` steers the model toward one or more languages — a single-element list for monolingual audio, or several codes for multilingual audio. It is mutually exclusive with `prompt`; pass one or the other, not both.
+
+```python
+import assemblyai as aai
+
+aai.settings.api_key = ""
+
+config = aai.SyncTranscriptionConfig(language_codes=["es"]) # or ["en", "es"] for multilingual
+result = aai.SyncTranscriber().transcribe("./call.wav", config=config)
+print(result.text)
+```
+
+
+
+
+ Get word timestamps
+
+Word timestamps are opt-in. By default each word carries `text` and `confidence` only — `start`/`end` are `None`. Set `timestamps=True` to compute accurate per-word timings at a small latency cost.
+
+```python
+import assemblyai as aai
+
+aai.settings.api_key = ""
+
+config = aai.SyncTranscriptionConfig(timestamps=True)
+result = aai.SyncTranscriber().transcribe("./call.wav", config=config)
+
+for word in result.words:
+ print(word.text, word.start, word.end) # milliseconds
+```
+
+
+
+
+ Pre-warm the connection
+
+The sync API is a single request/response, so a `transcribe()` that connects on demand pays the full DNS + TCP + TLS handshake on the critical path. Call `warm()` as soon as you know audio is coming — for example while it is still being recorded — so the next `transcribe()` reuses the open connection.
+
+```python
+import assemblyai as aai
+
+aai.settings.api_key = ""
+
+with aai.SyncTranscriber() as transcriber:
+ transcriber.warm() # fire as recording starts
+ audio = record_until_done()
+ result = transcriber.transcribe(audio) # reuses the hot connection
+ print(result.text)
+```
+
+
+
+
+ Handle errors
+
+Failures raise `aai.SyncTranscriptError` with the HTTP `status_code`, a machine-readable `error_code` (`bad_audio`, `audio_too_short`, `audio_too_large`, `capacity_exceeded`, …), and `retry_after` (seconds) on 429/503 responses.
+
+```python
+import assemblyai as aai
+
+aai.settings.api_key = ""
+
+try:
+ result = aai.SyncTranscriber().transcribe("./call.wav")
+ print(result.text)
+except aai.SyncTranscriptError as error:
+ print(error.status_code, error.error_code, error.retry_after)
+```
+
+
+
+---
+
### **Speech Understanding Examples**
diff --git a/assemblyai/__version__.py b/assemblyai/__version__.py
index 6618e4e..35104d3 100644
--- a/assemblyai/__version__.py
+++ b/assemblyai/__version__.py
@@ -1 +1 @@
-__version__ = "0.64.29"
+__version__ = "0.64.31"
diff --git a/assemblyai/types.py b/assemblyai/types.py
index 097facf..05a6f87 100644
--- a/assemblyai/types.py
+++ b/assemblyai/types.py
@@ -3021,7 +3021,7 @@ def _normalize_conversation_context(v):
class SyncSpeechModel(str, Enum):
"""Speech models available on the synchronous transcription API."""
- u3_sync_pro = "u3-sync-pro"
+ universal_3_5_pro = "universal-3-5-pro"
class SyncTranscriptionConfig(BaseModel):
@@ -3035,7 +3035,7 @@ class SyncTranscriptionConfig(BaseModel):
sent as the `X-AAI-Model` routing header, not in the request body.
"""
- model: str = SyncSpeechModel.u3_sync_pro.value
+ model: str = SyncSpeechModel.universal_3_5_pro.value
"The sync speech model to route to. Sent as the `X-AAI-Model` header."
prompt: Optional[str] = Field(default=None, max_length=_SYNC_MAX_PROMPT_LEN)
@@ -3059,9 +3059,9 @@ class SyncTranscriptionConfig(BaseModel):
language_codes: Optional[List[str]] = None
"""ISO 639-1 codes for the language(s) of the audio — a single-element
list (e.g. `["es"]`) for monolingual audio, or several codes (e.g.
- `["en", "es"]`) for multilingual audio. Steers the default transcription
- prompt toward the named language(s); ignored when `prompt` is set.
- Defaults to English. Supported: en, es, de, fr, it, pt, tr, nl, sv, no,
+ `["en", "es"]`) for multilingual audio. Overrides the default prompt
+ to guide the model to the named language(s); ignored when `prompt` is set.
+ Defaults to None. Supported: en, es, de, fr, it, pt, tr, nl, sv, no,
da, fi, hi, vi, ar, he, ja, ur, zh."""
sample_rate: Optional[int] = None