Skip to main content
The varg API is a single REST API for AI media generation across providers such as fal, Google, OpenAI, ElevenLabs, Black Forest Labs, HeyGen, Higgsfield, PiAPI, Together, Groq and Rendi. One API key, 120+ models, async jobs, stable output URLs at s3.varg.ai, and transparent credit billing.

Base URL

The OpenAPI 3.1 spec is at https://api.varg.ai/v2/openapi.json. Use it to generate a typed client or import the API into Postman. See OpenAPI spec.

Authentication

All requests (except GET /pricing) require a varg API key:
Get your API key at app.varg.ai or run bunx vargai login. See Authentication for details.

Core concepts

The API vocabulary has three levels: Tools: image, video, speech, music, transcription, ffmpeg, render, pipeline. Discover them at runtime via GET /v2/tools. Some parameters — vendor voice ids, style ids, avatar ids — are values you cannot guess and that silently fail when placed at the wrong path. The Presets catalogue (/v2/presets) browses, filters, and safely applies those values for you.

Quick start

Every generation is an async job: create it, poll until terminal, read the output URL.
Creation responses include ready-made lifecycle URLs:

Job lifecycle

The status only moves forward. What a running job is doing right now is its stage: When a provider refuses a request — a real person in the references, a content policy, a full queue — varg tries the next provider for the same model instead of failing the job. Every provider tried is listed in attempts, with a short reason and a reason_code for the ones that failed:
reason_code is one of content_privacy, content_policy, quota, rate_limit, provider_error, timeout, expired, prompt_too_long. Poll GET /v2/jobs/{id} (full view) or GET /v2/jobs/{id}/status (lightweight: status, stage, progress 0..1 and progress_message). Treat queued and running as in progress. A stuck job is guaranteed to reach a terminal status: every attempt has a time limit, and a submit interrupted by a restart is retried automatically.
Instead of polling, set options.webhook_url in your request. When the job finishes, varg POSTs the job snapshot (including stage and attempts) to your URL, signed with X-Varg-Signature: v1=<hmac-sha256>, with 8 retries and exponential backoff.

Request format

All generation endpoints take a flat JSON body: model plus tool-specific fields at the top level.
Media inputs are always passed by URL — upload local files first via POST /v2/files to get a stable varg URL.

Model resolution

Most requests should just use the model name. Pass a canonical varg name (seedance_2, kling_v3, flux_schnell) and varg auto-routes by priority and input shape — if your request includes files, routes that map files are preferred; the first route whose schema accepts your input wins.
For advanced control, two more address forms exist:
  • Provider prefix — same auto-routing, restricted to routes on that provider.
  • Exact model_key — pins one specific route. model_key values are a permanent public contract and safe to hardcode.
Every route’s model_key is listed in GET /v2/models. Two guarantees:
  1. No silent substitution. varg only picks which route serves the model you named — never a different model family.
  2. Transparent routing. The job records which provider model actually ran (provider, provider_model fields), and POST /v2/estimate returns the resolved_model_key before you submit.
Within a model, input shape can select a variant automatically: sending an image in files to kling_v3 routes to its image-to-video endpoint. Same family, same pricing rules. Model ids use underscores (kling_v3, flux_schnell). Dashed spellings (kling-v3) are accepted and normalized automatically. Browse all models and prices at GET /v2/pricing (public, no auth).

Model catalog

GET /v2/models (public, no auth) returns the full catalog: every model with its routes, pricing, and operational hints. Filter by tool with ?tool=video.
Each route’s model_key can be used directly in the model field to pin that route.

Discovering schemas at runtime

Agents and dynamic clients can discover the full API without reading docs. The discovery reads are public — no key needed (with a key, they also list your team’s private pipelines):
Every model’s schema is also published as a readable Markdown spec at https://varg.ai/models/{model}.md — see Model specs for agents.

Pricing and billing

1 credit = 1 cent = $0.01. The billing flow:
  1. Reserve — at job creation, the estimated cost is held from your balance (402 if insufficient).
  2. Commit — on completion, the hold is charged and a usage record written.
  3. Release — on failure, the hold is returned (most models; some bill partial work).
Each job carries its pricing in the response: pricing.estimated, pricing.actual, pricing.billed_units (e.g. {"seconds": 6}), and a pricing_id that pins the price rule the job was charged under — mid-flight price changes never affect running jobs.

Caching

Results are cached by canonical input. Repeating an identical request returns a completed job instantly with actual_cost_cents: 0 and pricing.cached: true — cache hits are free.

Idempotency

Pass an Idempotency-Key header on any job-creating POST to make retries safe:
The first request creates the job (202). Retrying with the same key returns the same job (200) — no duplicate charge, no duplicate generation.

Files and lineage

Outputs are mirrored to varg storage and served from stable s3.varg.ai URLs. Every output gets a file record with an AI-generated title, a thumbnail, and lineage back to the job that created it:
Send X-Content-Hash: sha256:<hex> on upload for content deduplication, or pre-check with GET /v2/files/check?hash=.

Error format

All errors use one envelope:
model_not_found errors include suggestions in details: did_you_mean lists close model names, and models_url points to /v2/models for the full catalog.

Rate limits

Rate limiting is a sliding window per API key. Every job-creation response carries:
On 429, wait for Retry-After seconds and retry (ideally with the same Idempotency-Key).

Migrating from v1

The v1 gateway (api.varg.ai/v1) is frozen. Key differences in v2: