> ## Documentation Index
> Fetch the complete documentation index at: https://docs.varg.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 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.




## OpenAPI

````yaml /openapi.yaml post /templates/{id}/render
openapi: 3.1.0
info:
  title: varg API
  version: 2.0.0
  description: |
    Unified REST API for AI media generation at `api.varg.ai/v2`.

    One API key, ~80 models across 8 providers, async jobs, stable output URLs
    on `s3.varg.ai`, files with lineage, and transparent credit billing
    (1 credit = 1 cent = $0.01).

    **The async job pattern:** every generation request returns `202 Accepted`
    with a job object (`status: queued`). Poll `GET /jobs/{id}` until the job
    reaches a terminal status (`completed`, `failed`, or `cancelled`), then read
    `output.outputs[0].url`. Alternatively, set `options.webhook_url` in the
    request to receive an HMAC-signed callback when the job finishes.
servers:
  - url: https://api.varg.ai/v2
security:
  - bearerAuth: []
tags:
  - name: Generation
    description: >-
      Create generation jobs (image, video, speech, music, transcription,
      ffmpeg, render, pipeline)
  - name: Tools
    description: Discover tools, their schemas, and call any tool generically
  - name: Jobs
    description: Poll and manage job lifecycle
  - name: Files
    description: Upload, import, probe, and manage files
  - name: Folders
    description: Group files into folders and file generated output automatically
  - name: Lineage
    description: Resolve which job produced a file
  - name: Presets
    description: Browse and apply reusable parameter values — voices, styles
  - name: Templates
    description: Browse, publish, use and render community templates
  - name: Pricing
    description: Estimate costs and browse the price catalog
  - name: Billing
    description: Balance, usage, and transaction history
  - name: Analytics
    description: >-
      Spend, runs and files over time — summaries, time series, breakdowns,
      activity
  - name: Account
    description: Identity and API key management
paths:
  /templates/{id}/render:
    parameters:
      - name: id
        in: path
        required: true
        description: Template id
        schema:
          type: string
          format: uuid
    post:
      tags:
        - Templates
      summary: Render a template to video
      description: |
        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.
      operationId: renderTemplate
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/WorkspaceId'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TemplateRenderRequest'
            example:
              mode: strict
              output: video
      responses:
        '200':
          $ref: '#/components/responses/JobReplay'
        '202':
          $ref: '#/components/responses/JobAccepted'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: invalid_request
                  message: Request failed validation
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientBalance'
        '404':
          description: Template or document not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: not_found
                  message: Template not found
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      schema:
        type: string
      description: |
        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).
    WorkspaceId:
      name: X-Workspace-Id
      in: header
      required: false
      schema:
        type: string
      description: |
        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.
  schemas:
    TemplateRenderRequest:
      type: object
      description: |
        Render options. The TSX `code` always comes from the template and cannot
        be supplied here.
      properties:
        mode:
          type: string
          enum:
            - strict
            - preview
          description: >-
            `strict` (default) fails on errors; `preview` substitutes
            placeholders
        output:
          type: string
          enum:
            - video
            - frames
        verbose:
          type: boolean
        options:
          $ref: '#/components/schemas/JobOptions'
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: model_not_found
            message:
              type: string
              example: 'Unknown model: flux-shnell'
            details: {}
    JobOptions:
      type: object
      description: Cross-cutting job options
      properties:
        webhook_url:
          type: string
          format: uri
          description: |
            HTTPS URL to receive the job snapshot when the job reaches a
            terminal status. Signed with an `X-Varg-Signature` HMAC header.
            8 retries with exponential backoff.
        cache:
          type: boolean
          default: true
          description: >-
            Set `false` to force a fresh generation (skips the result cache
            lookup and store)
      additionalProperties: true
    Job:
      type: object
      required:
        - id
        - status
        - stage
        - attempts
        - tool
        - input
        - output
        - error
        - progress_message
        - progress
        - progress_metadata
        - step_state
        - estimated_duration_ms
        - estimated_cost_cents
        - actual_cost_cents
        - pricing
        - provider
        - provider_model
        - provider_status
        - provider_job_id
        - completed_by_provider_model_id
        - last_attempt_provider_model_id
        - workspace_id
        - created_at
        - started_at
        - completed_at
      properties:
        id:
          type: string
          example: job_a1b2c3d4e5f6
        status:
          $ref: '#/components/schemas/JobStatus'
        stage:
          $ref: '#/components/schemas/JobStage'
        attempts:
          type: array
          description: >-
            Every provider tried for this job, oldest first. `provider` /
            `provider_model` are the newest one.
          items:
            $ref: '#/components/schemas/JobAttempt'
        tool:
          type: string
          description: >-
            Internal tool id (e.g. `tool_2001a2b3c4d5` for video), not the
            `tool_key`. Do not compare it against `GET /tools` keys.
          example: tool_2001a2b3c4d5
        input:
          type: object
          description: The request body as submitted (model, prompt, ...)
        output:
          oneOf:
            - $ref: '#/components/schemas/JobOutput'
            - type: 'null'
        error:
          type:
            - string
            - 'null'
          description: >-
            Human-readable failure message. `null` unless the job failed or was
            cancelled.
        progress_message:
          type:
            - string
            - 'null'
          example: stitching 3/8 (40%)
        progress:
          type:
            - number
            - 'null'
          description: Fraction 0..1
        progress_metadata:
          type:
            - object
            - 'null'
        step_state:
          type:
            - object
            - 'null'
          description: |
            Multi-step pipeline jobs only: the current step and each step's
            status, intermediate output and cost. `null` for ordinary jobs.
          properties:
            current_step:
              type:
                - string
                - 'null'
              example: extend
            steps:
              type: object
              additionalProperties:
                type: object
                properties:
                  status:
                    type: string
                  output_url:
                    type:
                      - string
                      - 'null'
                  cost:
                    type:
                      - integer
                      - 'null'
                    description: Cents
        estimated_duration_ms:
          type:
            - integer
            - 'null'
        estimated_cost_cents:
          type:
            - integer
            - 'null'
        actual_cost_cents:
          type:
            - integer
            - 'null'
        pricing:
          $ref: '#/components/schemas/JobPricing'
        provider:
          type:
            - string
            - 'null'
          example: fal
        provider_model:
          type:
            - string
            - 'null'
          example: fal:flux_schnell
        provider_status:
          type:
            - string
            - 'null'
          description: The provider's raw status string
        provider_job_id:
          type:
            - string
            - 'null'
        completed_by_provider_model_id:
          type:
            - string
            - 'null'
          description: Provider model route that completed the job
        last_attempt_provider_model_id:
          type:
            - string
            - 'null'
          description: Provider model route of the most recent attempt
        workspace_id:
          type:
            - string
            - 'null'
          description: Folder the outputs are filed into (see `X-Workspace-Id`)
        created_at:
          type: string
          format: date-time
        started_at:
          type:
            - string
            - 'null'
          format: date-time
        completed_at:
          type:
            - string
            - 'null'
          format: date-time
        warnings:
          type: array
          description: >-
            Present on creation responses when the request was adjusted (for
            example a resolution fallback)
          items:
            type: string
        urls:
          type: object
          description: Lifecycle URLs (present on creation responses)
          properties:
            self:
              type: string
            status:
              type: string
            refresh:
              type: string
            cancel:
              type: string
            retry:
              type: string
            confirm:
              type: string
            rerun:
              type: string
    JobStatus:
      type: string
      enum:
        - queued
        - running
        - awaiting_confirmation
        - completed
        - failed
        - cancelled
      description: |
        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.
    JobStage:
      type:
        - string
        - 'null'
      enum:
        - queued
        - submitting
        - uploading_references
        - rendering
        - retrying
        - finalizing
        - null
      description: |
        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 yet
        - `submitting` — being sent to the provider
        - `uploading_references` — the provider is taking the reference files
          into its asset library (`progress_message` shows `n/m`)
        - `rendering` — the provider accepted the task and is generating
        - `retrying` — an attempt failed (the provider refused, failed or rate
          limited it); the job waits for its next attempt, usually on another
          provider. See `attempts`.
        - `finalizing` — the result is being saved and billed
    JobAttempt:
      type: object
      description: |
        One provider tried for this job. A job can have several — when a
        provider refuses or fails, the job moves on to the next one. Reference
        uploads and a resubmit at the same provider are part of one attempt.
      properties:
        'n':
          type: integer
          example: 1
        provider:
          type:
            - string
            - 'null'
          example: byteplus
        model_key:
          type:
            - string
            - 'null'
          example: byteplus:dreamina-seedance-2-5-260628
        status:
          type: string
          enum:
            - running
            - completed
            - failed
            - cancelled
        reason:
          type: string
          description: Why a failed attempt failed, in a few words
          example: real person in the reference images
        reason_code:
          type: string
          enum:
            - content_privacy
            - content_policy
            - quota
            - rate_limit
            - provider_error
            - timeout
            - expired
            - prompt_too_long
        references_uploaded:
          type: integer
          description: Reference files taken into the provider's asset library
        resubmitted:
          type: boolean
          description: >-
            The provider refused the first submit and got the task again (with
            uploaded references)
        started_at:
          type:
            - string
            - 'null'
          format: date-time
        ended_at:
          type:
            - string
            - 'null'
          format: date-time
    JobOutput:
      type: object
      description: Canonical output envelope. Present only when the job is completed.
      properties:
        version:
          type: string
          const: v1
        outputs:
          type: array
          items:
            type: object
            properties:
              url:
                type: string
                description: Stable varg-hosted URL (s3.varg.ai)
              file_id:
                type: string
                description: The file record for this output — use with /files and /lineage
              media_type:
                type: string
                example: video/mp4
              size_bytes:
                type: integer
              thumbnail_url:
                type:
                  - string
                  - 'null'
              data:
                description: >-
                  Inline structured result (no file). Used by `video/analyze`
                  and transcription.
              raw:
                description: Provider-specific extra data
    JobPricing:
      type: object
      description: Structured pricing. 1 credit = 1 cent = $0.01.
      properties:
        estimated:
          type:
            - integer
            - 'null'
          description: Reserved at creation (cents)
        actual:
          type:
            - integer
            - 'null'
          description: Charged at completion (cents). 0 for cache hits.
        billing:
          type:
            - string
            - 'null'
        cached:
          type:
            - boolean
            - 'null'
          description: true when the result came from cache (actual = 0)
        billed_units:
          type:
            - object
            - 'null'
          example:
            images: 1
        pricing_id:
          type:
            - string
            - 'null'
          description: The pinned pricing rule this job was charged under
  responses:
    JobReplay:
      description: >-
        Idempotency replay — the existing job for this `Idempotency-Key` (no new
        charge).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Job'
    JobAccepted:
      description: Job created and queued. Poll `urls.self` until terminal.
      headers:
        X-RateLimit-Limit:
          schema:
            type: string
        X-RateLimit-Remaining:
          schema:
            type: string
        X-RateLimit-Reset:
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Job'
          examples:
            queued:
              summary: Queued job
              value:
                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
    Unauthorized:
      description: Missing or invalid API key / JWT
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            unauthorized:
              value:
                error:
                  code: unauthorized
                  message: Invalid or missing API key or JWT
    InsufficientBalance:
      description: >-
        Account balance too low to reserve the estimated cost. `error.details`
        shows the shortfall and how much is held by running jobs.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            insufficient:
              value:
                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
    ValidationError:
      description: Request body failed validation
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            invalid:
              value:
                error:
                  code: invalid_request
                  message: 'Body validation failed (text: Required)'
    RateLimited:
      description: Rate limit exceeded (sliding window per API key)
      headers:
        Retry-After:
          schema:
            type: string
        X-RateLimit-Limit:
          schema:
            type: string
        X-RateLimit-Remaining:
          schema:
            type: string
        X-RateLimit-Reset:
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: |
        varg API key (`varg_...`). Get one at [app.varg.ai](https://app.varg.ai)
        or run `bunx vargai login`. App sessions may alternatively send a
        Supabase JWT.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.