Ormia API
Send audio, get clean, punctuated text back. The API is OpenAI-compatible: tools and SDKs that already call OpenAI’s transcription endpoint switch by changing the base URL and key.
https://ormia.ai/v1Private beta. API keys go to developers on the waitlist first. Join the waitlist and pick “API” to get one.
Quickstart
Transcribe a file with cleanup (fillers removed, “no wait” corrections applied, lists formatted):
curl https://ormia.ai/v1/audio/transcriptions \
-H "Authorization: Bearer $ORMIA_API_KEY" \
-F file=@meeting-note.m4a \
-F style=formal \
-F dictionary="Ormia, Qwen3"from openai import OpenAI
client = OpenAI(base_url="https://ormia.ai/v1", api_key="orm_...")
with open("meeting-note.m4a", "rb") as f:
result = client.audio.transcriptions.create(model="ormia-1", file=f)
print(result.text)import fs from "node:fs";
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://ormia.ai/v1", apiKey: process.env.ORMIA_API_KEY });
const result = await client.audio.transcriptions.create({
model: "ormia-1",
file: fs.createReadStream("meeting-note.m4a"),
});
console.log(result.text);Response:
{ "text": "The launch is Friday." }Authentication
Every request needs an API key in the Authorization header:
Authorization: Bearer orm_...Keys are shown once when created. Ormia stores only a hash of each key. Keep keys on your server; never put them in a web page or a mobile app.
POST/v1/audio/transcriptions
Audio in, clean text out. The request is multipart/form-data.
| Field | Required | Description |
|---|---|---|
file | yes | The audio: WAV, MP3, M4A, WebM, OGG or FLAC, up to 4.4 MB |
language | no | An ISO code from the language list. Omit it to auto-detect, which also covers 22 Chinese dialects. Unknown codes fall back to auto-detect |
cleanup | no | true (default) removes fillers, applies “no wait” corrections and formats lists. false returns the raw transcript |
style | no | clean (default), casual or formal |
dictionary | no | Comma-separated names and terms to spell exactly, e.g. Ormia, Qwen3. Up to 100 terms of 64 characters each, 2,048 characters in total |
prompt | no | OpenAI-compatible alias: also treated as vocabulary, under the same limits |
response_format | no | json (default), text or verbose_json |
model | no | Accepted for compatibility and ignored |
4.4 MB fits about 4.5 minutes of 16 kHz WAV, or 15 minutes or more of compressed audio. For longer recordings, send compressed audio or split it.
verbose_json adds raw_text (before cleanup), language, duration (billed seconds), cleanup and style. If cleanup fails or takes longer than 4 seconds, you get the raw transcript and cleanup is false.
Every successful response has a Server-Timing header with the milliseconds spent on each step (read, reserve, asr, cleanup, settle, total).
POST/v1/edit
Rewrite text with a spoken or typed instruction. Text up to 20,000 characters, instruction up to 2,000.
curl https://ormia.ai/v1/edit \
-H "Authorization: Bearer $ORMIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text": "We should probably meet sometime next week to discuss the roadmap.", "instruction": "make this more direct"}'{ "text": "Let's meet next week to discuss the roadmap." }GET/v1/usage
This month’s usage and what is left of your allowance.
curl https://ormia.ai/v1/usage -H "Authorization: Bearer $ORMIA_API_KEY"{
"plan": "free",
"month_audio_seconds": 600, "allowance_audio_seconds": 1800, "remaining_audio_seconds": 1200,
"month_edits": 3, "allowance_edits": 50, "remaining_edits": 47
}Languages
Qwen3-ASR recognises 30 languages. Pass one of these codes as language, or leave it out to auto-detect:
zh en yue ar de fr es pt id it ko ru th vi ja tr hi ms nl sv da fi pl cs fil fa el hu mk ro
Allowances and limits
| Plan | Audio per month | Edits per month |
|---|---|---|
| Free | 30 minutes | 50 |
| Pro | 300 minutes | 2,000 |
| Teams | 600 minutes per seat | 5,000 |
Audio is counted by the duration the speech model reports, rounded up to the second. Ormia reserves an estimate before transcribing and settles to the real duration afterwards, so parallel requests can’t run past an allowance. When an allowance is used up, requests return 429 with code insufficient_quota until the next calendar month (UTC). Each network is also limited to 300 requests a minute.
Errors
Errors use OpenAI’s shape, so SDKs show the message:
{ "error": { "message": "Invalid or revoked API key.", "type": "invalid_request_error", "code": "invalid_api_key" } }| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_body, missing_file, empty_file, invalid_style, invalid_format, missing_instruction | Fix the request |
| 401 | invalid_api_key | Missing, malformed or revoked key |
| 413 | file_too_large, too_long, dictionary_too_long | Over a size limit |
| 405 | method_not_allowed | Wrong HTTP method for the endpoint |
| 415 | unsupported_media_type | Audio format not accepted |
| 429 | insufficient_quota | Monthly allowance used |
| 429 | none | More than 300 requests a minute from one network; wait a minute and retry with backoff |
| 502 | upstream_error | The speech or language model failed; retry |
| 503 | unavailable | Temporary outage; retry |
Privacy
Audio and text pass through OpenRouter to the provider that runs the open-weight Qwen models (Qwen3-ASR-0.6B for speech, with Qwen3-ASR-1.7B as a fallback; Qwen3-30B-A3B-Instruct for cleanup), and are not stored by Ormia. Ormia records only the seconds of audio and the number of requests per day, for billing. Read the full privacy policy.