Speko Docs

Control plane API

The hosted API at gateway.speko.dev that the sidecar consumes in managed mode.

The gateway talks to Speko's control plane at https://gateway.speko.dev in managed mode. You normally never call these endpoints yourself — the sidecar does — but the contract is documented here for transparency and for anyone implementing the protocol independently.

Conventions

  • Auth is Authorization: Bearer <SPEKO_API_KEY>, except where noted.
  • Every plan-related POST sends Idempotency-Key and Speko-Protocol-Revision: 3 (exact match required; mismatches return 400 unsupported_protocol_revision).
  • Bodies are JSON, capped at 1 MiB, with unknown fields rejected.
  • Every response carries an X-Request-ID header (cp_...) — quote it in support requests.
  • The error envelope is minimal: {"error":{"code":"..."}}. Note this differs from the relay envelope.

Endpoints

Method + pathAuthPurpose
GET /healthz, GET /readyznonehealth
GET /.well-known/jwks.jsonnonesession-plan signing keys
GET /.well-known/relay-jwks.jsonnonerelay-plan signing keys (separate key set by design)
POST /v1/session-plansAPI keymint one signed session plan
POST /v1/session-plan-batchesAPI key{"count": N, "plan": {...}} → up to 16 plans (warm-pool prefetch)
POST /v1/sessions/{session_id}/fallback-plansAPI key or plan tokenexchange a failed attempt for a plan on a backup provider
PUT /v1/runtime-instances/{instance_id}API keyinstance heartbeat
DELETE /v1/runtime-instances/{instance_id}API keymark instance offline
POST /v1/runtime-eventsplan telemetry tokenauthenticated content-free telemetry
POST /v1/anonymous-runtime-eventsnone allowedBYOK anonymous telemetry; a request with an Authorization header is rejected
POST /v1/turn-eventsAPI keyauthenticated conversation-profiler markers
POST /v1/anonymous-turn-eventsnone allowedBYOK profiler markers without account linkage; authorization headers are rejected

Plan issuance errors

StatusCode
401authentication_failed
402credit_exhausted
403launches_disabled, provider_not_entitled
409idempotency_conflict, idempotency_in_progress
422no_eligible_route
429quota_exhausted
503service_unavailable

The control plane and the relay name credit exhaustion differently: credit_exhausted here, insufficient_credit on the relay. Both are HTTP 402.

What a signed session plan contains

The plan is a JWS (typ: speko.session-plan+jws, algorithm EdDSA or RS256, audience speko-runtime) whose payload binds:

  • plan_id, session_id, attempt_id, and an expiry (minutes)
  • the route: provider, model, optional voice and region, adapter, transport, endpoint, and — on managed routes — a short-lived provider credential
  • the reservation: metering unit, authorized units, a fixed provider-direct deadline, and concurrency reservation
  • the telemetry destination and session-scoped token
  • an optional fallback exchange URL
  • requirements: protocol speko.voice.v0, revision exactly 3

The gateway verifies signature, kid against the JWKS, issuer, audience, expiry, and single-use jti before opening the provider connection. Fallback exchanges are always forced to the configured control-plane origin, even if a plan says otherwise. Full trust details in Trust and signing.

Provider-direct plan deadlines are fixed and enforced locally. There is no mid-call renewal endpoint. The hosted Relay uses a separate renewable lease contract for its long-lived streams.

On this page