Docs

Voice agent API quickstart

Speech-to-text, an LLM and text-to-speech through one Speko key, with the response beside every request.

Setup

export SPEKO_API_KEY=sk_live_...
pip install openai

Speech-to-text

import os
from openai import OpenAI

speko = OpenAI(api_key=os.environ["SPEKO_API_KEY"], base_url="https://api.speko.ai/v1")

with open("sample.wav", "rb") as audio:
    out = speko.audio.transcriptions.create(
        # "auto" ranks eligible models. To pin a route, use the id from a GET /v1/models row whose routable field is true.
        # Russian: pin openai:gpt-4o-transcribe and add language="ru".
        model="auto",
        file=audio,
    )
print(out.text)

Response

x-route: Deepgram/nova-3

{"text": "What time do you close on Saturday?"}

LLM

import os
from openai import OpenAI

speko = OpenAI(api_key=os.environ["SPEKO_API_KEY"], base_url="https://api.speko.ai/v1")

reply = speko.chat.completions.create(
    model="auto",
    messages=[{"role": "user", "content": "What time do you close on Saturday?"}],
)
print(reply.choices[0].message.content)

Response

x-route: OpenAI/gpt-5-mini

{"object": "chat.completion", "choices": [{"finish_reason": "stop",
  "message": {"role": "assistant", "content": "We close at six on Saturday."}}]}

Text-to-speech

import os
from openai import OpenAI

speko = OpenAI(api_key=os.environ["SPEKO_API_KEY"], base_url="https://api.speko.ai/v1")

speech = speko.audio.speech.create(
    model="auto",
    # A preset, not a pin: each provider answers it on its own voice.
    voice="alloy",
    input="We close at six on Saturday.",
    response_format="pcm",
)
speech.write_to_file("reply.pcm")

Response

x-route: Cartesia/sonic-3.5
content-type: audio/pcm;rate=24000

reply.pcm - 24 kHz mono PCM

Routes

POST /v1/transcribeTranscribe raw audio with cross-provider routing
POST /v1/synthesizeSynthesize raw PCM with cross-provider routing
POST /v1/audio/transcriptionsTranscribe audio
POST /v1/audio/speechSynthesize speech
POST /v1/chat/completionsCreate a chat completion
GET /v1/modelsList measured models
GET /v1/routing/previewPreview a route without upstream traffic
POST /v1/realtime/sessionsMint a 60-second browser credential
GET /v1/realtimeOpen a speech-to-speech WebSocket
GET /v1/transcribe/streamOpen a realtime transcription WebSocket
GET /healthzCheck routing readiness
GET /v1/synthesize/streamOpen an incremental TTS WebSocket
POST /v1/synthesize/streamSynthesize PCM, chunked as it decodes
POST /v1/audio/speech/streamOpenAI-compatible streaming speech

Request headers

X-Speko-Objectivelatency, quality, cost, balanced
X-Speko-LanguageBCP 47 language tag used for benchmark selection and provider transcription.
X-Speko-AllowComma-separated providers or provider:model ids to allow.
X-Speko-DenyComma-separated providers or provider:model ids to exclude.
X-Speko-Max-PriceMaximum published benchmark price for the request stage: STT in USD per minute, LLM in USD per 1M tokens, or TTS in USD per 1M characters. Candidates without a published price are excluded when this constraint is set.
X-Speko-Provider-OptionsProvider-specific settings to forward, as a JSON object keyed by provider name: {"deepgram":{"endpointing":1200},"smallest":{"max_words":24}}. At most 4096 bytes.

Response headers

X-RouteServing provider and model on success; last attempted route on terminal upstream failure, or none/none if no route was attempted.
X-Route-Reasonobjective:score=..;lang=xx(measured|english-proxy|none);model-pin=..
X-Speko-Failover-CountRecorded failed or circuit-bypassed candidates before success, or before a terminal failure was returned.
X-Speko-First-Byte-MsRouter-observed elapsed time at the selected adapter boundary. Successful direct HTTP routes include the first upstream body frame; buffered or translated adapters can include the completed upstream operation; terminal failures can omit this header.

Errors

400invalid_request_bodyFix the body.
400invalid_routing_headerFix the named header.
401invalid_api_keyReplace the bearer key.
413request_too_largeOver the 25 MiB replay limit.
502all_upstreams_failedEvery candidate failed. Retry with backoff.
503no_candidateNothing routable matches. Widen the constraints.

Agents

Read https://api.speko.ai/openapi.json and wire Speko into this repo: one key for speech-to-text, the LLM and text-to-speech.

Next

LiveKitAn AgentSession on one key
PipecatA pipeline on one key
ModelsThe measured rows the ranking reads
OpenAPIThe machine-readable contract