OpenRouter x AssemblyAI: Universal‑3.5 Pro is now available on OpenRouter AssemblyAI's Universal-3.5 Pro speech-to-text model is now available on OpenRouter as `assemblyai/universal-3-5-pro`, served through AssemblyAI's Sync Speech-to-Text API at AssemblyAI's published rates with no markup added by OpenRouter. The model supports the same 19 languages and is reached via a single POST to OpenRouter's transcription endpoint, with three AssemblyAI options — `prompt` (up to 6,000 characters), `keyterms_prompt`, and `conversation_context` (up to 500 turns or 16,000 characters) — passed in `provider.options.assemblyai`. Universal-3.5 Pro is now on OpenRouter The speech-to-text call at the front of your pipeline now runs on the OpenRouter key you already have. Same model, same 19 languages, our published rate with no markup. A voice agent captures a turn the moment endpointing fires, and nothing downstream can start until the words come back. A dictation feature has to put text on screen while the user is still holding the key down. A phone tree captures one utterance and branches the call on what it heard. A push-to-talk message leaves the moment the user lifts their thumb. In all of them, transcription runs first, and every model after it reasons about the words transcription handed over. A wrong word there is a wrong answer three calls later, and the LLM has no way to know it. The model layer behind that first call has consolidated everywhere except the first call itself. If you build on OpenRouter, you already reach dozens of models through one key, one billing relationship, and one request shape. Speech-to-text sat outside it — a separate vendor, a separate contract, a separate SDK — wrapped around the one component that determines what the rest of your stack sees. Today, Universal-3.5 Pro is available on OpenRouter, served through our Sync Speech-to-Text API https://www.assemblyai.com/blog/sync-api . It is listed on OpenRouter’s transcription endpoint as assemblyai/universal-3-5-pro . Pricing matches our published rates, and OpenRouter passes it through without a markup. One POST to the endpoint you already call One request, one transcript, no job to poll and no WebSocket to hold open: python import base64 import os import requests with open "turn.wav", "rb" as f: audio = base64.b64encode f.read .decode "utf-8" response = requests.post "https://openrouter.ai/api/v1/audio/transcriptions", headers={"Authorization": f"Bearer {os.environ 'OPENROUTER API KEY' }"}, json={ "model": "assemblyai/universal-3-5-pro", "input audio": {"data": audio, "format": "wav"}, }, timeout=30, response.raise for status print response.json "text" That is the whole integration. If you are already calling OpenRouter for chat completions, the path and the model string are the only things that change. The endpoint also accepts OpenAI-style multipart requests, so an existing OpenAI SDK client pointed at OpenRouter’s base URL works against Universal-3.5 Pro without a code change. Word timestamps come back through OpenRouter’s own response format and timestamp granularities fields rather than ours, which keeps the response shape identical to every other transcription model on the endpoint. Three ways to tell the model what it is about to hear Three AssemblyAI options travel in provider.options.assemblyai : prompt , keyterms prompt , and conversation context . They are what change what you get back on hard audio, and they are the difference between a transcript that is broadly right and one that gets your customer’s vocabulary right. prompt describes the situation before the first word arrives. Up to 6,000 characters telling the model what kind of speech is coming: your domain, your product, the shape of the conversation. “Transcribe this medical intake conversation” primes the decoder for clinical vocabulary, which is exactly the ground where a general-purpose model guesses and gets it plausibly wrong. Plausibly wrong is the expensive failure, because it survives every check downstream of it. conversation context passes the preceding turns with each request, up to 500 turns or 16,000 characters, and the model transcribes the current clip against that history. When a caller answers “yeah, the second one” or reads back a number the agent just asked for, the model knows what question it is answering. You are only billed for the current turn’s audio, so carrying the full dialogue costs nothing but request size. keyterms prompt takes up to 100 terms per request and biases the model toward strings you already know: product names, drug names, the SKUs that belong to this one account. Because they are sent per request, they can be scoped to the individual conversation instead of baked into a global config, which matters when your vocabulary differs per customer. curl https://openrouter.ai/api/v1/audio/transcriptions \ -H "Authorization: Bearer $OPENROUTER API KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "assemblyai/universal-3-5-pro", "input audio": { "format": "wav", "data": "