curl --request POST \
--url https://api.varg.ai/v2/templates/{id}/render \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"mode": "strict",
"output": "video"
}
'import requests
url = "https://api.varg.ai/v2/templates/{id}/render"
payload = {
"mode": "strict",
"output": "video"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({mode: 'strict', output: 'video'})
};
fetch('https://api.varg.ai/v2/templates/{id}/render', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.varg.ai/v2/templates/{id}/render",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'mode' => 'strict',
'output' => 'video'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.varg.ai/v2/templates/{id}/render"
payload := strings.NewReader("{\n \"mode\": \"strict\",\n \"output\": \"video\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.varg.ai/v2/templates/{id}/render")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"mode\": \"strict\",\n \"output\": \"video\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.varg.ai/v2/templates/{id}/render")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"mode\": \"strict\",\n \"output\": \"video\"\n}"
response = http.request(request)
puts response.read_body{
"id": "job_a1b2c3d4e5f6",
"status": "queued",
"stage": "queued",
"attempts": [
{
"n": 1,
"provider": "byteplus",
"model_key": "byteplus:dreamina-seedance-2-5-260628",
"status": "running",
"reason": "real person in the reference images",
"reason_code": "content_privacy",
"references_uploaded": 123,
"resubmitted": true,
"started_at": "2023-11-07T05:31:56Z",
"ended_at": "2023-11-07T05:31:56Z"
}
],
"tool": "tool_2001a2b3c4d5",
"input": {},
"output": {
"version": "v1",
"outputs": [
{
"url": "<string>",
"file_id": "<string>",
"media_type": "video/mp4",
"size_bytes": 123,
"thumbnail_url": "<string>",
"data": "<unknown>",
"raw": "<unknown>"
}
]
},
"error": "<string>",
"progress_message": "stitching 3/8 (40%)",
"progress": 123,
"progress_metadata": {},
"step_state": {
"current_step": "extend",
"steps": {}
},
"estimated_duration_ms": 123,
"estimated_cost_cents": 123,
"actual_cost_cents": 123,
"pricing": {
"estimated": 123,
"actual": 123,
"billing": "<string>",
"cached": true,
"billed_units": {
"images": 1
},
"pricing_id": "<string>"
},
"provider": "fal",
"provider_model": "fal:flux_schnell",
"provider_status": "<string>",
"provider_job_id": "<string>",
"completed_by_provider_model_id": "<string>",
"last_attempt_provider_model_id": "<string>",
"workspace_id": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"started_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"warnings": [
"<string>"
],
"urls": {
"self": "<string>",
"status": "<string>",
"refresh": "<string>",
"cancel": "<string>",
"retry": "<string>",
"confirm": "<string>",
"rerun": "<string>"
}
}{
"id": "job_a1b2c3d4e5f6",
"status": "queued",
"stage": "queued",
"attempts": [],
"tool": "tool_a1b2c3d4e5f6",
"input": {
"model": "flux_schnell",
"prompt": "a cat astronaut"
},
"output": null,
"error": null,
"progress_message": null,
"progress": null,
"progress_metadata": null,
"step_state": null,
"estimated_duration_ms": 8000,
"estimated_cost_cents": 4,
"actual_cost_cents": null,
"pricing": {
"estimated": 4,
"actual": null,
"billing": "metered",
"cached": null,
"billed_units": null,
"pricing_id": "ppr_abc123"
},
"provider": "fal",
"provider_model": "fal:flux_schnell",
"provider_status": null,
"provider_job_id": null,
"completed_by_provider_model_id": null,
"last_attempt_provider_model_id": null,
"workspace_id": null,
"created_at": "2026-07-01T10:00:00Z",
"started_at": null,
"completed_at": null,
"urls": {
"self": "https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6",
"status": "https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6/status",
"refresh": "https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6/refresh",
"cancel": "https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6/cancel",
"retry": "https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6/retry"
}
}{
"error": {
"code": "invalid_request",
"message": "Request failed validation"
}
}{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key or JWT"
}
}{
"error": {
"code": "insufficient_balance",
"message": "Insufficient balance to run this job",
"details": {
"needed_cents": 120,
"available_cents": 40,
"reserved_cents": 300,
"total_cents": 340,
"held_jobs": 2,
"job_id": "job_a1b2c3d4e5f6"
}
}
}{
"error": {
"code": "not_found",
"message": "Template not found"
}
}{
"error": {
"code": "invalid_request",
"message": "Body validation failed (text: Required)"
}
}{
"error": {
"code": "model_not_found",
"message": "Unknown model: flux-shnell",
"details": "<unknown>"
}
}Render a template to video
Renders the template’s TSX as an ordinary render job, billed and polled
exactly like POST /render. Approved templates, or your own, can be
rendered. The body is optional and carries render options only; the
code always comes from the template.
curl --request POST \
--url https://api.varg.ai/v2/templates/{id}/render \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"mode": "strict",
"output": "video"
}
'import requests
url = "https://api.varg.ai/v2/templates/{id}/render"
payload = {
"mode": "strict",
"output": "video"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({mode: 'strict', output: 'video'})
};
fetch('https://api.varg.ai/v2/templates/{id}/render', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.varg.ai/v2/templates/{id}/render",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'mode' => 'strict',
'output' => 'video'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.varg.ai/v2/templates/{id}/render"
payload := strings.NewReader("{\n \"mode\": \"strict\",\n \"output\": \"video\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.varg.ai/v2/templates/{id}/render")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"mode\": \"strict\",\n \"output\": \"video\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.varg.ai/v2/templates/{id}/render")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"mode\": \"strict\",\n \"output\": \"video\"\n}"
response = http.request(request)
puts response.read_body{
"id": "job_a1b2c3d4e5f6",
"status": "queued",
"stage": "queued",
"attempts": [
{
"n": 1,
"provider": "byteplus",
"model_key": "byteplus:dreamina-seedance-2-5-260628",
"status": "running",
"reason": "real person in the reference images",
"reason_code": "content_privacy",
"references_uploaded": 123,
"resubmitted": true,
"started_at": "2023-11-07T05:31:56Z",
"ended_at": "2023-11-07T05:31:56Z"
}
],
"tool": "tool_2001a2b3c4d5",
"input": {},
"output": {
"version": "v1",
"outputs": [
{
"url": "<string>",
"file_id": "<string>",
"media_type": "video/mp4",
"size_bytes": 123,
"thumbnail_url": "<string>",
"data": "<unknown>",
"raw": "<unknown>"
}
]
},
"error": "<string>",
"progress_message": "stitching 3/8 (40%)",
"progress": 123,
"progress_metadata": {},
"step_state": {
"current_step": "extend",
"steps": {}
},
"estimated_duration_ms": 123,
"estimated_cost_cents": 123,
"actual_cost_cents": 123,
"pricing": {
"estimated": 123,
"actual": 123,
"billing": "<string>",
"cached": true,
"billed_units": {
"images": 1
},
"pricing_id": "<string>"
},
"provider": "fal",
"provider_model": "fal:flux_schnell",
"provider_status": "<string>",
"provider_job_id": "<string>",
"completed_by_provider_model_id": "<string>",
"last_attempt_provider_model_id": "<string>",
"workspace_id": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"started_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"warnings": [
"<string>"
],
"urls": {
"self": "<string>",
"status": "<string>",
"refresh": "<string>",
"cancel": "<string>",
"retry": "<string>",
"confirm": "<string>",
"rerun": "<string>"
}
}{
"id": "job_a1b2c3d4e5f6",
"status": "queued",
"stage": "queued",
"attempts": [],
"tool": "tool_a1b2c3d4e5f6",
"input": {
"model": "flux_schnell",
"prompt": "a cat astronaut"
},
"output": null,
"error": null,
"progress_message": null,
"progress": null,
"progress_metadata": null,
"step_state": null,
"estimated_duration_ms": 8000,
"estimated_cost_cents": 4,
"actual_cost_cents": null,
"pricing": {
"estimated": 4,
"actual": null,
"billing": "metered",
"cached": null,
"billed_units": null,
"pricing_id": "ppr_abc123"
},
"provider": "fal",
"provider_model": "fal:flux_schnell",
"provider_status": null,
"provider_job_id": null,
"completed_by_provider_model_id": null,
"last_attempt_provider_model_id": null,
"workspace_id": null,
"created_at": "2026-07-01T10:00:00Z",
"started_at": null,
"completed_at": null,
"urls": {
"self": "https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6",
"status": "https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6/status",
"refresh": "https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6/refresh",
"cancel": "https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6/cancel",
"retry": "https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6/retry"
}
}{
"error": {
"code": "invalid_request",
"message": "Request failed validation"
}
}{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key or JWT"
}
}{
"error": {
"code": "insufficient_balance",
"message": "Insufficient balance to run this job",
"details": {
"needed_cents": 120,
"available_cents": 40,
"reserved_cents": 300,
"total_cents": 340,
"held_jobs": 2,
"job_id": "job_a1b2c3d4e5f6"
}
}
}{
"error": {
"code": "not_found",
"message": "Template not found"
}
}{
"error": {
"code": "invalid_request",
"message": "Body validation failed (text: Required)"
}
}{
"error": {
"code": "model_not_found",
"message": "Unknown model: flux-shnell",
"details": "<unknown>"
}
}Authorizations
varg API key (varg_...). Get one at app.varg.ai
or run bunx vargai login. App sessions may alternatively send a
Supabase JWT.
Headers
Any unique string. Retrying a request with the same key returns the existing job (HTTP 200) instead of creating and charging a new one (HTTP 202).
Folder id (uuid) or slug. The job's output is filed into this folder
when the job completes. An unknown folder returns 404
workspace_not_found and no job is created. If you cannot set
headers, send a top-level workspace_id field in the JSON body
instead. Not part of the generation input, so it does not affect
caching.
Path Parameters
Template id
Body
Render options. The TSX code always comes from the template and cannot
be supplied here.
Response
Idempotency replay — the existing job for this Idempotency-Key (no new charge).
"job_a1b2c3d4e5f6"
The status only moves forward: queued → running → completed,
failed or cancelled. Everything a running job goes through —
sending to the provider, uploading references, switching to another
provider — is a stage of running; a job never goes back to
queued. (Older API builds also reported submitting; treat it as
running.)
awaiting_confirmation (multi-step pipelines only): the job finished a
step that asks for review and waits for POST /jobs/{id}/confirm. It
is not terminal.
queued, running, awaiting_confirmation, completed, failed, cancelled What the job is doing right now. null once the job is terminal, and
while the job is awaiting_confirmation.
queued— waiting for a slot; no attempt yetsubmitting— being sent to the provideruploading_references— the provider is taking the reference files into its asset library (progress_messageshowsn/m)rendering— the provider accepted the task and is generatingretrying— an attempt failed (the provider refused, failed or rate limited it); the job waits for its next attempt, usually on another provider. Seeattempts.finalizing— the result is being saved and billed
queued, submitting, uploading_references, rendering, retrying, finalizing, null Every provider tried for this job, oldest first. provider / provider_model are the newest one.
Show child attributes
Show child attributes
Internal tool id (e.g. tool_2001a2b3c4d5 for video), not the tool_key. Do not compare it against GET /tools keys.
"tool_2001a2b3c4d5"
The request body as submitted (model, prompt, ...)
Canonical output envelope. Present only when the job is completed.
Show child attributes
Show child attributes
Human-readable failure message. null unless the job failed or was cancelled.
"stitching 3/8 (40%)"
Fraction 0..1
Multi-step pipeline jobs only: the current step and each step's
status, intermediate output and cost. null for ordinary jobs.
Show child attributes
Show child attributes
Structured pricing. 1 credit = 1 cent = $0.01.
Show child attributes
Show child attributes
"fal"
"fal:flux_schnell"
The provider's raw status string
Provider model route that completed the job
Provider model route of the most recent attempt
Folder the outputs are filed into (see X-Workspace-Id)
Present on creation responses when the request was adjusted (for example a resolution fallback)
Lifecycle URLs (present on creation responses)
Show child attributes
Show child attributes
Was this page helpful?