Auth. When API keys are enabled (the default), every route except GET /v1/health requires an x-api-key header; GET /v1/metrics has its own toggle (VIDARAX_METRICS_REQUIRE_API_KEY). Missing or invalid keys return 401 unauthorized.
Ownership. Runs and uploaded files belong to the authenticated principal. A run owned by a different principal returns 404 not_found, indistinguishable from a missing run. x-tenant-id is metadata, not an authorization boundary.
Rate limits. The global limiter (when configured) applies to every request, including health checks; the per-principal limiter applies to authenticated routes. Both return 429 rate_limited.
Request IDs. Handler-generated JSON bodies usually carry a string request_id (format req- plus 16 hex digits). The health check, run list, upload response, interaction response, file serving, and WHIP routes are exceptions documented below.
Errors use the JSON envelope described below, except for the routes explicitly marked as returning raw bodies.
{ source_uri, sampling_policy?, fixed_fps?, sample_fps?, max_frames?, stream_id? }. source_uri is required and must resolve under an ingest root or the upload root. sampling_policy is source_fps_adaptive (default) or fixed; fixed_fps must be in [0.2, 120] and is required for fixed; max_frames is in [1, 500000], default 512. Unknown fields are rejected.
{ model, mode?, stream_id?, sampling_policy?, fixed_fps?, frames?, window_size?, segment_ms?, trace_id? }. Supply 1 to 4096 frames with normalized scores, or omit frames to reuse signals from the run’s latest frames_decoded event. window_size is in [2, 256]; segment_ms is in [50, 60000].
Appends semantic_chunk_inferred and semantic_chunk_generated per chunk, marker_emitted per marker, semantic_fallback_activated when semantic inference was requested with no provider, and run_completed
{ model, prompt, run_id?, max_tokens?, temperature?, timeout_ms?, allow_fallback?, primary_provider?, output_schema? }. Prompt 1 to 32768 bytes; max_tokens in [1, 4096]; temperature in [0, 2]; timeout_ms in [1, 120000]; primary_provider one of vllm, sglang, gemini, mlx.
Both feedback routes require the optional SpacetimeDB integration; without VIDARAX_SPACETIMEDB_URL they return 500 with a “spacetimedb client not configured” message.
GET /v1/runs/:id/keyframes/:sha256 returns image/jpeg bytes for a hash referenced by a keyframe_stored event on that run. The caller must own the run; knowing a blob hash from another run is not enough to retrieve it. Responses use a private immutable cache policy and an ETag equal to the content hash. Invalid hashes return the JSON validation envelope, and missing references or files return the JSON not-found envelope. Image bytes are never placed in JSON or base64-encoded by this API.
Success and failure statuses for the four WHIP routes are covered in WebRTC ingest. Two things differ from the rest of the API: POST /v1/stream/whip answers with raw SDP (plus Location and x-vidarax-run-id headers) rather than JSON, and WHIP failures return bare status codes or plain-text bodies rather than the JSON envelope. The offer accepts an optional x-attach-config header (base64url-encoded JSON, no padding, size-capped) whose prompt, max_output_tokens_per_second, clip_mode, and normalized crop fields apply before workers start. Unknown attach fields are rejected. PATCH /v1/stream/whip/:sess/prompt accepts { prompt, output_schema? }, where output_schema is a JSON Schema object, and returns the applied values. Token caps, crop, and clip mode cannot be changed after start.
Handler errors share one JSON shape. The request_id is a string and lives inside the error object:
{
"error": {
"code": "validation_error",
"message": "invalid ingest request",
"request_id": "req-000000000000002a",
"details": [
{ "field": "source_uri", "message": "..." }
]
}
}
Status
Code
When
400
validation_error
CORS preflight without an Origin header.
401
unauthorized
Missing or invalid x-api-key; missing x-tenant-id when required.
403
cors_forbidden
Preflight from an origin outside the allowlist.
404
not_found
Unknown, deleted, or other-principal run_id.
409
conflict
Action on a terminal run; active stream limit exceeded.
422
validation_error
Field-level validation failure; details lists the fields.
429
rate_limited
Global or per-principal rate limit exceeded.
500
internal_error
Internal failure; the message is sanitized and details are logged server-side.
503
metrics_unavailable
Metrics auth enabled with no API keys configured.
Not everything uses the envelope. WHIP routes return raw SDP on success and bare status codes or plain text on failure; GET /v1/files failures are plain text; and requests rejected before a handler runs (malformed JSON bodies, unknown routes, oversized uploads) get the framework’s default plain responses.
Binary TCP embedding sidecar; setting it enables live semantic novelty
VIDARAX_NOVELTY_REUSE_THRESHOLD
0.01
Conservative embedding-distance ceiling for description reuse; calibrate it on labelled deployment traffic
When neither backend URL is set, the server reads a TOML config file (VIDARAX_CONFIG, default vidarax.toml) that declares backends in priority order; the parser supports openai_compat and gemini backend types, and string fields interpolate ${ENV_VAR} references. When either explicit URL is set, the TOML file is not read.
The full configuration reference, including decode backend selection, CORS, rate limits, WebRTC and TURN settings, and SpacetimeDB, lives in docs/deployment.md in the repository. The hardening-relevant variables are summarized in Operations.