Discord

API reference

Every route below, except API key management, is for sending model requests, and requires Authorization: Bearer llmr_sk_<env>_… — see Authentication.

GET /v1/balance returns the key's wallet for low-balance alerts: {"balance_usd", "available_usd", "held_usd", "held_release_at"}. Alert on available_usd — it excludes in-flight job reservations and unreleased ACH holds, the number a new request is checked against. Unbilled.

Pricing

Two read-only calls tell you what something costs before you send it. Neither reserves credits, calls a provider, or is billed.

GET/v1/models

Every row carries a pricing object — the model's list price, the same numbers as the /models page. One shape for every model type: unit says what each number in rates is per, and rates is keyed by whatever the price varies on (a video's resolution tier, an image's size/quality, token direction). "*" means the same for every option. The platform_fee_rate is billed on top: you pay rate × (1 + platform_fee_rate). pricing is null for auto (it routes per request) and for a model with no published price yet.

{
  "id": "fal/seedance-2.0",
  "object": "model",
  "type": "video",
  "endpoint": "/v1/videos",
  "pricing": {
    "currency": "USD",
    "unit": "second",
    "rates": { "480p": 0.1345, "720p": 0.3034, "1080p": 0.682, "4k": 1.5552 },
    "platform_fee_rate": 0.025
  }
}
unitModels & what rates is keyed by
1m_tokenschat (input, output, cache_read, cache_write), embeddings, and token-billed image / speech models
secondvideo, lip sync, face swap, avatars, sound effects, live video — keyed by resolution tier (avatars: avatar_type/resolution; live video: standard / fast, plus world_setup_fee and min_billed_seconds where a model has them)
clipvideo priced per finished clip, keyed by length ("6s", "10s")
imageimages — "*", or size/quality (e.g. "1k/standard")
minute · song · modeltranscription, music, and 3D (base plus an addons object, or one rate per texture_quality)
1m_characterstext-to-speech
megapixel · variableper-megapixel images; and rows whose price depends on the input you send (upscalers) — use the estimate below

POST/v1/pricing/estimate

Send the same JSON you would send to the real endpoint, plus type (or endpoint, e.g. "/v1/videos") saying which one — and get the expected total back. If you leave both out, the type is inferred from model when it is unambiguous.

Request

curl https://videorouter.sh/v1/pricing/estimate \
  -H "Authorization: Bearer $VIDEOROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type": "video", "model": "fal/seedance-2.0", "duration_secs": 8, "resolution": "720p"}'

Example response

