---
title: "Speko Router API quickstart"
description: "Call Speko Router's native model discovery, speech-to-text, LLM, and text-to-speech operations with typed responses."
canonical: "https://speko.ai/docs"
last-updated: "2026-08-24"
---

> ## Speko page index
> The complete index of every page on this site is at: https://speko.ai/llms.txt
> Read it before exploring further. It lists the exact Markdown URL for every canonical HTML page.

# Speko Router API quickstart

Docs

Call Speko Router's native model discovery, speech-to-text, LLM, and text-to-speech operations with typed responses.

## Set the credential

```bash
export SPEKO_API_KEY=sk_live_...
export SPEKO_ROUTER=https://router.speko.dev
```

## Discover models

```bash
curl --fail --silent "$SPEKO_ROUTER/v1/models" \
  -H "Authorization: Bearer $SPEKO_API_KEY"
```

## Transcribe audio

```bash
curl --fail --silent "$SPEKO_ROUTER/v1/stt/transcriptions" \
  -H "Authorization: Bearer $SPEKO_API_KEY" \
  -H "Idempotency-Key: stt-$(uuidgen)" \
  -F 'request={"routing":{"mode":"auto","objective":"latency"},"language":"en"};type=application/json' \
  -F 'audio=@sample.wav;type=application/octet-stream'
```

Response

```json
{
  "text": "What time do you close on Saturday?",
  "route": {"provider": "deepgram", "model": "nova-3", "region": "us-west-2", "attempt_id": "att_..."},
  "usage": {"duration_ms": 1840}
}
```

## Generate an LLM response

```bash
curl --fail --silent "$SPEKO_ROUTER/v1/llm/responses" \
  -H "Authorization: Bearer $SPEKO_API_KEY" \
  -H "Idempotency-Key: llm-$(uuidgen)" \
  -H "Content-Type: application/json" \
  --data '{
    "routing": {"mode": "auto", "objective": "quality"},
    "input": [{"type": "message", "role": "user", "content": [{"type": "text", "text": "What time do you close on Saturday?"}]}],
    "max_output_tokens": 128
  }'
```

Response

```json
{
  "id": "resp_req_...",
  "route": {"provider": "openai", "model": "gpt-5.2", "region": "us-west-2", "attempt_id": "att_..."},
  "output": [{"type": "message", "role": "assistant", "content": [{"type": "text", "text": "We close at six on Saturday."}]}],
  "stop_reason": "stop",
  "usage": {"input_tokens": 18, "output_tokens": 11}
}
```

## Synthesize speech

```bash
curl --fail --silent "$SPEKO_ROUTER/v1/tts/speech" \
  -H "Authorization: Bearer $SPEKO_API_KEY" \
  -H "Idempotency-Key: tts-$(uuidgen)" \
  -H "Content-Type: application/json" \
  --data '{
    "routing": {"mode": "auto", "objective": "balanced"},
    "input": "We close at six on Saturday.",
    "language": "en",
    "audio": {"encoding": "pcm_s16le", "sample_rate_hz": 24000, "channels": 1}
  }' \
  --output reply.pcm
```

## Routes

|  |  |
| --- | --- |
| GET /openapi.json | Download the canonical OpenAPI 3.1 contract without authentication |
| GET /v1/models | List currently routable models and capabilities |
| POST /v1/stt/transcriptions | Transcribe one uploaded audio file |
| GET /v1/stt/stream | Open a realtime transcription WebSocket |
| POST /v1/tts/speech | Synthesize one utterance to a raw audio stream |
| GET /v1/tts/stream | Open a streaming synthesis WebSocket |
| POST /v1/llm/responses | Generate a typed JSON or SSE LLM response |

## Request headers

|  |  |
| --- | --- |
| `Authorization` | Bearer Speko API key. Required on every /v1 operation. |
| `Idempotency-Key` | Required on every POST and WebSocket upgrade. Reuse only for a byte-identical retry. |
| `Content-Type` | application/json, multipart/form-data, or the media type declared by the operation. |

## Response headers

|  |  |
| --- | --- |
| `Speko-Request-ID` | Router correlation id; also appears in error envelopes when available. |
| `Speko-Attempt-ID` | The attempt that produced the response after any pre-output fallback. |
| `Speko-Provider` | The concrete provider selected for this response. |
| `Speko-Model` | The concrete provider model selected for this response. |
| `Speko-Region` | The Speko Router region that served the request. |
| `RateLimit-Policy` | Default edge policy: "relay-ip";q=2000;w=300. Lower concurrency controls may also apply. |
| `Retry-After` | Minimum delay on an application-generated 429; continue with exponential backoff. |

## Errors

|  |  |  |
| --- | --- | --- |
| `400` | `invalid_request` | Correct the fields named by message and hint. |
| `401` | `authentication_failed` | Replace or reactivate the bearer key. |
| `404` | `route_not_found` | Read /openapi.json and use a declared route. |
| `405` | `method_not_allowed` | Use the method in the Allow header. |
| `409` | `idempotency_conflict` | Use a new Idempotency-Key when content changes. |
| `429` | `rate_limited` | Honor Retry-After and use exponential backoff. |
| `429` | `concurrency_exhausted` | Wait for active work to finish, then retry. |
| `502` | `provider_error` | Retry or allow Router to select another provider. |
| `503` | `provider_unavailable` | Retry after a delay or use auto routing. |
| `504` | `request_timeout` | Retry; the selected provider stopped making progress. |

## Give the contract to an agent

```text
Read https://speko.ai/openapi.json. Integrate the native Speko Router contract into this repository. Do not treat Router as an OpenAI-compatible hostname. Use Idempotency-Key on every POST and preserve the typed error envelope.
```
