Speech-to-text API. OpenAI- and ElevenLabs-compatible interfaces on the same key — point whichever SDK you already use at this host.
👉 Interactive playground — try batch & realtime transcription in the browser, no setup.
| Method | Path | Auth | What |
|---|---|---|---|
| GET | /healthz | no | Liveness check |
| GET | /v1/models | yes | List available models |
| POST | /v1/audio/transcriptions | yes | OpenAI-style batch transcription |
| POST | /v1/speech-to-text | yes | ElevenLabs-style batch transcription |
| WS | /v1/realtime | yes | OpenAI-style realtime streaming |
| WS | /v1/speech-to-text/realtime | yes | ElevenLabs-style realtime streaming |
One API key works for both protocols and all endpoints (except
/healthz). Send via whichever header your client library
already speaks:
Authorization: Bearer <key> # OpenAI SDKs
xi-api-key: <key> # ElevenLabs SDKs
WebSocket clients that can't set custom headers (browsers) also accept
the key via the Sec-WebSocket-Protocol subprotocol entry
(bearer.<key>) or the ?api_key= /
?token= query parameter.
Pass the model identifier in the model (OpenAI) or
model_id (ElevenLabs) field. Authenticated clients can
list the available identifiers via /v1/models.
Provider-default names from the OpenAI and ElevenLabs SDKs are accepted
without modification.
Two bidirectional WebSocket surfaces — the client streams PCM audio up while the server streams transcripts back. These are not in the Swagger/OpenAPI spec: OpenAPI cannot describe WebSocket endpoints. Both pick a backend from the requested model the same way the batch endpoints do, and authenticate with the same key (see above).
WS /v1/realtime — OpenAI Realtime styleClient → server (JSON text frames):
input_audio_buffer.append — {"audio": "<base64 PCM16LE>"}input_audio_buffer.commit (or response.create) — finalise the current utterancesession.update — optional language hint mid-sessionServer → client (JSON):
session.createdconversation.item.input_audio_transcription.delta — {"delta": "…"} (incremental)input_audio_buffer.committed then
conversation.item.input_audio_transcription.completed — {"transcript": "…"}errorWS /v1/speech-to-text/realtime — ElevenLabs Realtime styleConnection config is passed as query parameters:
model_id — backend selector (optional)encoding / audio_format — must be pcm_<rate> (default pcm_16000)sample_rate — default 16000 (vLLM backends require 16000)commit_strategy — manual (default) or vad (server endpoints on silence)language_code — optional hintinclude_timestamps — true/falsecommit_strategy=vad): vad_threshold,
min_speech_duration_ms, vad_silence_threshold_secsClient → server (JSON): {"audio_base_64": "<base64 PCM>"} to stream audio,
{"commit": true} to finalise (when manual).
Server → client (JSON, discriminated by message_type):
session_started, partial_transcript {"text": "…"},
committed_transcript (or committed_transcript_with_timestamps) {"text": "…"},
error.
OpenAI-style batch:
curl -X POST https://stt.sipgate.ai/v1/audio/transcriptions \
-H "Authorization: Bearer $KEY" \
-F file=@sample.wav \
-F language=de \
-F response_format=verbose_json
ElevenLabs-style batch with raw PCM (skips server-side ffmpeg, lower latency):
ffmpeg -i sample.wav -f s16le -ac 1 -ar 16000 sample.pcm
curl -X POST https://stt.sipgate.ai/v1/speech-to-text \
-H "xi-api-key: $KEY" \
-F file=@sample.pcm \
-F file_format=pcm_s16le_16 \
-F language_code=deu
WebSocket streaming (ElevenLabs flavour, with
websocat):
websocat -t "wss://stt.sipgate.ai/v1/speech-to-text/realtime?\
encoding=pcm_16000&sample_rate=16000&\
commit_strategy=MANUAL&language_code=deu&token=$KEY"