{
  "object": "pricing.estimate",
  "type": "video",
  "model": "fal/seedance-2.0",
  "currency": "USD",
  "estimated_cost_usd": 2.48788,
  "max_cost_usd": 2.48788,
  "breakdown": { "subtotal_usd": 2.4272, "platform_fee_usd": 0.06068, "platform_fee_rate": 0.025 },
  "pricing": {
    "currency": "USD",
    "unit": "second",
    "rates": { "480p": 0.1345, "720p": 0.3034, "1080p": 0.682, "4k": 1.5552 },
    "platform_fee_rate": 0.025
  },
  "assumptions": { "duration_secs": 8.0, "resolution": "720p", "aspect_ratio": "16:9" },
  "notes": []
}
FieldMeaning
estimated_cost_usdWhat the request is expected to cost, platform fee included — the price on the cheapest host that will serve it. null when the price is only known after the call runs (token-billed images, some music models); notes says why.
max_cost_usdThe most automatic failover could reach if cheaper hosts are down. Equal to the estimate when there is nothing pricier to fall back to.
assumptionsEverything the price depended on that the request did not state outright — the resolution tier a default resolved to, the output tokens assumed. Never silent.
notesPlain-English caveats (“billed on the tokens actually used”, “priced at the model's 30s maximum input”).

What to send, per type

typeFields that change the price
chatmessages (sized at ~4 characters per token) or input_tokens; output_tokens or max_tokens (otherwise 4096 is assumed). Billed on real usage afterwards.
videoduration_secs, resolution, aspect_ratio, n, draft, task_type, auto_upscale, input_references / input_video_references (+ reference_video_secs). Editing or upscaling: input_video_url with input_video_secs (upscalers also input_width / input_height).
imagen, size or resolution + aspect_ratio, quality. A model priced per tier (1k, 2k, …) takes the tier as resolution.
lipsync · face_swap · avataraudio_secs (lip sync, avatar), video_secs (face swap), resolution; an avatar can send its script instead of audio_secs.
speech · transcription · embeddingspeech: input (the text); transcription: duration_secs (or minutes); embedding: input or input_tokens.
music · sfx · mesh · live_videomusic / sfx: duration; 3D: the add-on flags (texture_quality, textured, …); live video: max_duration_seconds, speed.

An estimate that cannot be priced honestly (an upscaler without its clip facts, a transcription without a length, auto) is a 400 with code: "cannot_estimate" and a message naming the missing field. An estimate is a quote, not a cap: chat, token-billed and settle-at-cost models are charged on what they actually use.

Chat completions

Endpoint Description
POST /v1/chat/completionsOpenAI-compatible chat completions; model:"auto" routes, a slug pins — streaming, tools, automatic fallback
POST /v1/routerouting decision only — no upstream call, no charge
GET /v1/modelsevery model on every endpoint (chat, images, video, lip sync, face swap, 3D, music, speech, embeddings, live video), each with its type, endpoint and pricing (per-resolution / per-option rates — see Pricing); filter with ?type=chat. Chat rows include the auto pseudo-model and honour your key's allowlist
POST /v1/pricing/estimatewhat one request to any endpoint will cost, before you send it — no upstream call, no charge. See Pricing

Full request/response detail: Models & routing, Streaming, Tool calling. Full parameters & example responses: Chat completions API reference →

Image generation is also reachable here — pass modalities: ["image", "text"] to get a generated image back on message.images, billed the same rate as /v1/images below. See image output in chat completions.

Spoken audio output too — pass modalities: ["audio", "text"] to a gpt-audio model to get a reply back on message.audio. See audio output in chat completions.

Embeddings

A provider passthrough endpoint kept for drop-in SDK compatibility — not part of the chat/routing surface.

Endpoint Description
POST /v1/embeddingsOpenAI-compatible embeddings, billed the same as chat (provider cost + 2.5%)

Full parameters & example responses: Embeddings API reference →

Images

Endpoint Description
POST /v1/imagesunified text-to-image generation and image-to-image editing (pass input_references) — one endpoint for both, billed per image
GET /v1/images/modelslive list of every valid model slug for POST /v1/images — bare ids only, no price/capability breakdown (see /models for that); unbilled

Full guide: image generation → Full parameters & example responses: Images API reference →

Uploads

A helper for any caller — images, video, lip sync, face swap — that has raw file bytes rather than an already-public URL to pass as a reference (input_references, start_image_url, input_video_url, etc.). A base64 data: URI works directly on those fields too and skips this call entirely — use it for small files; use this endpoint when that would blow past a request-body-size limit.

Endpoint Description
POST /v1/uploadsmultipart file upload (image ≤10 MB, audio ≤20 MB, video ≤50 MB); returns a presigned url valid for 30 minutes — stage it, then immediately reference it in the same session's generate call; unbilled, not durable storage

Audio

Endpoint Description
POST /v1/audio/speechtext-to-speech; returns raw audio, billed per input character (per-token for gpt-4o-mini-tts and the Gemini TTS family)
POST /v1/audio/transcriptionsspeech-to-text, billed per minute of real audio duration (per-token for Gemini 3.5 Transcribe)
POST /v1/audio/musictext-to-music (Google Lyria); returns raw audio, billed flat per generated song
GET /v1/audio/music/modelslive list of every valid model slug for POST /v1/audio/music (also GET /v1/audio/sfx/models for POST /v1/audio/sfx); unbilled

Full guide: text-to-speech → · Full guide: speech-to-text → Full parameters & example responses: Audio API reference →

Realtime

Full-duplex voice, one WebSocket for GPT Realtime (OpenAI/Azure), Grok Voice (xAI), Gemini Live (Google), and GPT Live 1 — a ?model= change, not a different endpoint.

Endpoint Description
WS /v1/realtimeopen a WebSocket, pick a model with ?model=, exchange that model's own event frames — billed per token (GPT Realtime/Gemini Live) or per session-minute (Grok Voice, GPT Realtime Translate/Whisper, GPT Live 1)

Full guide: Realtime guide → Full parameters & example responses: Realtime API reference →

Video

Endpoint Description
POST /v1/videossubmit a video generation job — text-to-video, or image-to-video (pass start_image_url)/reference-to-video (pass input_references/input_video_references/input_audio_references) on supporting models; async, returns a video id immediately; billed per requested second at creation time
GET /v1/videos/modelslive list of every valid model slug for POST /v1/videos — bare ids only, no price/capability breakdown (see /models for that); unbilled
GET /v1/videos/{id}poll status; the finished video URL is included once status is completed

Full guide: video generation → Full parameters & example responses: Video API reference → — also see Motion control → for Kling v3.0 Motion Control's character-image + reference-motion-video shape.

Lip sync

Endpoint Description
POST /v1/lipsynca SEPARATE endpoint from /v1/videos — re-sync a face to a driving audio track, either animating a still (pass image_url + audio_url) or dubbing an existing clip's mouth to new speech (pass video_url + audio_url); async, returns a job id immediately; billed once at creation time from the driving audio's (or the longer of audio/video's) real duration
GET /v1/lipsync/modelslive list of every valid model slug for POST /v1/lipsync; each row says whether it takes an image or a video input alongside audio_url; unbilled
GET /v1/lipsync/{id}poll status — identical job-id scheme and response shape as GET /v1/videos/{id}

Full guide: lip sync → Full parameters & example responses: Lip sync API reference →

Face swap

Endpoint Description
POST /v1/face-swapa SEPARATE endpoint from /v1/videos — replace the face throughout an existing video (video_url) with a source face photo (face_image_url); requires source_face_consent: true; async, returns a job id immediately; billed reserve-then-settle from the provider's own completed-job invoice
GET /v1/face-swap/modelslive list of every valid model slug for POST /v1/face-swap; unbilled
GET /v1/face-swap/{id}poll status — identical job-id scheme and response shape as GET /v1/videos/{id}

Full guide: face swap → Full parameters & example responses: Face swap API reference →

Talking avatars

Endpoint Description
POST /v1/avatars/videosa talking avatar video: a catalog avatar_id or your own image_url (needs source_face_consent), plus script + voice_id or an audio_url. Async; optional webhook_url. Held then settled on the real video length
GET /v1/avatars/videos/{id}poll status — same job object and cost_usd as GET /v1/videos/{id}
GET /v1/avatarscatalog avatars usable as avatar_id; filter ?type=, page with next_token; unbilled
GET /v1/avatars/voicesvoices usable as voice_id; filter ?language=Arabic; unbilled
GET /v1/avatars/modelsvalid model slugs; unbilled

Full guide, parameters and billing: talking avatars →

3D generation

Endpoint Description
POST /v1/meshessubmit a text-to-3d (prompt), image-to-3d (image_url), or multi-image-to-3d (image_urls) job — async, returns a job id immediately; billed flat at creation time from the model + option choice
GET /v1/meshes/modelslive list of every valid model slug for POST /v1/meshes, with the input shape each takes (text, image, multi-image); unbilled
GET /v1/meshes/{id}poll status; the finished mesh (GLB + whichever of FBX/OBJ/USDZ/textures the model produces) is included once status is completed

Full guide: 3D generation → Full parameters & example responses: 3D generation API reference →

Async Jobs

Submit a single request that's OK to wait 1 or 6 hours for a deeper discount — same body as /v1/chat/completions, wrapped.

Endpoint Description
POST /v1/jobssubmit with completion_window: "1h" or "6h"; returns a job id, or push results to a webhook_url
GET /v1/jobs/{id}poll status and read the result once completed

Full guide: Async Jobs → Full parameters & example responses: Async Jobs API reference →

Batch

For bulk work on the full 24-hour window — the OpenAI-compatible Files + Batches shape, so any OpenAI Batch SDK client works with a one-line base_url change.

Endpoint Description
POST /v1/filesupload a JSONL file of requests, purpose "batch"
GET /v1/fileslist files
GET /v1/files/{id}file metadata
GET /v1/files/{id}/contentdownload raw file content — input request lines, or the output/error JSONL once a batch completes
POST /v1/batchescreate a batch from input_file_id, or an inline requests array for small jobs
GET /v1/batcheslist batches
GET /v1/batches/{id}status, progress counts, and output/error file ids once complete
POST /v1/batches/{id}/cancelcancel a batch any time before it completes

Full guide: Batch API → Full parameters & example responses: Batch API reference →

API key management

Create, cap and revoke API keys for your whole workspace, and read its spend by day, key, end user and app — from your own tooling. These routes take a management key (create one at Org admin → API Keys → Management Keys), not a regular API key, and can't call model endpoints.

Endpoint Description
GET /api/v1/keyslist keys, with current usage
POST /api/v1/keyscreate a key with an optional daily / weekly / monthly spend limit
GET /api/v1/keys/{hash}one key's limit and usage
PATCH /api/v1/keys/{hash}rename, change the limit, or revoke
DELETE /api/v1/keys/{hash}revoke a key
GET /api/v1/usagedaily spend by key, end user, app or model

Full parameters & example responses: API key management reference →