From fc33f16d5146c5a279ad8178dd6c6b7dd16879ba Mon Sep 17 00:00:00 2001 From: unknown <> Date: Tue, 7 Jul 2026 17:04:55 +0000 Subject: [PATCH] docs(openrouter-stt): document OpenAI-style multipart transcription requests Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- skills/openrouter-stt/README.md | 2 +- skills/openrouter-stt/SKILL.md | 43 ++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/skills/openrouter-stt/README.md b/skills/openrouter-stt/README.md index 3f9565f..34fae89 100644 --- a/skills/openrouter-stt/README.md +++ b/skills/openrouter-stt/README.md @@ -23,7 +23,7 @@ For other install methods (Claude Code plugin marketplace, Cursor Rules, etc.) s See [SKILL.md](SKILL.md) for the full reference, including: -- Why this endpoint is **not** OpenAI-compatible (base64 JSON body, not `multipart/form-data`) +- Both request shapes: base64 JSON (`input_audio`) and OpenAI-style `multipart/form-data` (works with the official OpenAI SDKs) - A drop-in bash script that base64-encodes audio, posts JSON, and extracts the transcript - Discovering STT models via `/api/v1/models?output_modalities=transcription` - Audio format guidance (`wav`, `mp3`, `flac`, `m4a`, `ogg`, `webm`, `aac`) and avoiding format/bytes mismatch diff --git a/skills/openrouter-stt/SKILL.md b/skills/openrouter-stt/SKILL.md index 08444a0..3b4eb0c 100644 --- a/skills/openrouter-stt/SKILL.md +++ b/skills/openrouter-stt/SKILL.md @@ -7,7 +7,10 @@ description: Transcribe speech to text using OpenRouter's speech-to-text API. Us Transcribe audio via `POST /api/v1/audio/transcriptions` using `curl`. Requires `OPENROUTER_API_KEY` (get one at https://openrouter.ai/keys). If unset, stop and ask. -**This endpoint is not OpenAI-compatible.** The body is JSON with base64 audio under `input_audio: { data, format }` — not `multipart/form-data` with a `file` field the way OpenAI's `/v1/audio/transcriptions` works. Do not point the OpenAI SDK at this endpoint; it will send the wrong shape. Use `curl`, `fetch`, or `requests` directly. +The endpoint accepts two request shapes: + +- **JSON** (preferred) — base64 audio under `input_audio: { data, format }`. Supports all parameters including `provider` passthrough, and handles large files via streaming offload. +- **OpenAI-style `multipart/form-data`** — a `file` field plus `model`, the same shape OpenAI's `/v1/audio/transcriptions` uses. The official OpenAI SDKs work by pointing their base URL at `https://openrouter.ai/api/v1`. Capped at 25 MB; see below. ## One call, JSON back @@ -78,6 +81,44 @@ jq -r '.text' "$BODY" rm -f "$BODY" "$PAYLOAD" ``` +## OpenAI-compatible multipart requests + +Clients built for OpenAI's transcription endpoint (including the official OpenAI SDKs) work as-is: + +```python +import os + +from openai import OpenAI + +client = OpenAI( + base_url="https://openrouter.ai/api/v1", + api_key=os.environ["OPENROUTER_API_KEY"], +) + +with open("audio.wav", "rb") as f: + result = client.audio.transcriptions.create( + model="openai/whisper-large-v3", + file=f, + ) + +print(result.text) +``` + +```bash +curl https://openrouter.ai/api/v1/audio/transcriptions \ + -H "Authorization: Bearer $OPENROUTER_API_KEY" \ + -F file="@audio.wav" \ + -F model="openai/whisper-large-v3" +``` + +Multipart specifics: + +- Supported fields: `file`, `model`, `language`, `temperature`. `prompt` and `timestamp_granularities` are accepted but ignored. +- `response_format` may only be `json` (the default); `text`, `srt`, `vtt`, and `verbose_json` are rejected with a 400. +- The audio format is derived from the filename extension or the file part's content type. +- Uploads are capped at 25 MB (same as OpenAI). That's roughly 26 minutes of 128 kbps MP3 or about 13 minutes of 16 kHz mono WAV — prefer compressed formats for long recordings, or send larger files as base64 JSON via `input_audio`. +- Provider passthrough (`provider.options.`) is JSON-only. + ## Discovering STT models Filter the models endpoint by output modality to list transcription models.