Server API
OpenASR can run a local HTTP server so existing applications can call local speech recognition through a single interface.
Start the local server:
openasr serveBy default it binds 127.0.0.1:8080. Non-loopback remote serving requires
--tls-self-signed (or another TLS setup) and pairing auth — see
openasr serve --help.
Endpoints
Section titled “Endpoints”Routes marked Operator require the admin/operator credential when
pairing auth is active — paired remote-compute device
tokens receive 403. In simple bearer-token mode the distinction does not
apply; any valid key can call any route. /health and
POST /v1/pairing/requests are always unauthenticated.
| Method | Path | Operator |
|---|---|---|
| GET | /health | |
| GET | /v1/models | |
| GET | /v1/catalog | |
| GET | /v1/capabilities | |
| GET | /v1/devices | |
| GET | /v1/config | Yes |
| PUT | /v1/config | Yes |
| POST | /v1/audio/transcriptions | |
| GET | /v1/audio/transcriptions/progress | |
| POST | /v1/audio/transcriptions/{id}/cancel | |
| POST | /v1/audio/transcriptions/{id}/pause | |
| POST | /v1/audio/transcriptions/{id}/resume | |
| POST | /v1/audio/translations | |
| ANY | /v1/audio/realtime | |
| GET | /v1/history | Yes |
| GET | /v1/history/{id} | Yes |
| DELETE | /v1/history/{id} | Yes |
| GET | /v1/speakers | Yes |
| POST | /v1/speakers | Yes |
| PATCH | /v1/speakers/{id} | Yes |
| DELETE | /v1/speakers/{id} | Yes |
| POST | /v1/speakers/{id}/reenroll | Yes |
| GET | /v1/models/local | |
| POST | /v1/models/local/import | Yes |
| GET | /v1/models/default | |
| POST | /v1/models/default | Yes |
| PUT | /v1/models/default | Yes |
| DELETE | /v1/models/{id} | Yes |
| POST | /v1/models/{id}/pull | Yes |
| GET | /v1/models/pull/{job_id} | |
| GET | /v1/models/pull/{job_id}/events | |
| POST | /v1/models/pull/{job_id}/cancel | Yes |
| POST | /v1/models/pull/{job_id}/pause | Yes |
| POST | /v1/models/pull/{job_id}/resume | Yes |
| POST | /v1/pairing/requests | |
| GET | /v1/pairing/requests | Yes |
| POST | /v1/pairing/requests/{request_id}/approve | Yes |
| DELETE | /v1/pairing/requests/{request_id} | Yes |
| GET | /v1/pairing/requests/{request_id}/credential | Varies |
| GET | /v1/pairing/credentials | Yes |
| DELETE | /v1/pairing/credentials/{device_id} | Yes |
Authentication
Section titled “Authentication”The server supports three auth modes:
- Disabled (default) — loopback is trusted, no key required.
- Bearer token — one or more static keys managed by
openasr apikey create/list/revoke. Any valid key can call any route. - Pairing — an admin/operator token plus a device-credential registry.
The operator-only column above applies in this mode: paired device tokens
are rejected (
403) on routes that touch the operator’s local data (config, history, speakers) or mutate models.
/health is always reachable without credentials, even when auth is
enabled. On missing or invalid credentials the server returns
401 Unauthorized with a WWW-Authenticate: Bearer header. On valid
but insufficient credentials for an operator-only route it returns
403 Forbidden.
Transcriptions
Section titled “Transcriptions”curl -s http://127.0.0.1:8080/v1/audio/transcriptions \ -F model=whisper-small \ -F response_format=jsonSupported response_format values:
jsontextsrtvttverbose_jsonmarkdown
This endpoint is compatible with the OpenAI audio transcriptions API subset; migrating an existing integration usually only requires pointing it at the local server URL and making sure the requested model is installed.
Transcription job control
Section titled “Transcription job control”Long file transcriptions can be monitored and controlled while in flight:
GET /v1/audio/transcriptions/progress— returns the current phase and fraction-complete of the active file transcription. When nothing is running, all fields are zero/null.POST /v1/audio/transcriptions/{id}/cancel— cancels at the next long-form slice boundary; already-decoded segments are discarded.POST /v1/audio/transcriptions/{id}/pause— pauses at the next slice boundary; the request blocks until a matching resume or cancel.POST /v1/audio/transcriptions/{id}/resume— resumes a paused job, keeping already-accumulated segments.
If a client disconnects mid-decode, the in-flight native worker is auto-cancelled rather than leaked.
Translations
Section titled “Translations”POST /v1/audio/translations mirrors /v1/audio/transcriptions but always
translates the source audio to English (matching the OpenAI translations
contract), backed by a translation-capable pack such as Hy-MT2. It shares the
same multipart form fields and non-streaming response formats.
Streaming (realtime)
Section titled “Streaming (realtime)”/v1/audio/realtime upgrades to a WebSocket for streaming transcription
and, when a translation-capable pack is installed, streaming translation. It
emits incremental events (VAD, partial/final transcript segments,
speech-boundary) instead of waiting for a full-file response.
Models and catalog
Section titled “Models and catalog”GET /v1/catalogreturns the signed model catalog (available models, quantizations, licenses) the server can pull from.GET /v1/models/locallists model packs already installed underOPENASR_HOME, including anis_defaultflag per pack.POST /v1/models/local/importinstalls a model pack from a.oasrfile already present on local disk — it never touches the network.GET /v1/models/defaultreturns the current default pack selection.POST /v1/models/default(orPUT) sets the default model by id or via an auto-select that picks the best installed quant; persists across restarts.DELETE /v1/models/{id}removes an installed pack. If it was the default, the default-model selection is cleared.
Model pull jobs
Section titled “Model pull jobs”POST /v1/models/{id}/pull starts an async download job. The JSON body
accepts quant, size, accept_license, and from. License-gated models
require accept_license: true or the request returns 400. If the pack is
already installed the response is 200; otherwise 202 Accepted with a
queued job snapshot.
GET /v1/models/pull/{job_id}— job status snapshot (state, progress bytes, speed, ETA, error, installed path).GET /v1/models/pull/{job_id}/events— Server-Sent Events stream of download progress.POST .../cancel,.../pause,.../resume— lifecycle control (operator-only).
Config
Section titled “Config”GET /v1/config— returns the full config document (config and preferences). Operator-only.PUT /v1/config— accepts either a full config-document JSON body or a narrow preferences patch (e.g.{"preferences": {"diarize": true}}) that merges over the existing stored preferences without resetting other fields. Validated against the model registry before saving. Operator-only.
See the Configuration page for available preference keys.
History
Section titled “History”GET /v1/history— paginated list of past transcription/translation runs. Query parameters:search,kind(fileorlive),limit(default 50, max 500),offset. Returns{object, data, total, limit, offset}.GET /v1/history/{id}— single entry detail;404if not found.DELETE /v1/history/{id}— delete one entry; returns{deleted, id}.
All history endpoints are operator-only. Entries are pruned according to the
history_retention preference on every request.
Speakers
Section titled “Speakers”GET /v1/speakers, POST /v1/speakers, PATCH /v1/speakers/{id},
DELETE /v1/speakers/{id}, and POST /v1/speakers/{id}/reenroll manage
enrolled speaker profiles used for diarization and speaker labeling. All are
operator-only. See the Diarization page for details on
speaker enrollment.
Capabilities and devices
Section titled “Capabilities and devices”GET /v1/capabilities— returns what the currently bound model/backend supports (transcription, realtime), derived from the native pack’s capabilities.GET /v1/devices— read-only hardware/compute-device enumeration (default_execution_target,devices), reflecting the daemon’s actual ggml runtime detection.
Pairing
Section titled “Pairing”Pairing lets a remote-compute device authenticate to the server with its own credential, distinct from the operator’s admin token.
POST /v1/pairing/requests— a remote device creates a pairing request (unauthenticated entry point).GET /v1/pairing/requests— operator lists pending requests.POST /v1/pairing/requests/{request_id}/approve— operator approves, issuing a device credential.DELETE /v1/pairing/requests/{request_id}— operator rejects a request.GET /v1/pairing/requests/{request_id}/credential— fetch the issued credential for an approved request.GET /v1/pairing/credentials— operator lists all issued credentials.DELETE /v1/pairing/credentials/{device_id}— operator revokes a device.
A paired device identifies itself with the x-openasr-remote-compute: client
request header. Operator-only routes reject device tokens with 403.
/health fields
Section titled “/health fields”curl -s http://127.0.0.1:8080/healthBesides status, server_version, pid, and instance_token, the response
carries fields useful for diagnosing model residency and idle behavior:
model_installed(bool) — whether a model is currently bound and ready to serve transcription requests.falseon a fresh install with zero pulled models; the daemon is still healthy, it just has nothing to transcribe with yet.model_resident(bool) — whether the bound model’s runtime is currently resident in memory, i.e. ready to transcribe instantly with no cold-load latency.model_installed: true, model_resident: falsemeans a model is bound but its runtime has been unloaded (idle past the configuredidle_unloadthreshold, or never loaded yet this boot) — the next transcription request pays a cold rebuild before it can run, which is expected, not an error. Alwaysfalsewhenmodel_installedisfalse.native_active_count(u64) — the process-wide count of currently active native requests/sessions: in-flight offline transcriptions/translations and attached realtime native-streaming sessions both count. A transient nonzero count during a single request is normal; useful when diagnosing whyidle_unloadhas not fired yet.idle_seconds(u64) — seconds elapsed since the native activity count last returned to zero (0whilenative_active_countis nonzero). Compare against the configuredidle_unloadthreshold to see how close the next eviction sweep is.abandoned_worker_count(u64) — the count of native streaming decode workers the decode watchdog has abandoned because a decode never returned within its budget. Normally0; a nonzero value is a strong signal of a GPU/driver-level decode hang. The daemon fails loud and exits once this reaches its internal threshold, so a supervisor can restart it cleanly.
Idle model unload
Section titled “Idle model unload”To keep memory free, the server evicts an idle model’s runtime from memory
after a configurable idle period (idle_unload) — the pack stays installed
on disk, so the next request just pays a normal load/warm-up cost again. The
default threshold is 10 minutes of no active request or realtime
session; other supported settings are never, now (~5 seconds), 2m, and
1h.
Runtime posture
Section titled “Runtime posture”The server runs native (the same fail-closed, ggml-backed backend as the
CLI) against an already-installed or explicitly pinned (--model-pack)
local pack. It never downloads a model to satisfy a transcription
request — the operator-authenticated POST /v1/models/{id}/pull is the
only server-side path that downloads from the network; local imports via
/v1/models/local/import install from a path already on disk. There is no
telemetry.
See the Models page for available models and the CLI reference for install/management commands. To run this server from a published container image (CPU multi-arch or CUDA), see Docker.