Skip to main content

Overview

The Voxray server exposes a JSON/HTTP REST API for health, WebRTC signaling, session management, and Prometheus metrics, plus WebSocket and telephony transports for real-time voice pipelines. All JSON endpoints follow a consistent success and error envelope. The interactive OpenAPI specification is available at /swagger/ when the server is running. The spec file (swagger.json) is located in the docs/ folder; Mintlify renders it automatically when configured in mint.json.

Base URL

The default bind address is localhost on port 3042. Override both with configuration or environment variables.
When tls_enable is true, the server calls ListenAndServeTLS and the base URL becomes https://.

Versioned paths

All core routes are available at both a versioned prefix and a legacy path: Prefer the versioned paths for all new integrations. Legacy paths remain supported but are not guaranteed in future major versions.

Authentication

Authentication is optional and controlled entirely by the server_api_key configuration value (or the VOXRAY_SERVER_API_KEY environment variable). When this key is not set, all endpoints are open. When a key is configured, protected endpoints require one of the following request headers:
Both header forms are accepted interchangeably. The key is static — there is no login, token exchange, expiry, or refresh flow. On failure: 401 Unauthorized with error code UNAUTHORIZED.

Protected vs open endpoints

The /daily-dialin-webhook endpoint uses a separate secret (daily_dialin_webhook_secret / VOXRAY_DAILY_DIALIN_WEBHOOK_SECRET) validated via the X-Webhook-Secret header, not the server API key.

Request and Response Format

All JSON endpoints consume and produce application/json. Clients may send X-Request-ID; the server echoes it in response meta.requestId. Body size limit: Request bodies are capped at max_request_body_bytes (default 256 KB). Configure via VOXRAY_MAX_BODY_BYTES.

Success envelope

Always read the response payload from body.data. The meta object is present on all successful responses.

Error envelope

details is included only for validation errors and contains per-field information.

HTTP status codes

All error codes


Endpoints Overview

* When server_api_key is configured. † Uses X-Webhook-Secret when daily_dialin_webhook_secret is set.

Endpoint Details

GET /health

Liveness probe. Returns 200 when the server process is running regardless of dependency state.

GET /ready

Readiness probe. When session_store is redis, pings Redis before responding. Use this endpoint for load balancer readiness checks.
503 response (Redis unreachable):

GET /metrics

Returns Prometheus metrics in text exposition format. When metrics_enabled is false, returns 204 No Content.
Restrict access to /metrics in production using a network policy or firewall rule. The endpoint has no built-in authentication.

GET /swagger/

Serves the Swagger UI. The OpenAPI definition file is docs/swagger.json. Append doc.json for the raw spec: GET /swagger/doc.json.

POST /webrtc/offer

Submit a WebRTC SDP offer. The server returns an SDP answer and wires the new transport into the voice pipeline. Available when transport is smallwebrtc or both. Request body: Example:
Success (200):

POST /start

Create a runner session. Returns a sessionId plus optional ICE config or Daily room details. Supports idempotency via the Idempotency-Key header. Headers: Request body: Example:
Success (201):
When createDailyRoom is true, data also contains dailyRoom (room URL) and dailyToken.

POST /sessions//api/offer

Submit a WebRTC SDP offer for an existing session. The id path parameter must be a valid UUID obtained from POST /start. Path parameters: Request body: Example:
Success (200):

PATCH /sessions//api/offer

ICE trickle acknowledgment. Fire-and-forget — returns 204 with no body.
Returns 204 No Content on success. Same 400/401/404 errors as POST apply.

GET /ws

WebSocket upgrade for the real-time voice pipeline. One connection equals one session. The API key check (when configured) is performed before the protocol upgrade — a 401 JSON response is returned if it fails. Query parameters: Browser example:
Go example:

POST / (Telephony webhook)

Accepts webhook callbacks from Twilio, Telnyx, Plivo, and Exotel when runner_transport is set to one of those providers. Response format depends on the provider.
Returns 200 OK with Content-Type: application/xml:

GET /telephony/ws

WebSocket endpoint for telephony media streams. The provider is detected automatically from the first frames received. Available when runner_transport is twilio, telnyx, plivo, or exotel. No authentication required.

POST /daily-dialin-webhook

Handles incoming Daily PSTN dial-in events. Available when runner_transport=daily and dialin=true. When daily_dialin_webhook_secret is set, the request must include X-Webhook-Secret: <secret>. Request body: Success (201, non-test):

Middleware

Middleware is applied in the following order for every request: Auth is enforced per-handler via requireAPIKey, not as global middleware.

Idempotency

POST /start supports the Idempotency-Key request header. Submitting the same key within 24 hours returns the cached 201 Created response body without creating a new session. The cache is in-memory and does not survive process restarts.

Interactive API Docs

The full interactive Swagger UI is served at /swagger/ when the server is running. The raw OpenAPI 2.0 spec is at /swagger/doc.json and is also available as docs/swagger.json in the repository.