Video Generation

Shotstack Template Update API

Shotstack Template Update — update an existing template name and/or definition (timeline + output). Billed per request.

model: shotstack/template-update
Wholesale key required. This endpoint accepts wholesale keys only. Have access? Get your key on the wholesale dashboard. Not on wholesale yet? Email admin@skillboss.co with your use case — we'll get you provisioned.

Quickstart

Video generation uses /v1/run. The quickstart below shows the synchronous form, but video routinely takes 60–180s and exceeds most client / proxy / serverless timeouts — use opt-in async mode (Async mode section below) in production. Response includes a signed URL to the generated MP4.

bash# VEO generation is synchronous (60–180s per clip). Set timeout >= 300s.
curl --max-time 300 https://api.skillboss.co/v1/run \
  -H "Authorization: Bearer $SKILLBOSS_WHOLESALE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "shotstack/template-update",
    "inputs": {
      "prompt": "A cat walking on the beach at sunset",
      "duration_seconds": 8,
      "aspect_ratio": "16:9",
      "resolution": "1080p"
    }
  }'

Your first 200 response is the fastest way to confirm setup. From there, swap in your real prompt and tune the model-specific parameters listed below.

Authentication

Every request must include your wholesale key. The header name depends on the endpoint — match the SDK you're using:

bashAuthorization: Bearer $SKILLBOSS_WHOLESALE_KEY

Treat the wholesale key like a password — never commit it to source control or ship it in client-side bundles. Rotate from the wholesale dashboard if exposed. Standard (non-wholesale) console keys are rejected at the gateway with 401.

Code examples

Python
pythonimport os, requests

# VEO synchronous generation typically takes 60–180s. Set timeout ≥ 300s.
resp = requests.post(
    "https://api.skillboss.co/v1/run",
    headers={"Authorization": f"Bearer {os.environ['SKILLBOSS_WHOLESALE_KEY']}"},
    json={
        "model": "shotstack/template-update",
        "inputs": {
            "prompt": "A cat walking on the beach at sunset",
            "duration_seconds": 8,
            "aspect_ratio": "16:9",
            "resolution": "1080p",
        },
    },
    timeout=300,
)
data = resp.json()
print(data["outputs"][0]["url"])  # signed URL to the generated video
JavaScript / TypeScript
typescript// VEO synchronous generation typically takes 60–180s.
// AbortController with a 300s timeout handles the long wait safely.
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 300_000);

const resp = await fetch("https://api.skillboss.co/v1/run", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SKILLBOSS_WHOLESALE_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "shotstack/template-update",
    inputs: {
      prompt: "A cat walking on the beach at sunset",
      duration_seconds: 8,
      aspect_ratio: "16:9",
      resolution: "1080p",
    },
  }),
  signal: controller.signal,
});
clearTimeout(timer);
const data = await resp.json();
console.log(data.outputs[0].url);  // signed URL to the generated video

Parameters

Pass the model identifier as a top-level model field, and all generation parameters under an inputs object. The exact set of inputs.* fields depends on the model — see the model card on the wholesale dashboard for advanced options.

NameTypeRequiredDescription
modelstringrequiredModel id. Use shotstack/template-update.
inputs.promptstringrequiredText description of the video to generate. Kept in original language (no translation).
inputs.duration_secondsintegeroptionalClip length in seconds. Default 8. Drives per-second billing — every additional second costs proportionally.
inputs.aspect_ratiostringoptionalAspect ratio. One of 16:9 (default), 9:16, 1:1.
inputs.resolutionstringoptionalOutput resolution, 720p or 1080p. Default 1080p.
inputs.negative_promptstringoptionalWhat to avoid — describes content/styles the generator should NOT produce (e.g. "blurry, low quality, watermark").
inputs.imagestringoptionalOptional first-frame image as base64 (image-to-video mode). Enables animating a static image into a clip.
inputs.last_framestringoptionalOptional last-frame image as base64. Combined with inputs.image, pins both endpoints — useful for seamless loops or precise A→B animation.
inputs.reference_imagesarray<string>optionalArray of reference images (base64) for style/character consistency across the clip. Model-specific support — see individual model notes.
inputs.generate_audiobooleanoptionalGenerate an accompanying soundtrack (default false). Adds zero billable seconds but the upstream may upcharge — check the model's pricing card.
asyncbooleanoptionalStrongly recommended for video — submit returns 202 immediately; poll status or use webhook. Sync calls routinely exceed proxy/serverless timeouts (video gen runs 60–180s).
webhook_urlstringoptionalHTTPS URL we POST the result to on completion. Implies async mode — no need to also set async: true.

Async mode (recommended for production)

Image and video generation can take from tens of seconds to several minutes. The default /v1/run call is synchronous — it holds the HTTP connection until the result is ready, which routinely exceeds client / proxy / serverless function timeouts and pins a worker for the full duration.

Opt into async mode by adding "async": true to the request body (or by supplying webhook_url). Submit returns in <1s with a request_id; you then poll the status URL or receive the result via webhook. This is the standard queue-based pattern used by every async-generation provider — clients designed for that shape work without changes.

1. Submit (returns 202 immediately)
bashcurl -X POST https://api.skillboss.co/v1/run \
  -H "Authorization: Bearer $SKILLBOSS_WHOLESALE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "shotstack/template-update",
    "inputs": { "prompt": "your prompt here" },
    "async": true
  }'

Response:

json{
  "request_id": "c546520207fb4b68b0adce825f9dcf6d",
  "status": "IN_QUEUE",
  "status_url": "https://api.skillboss.co/v1/run/status/c546520207fb4b68b0adce825f9dcf6d",
  "cancel_url": "https://api.skillboss.co/v1/run/cancel/c546520207fb4b68b0adce825f9dcf6d"
}

The same request_id is also returned in the x-request-id response header. A separate x-record-id header carries the internal deduct/audit row id — quote it when reporting an issue so support can find the call in our logs. Day-to-day client code only needs request_id.

2. Poll status (or use webhook — see below)
bashcurl https://api.skillboss.co/v1/run/status/{request_id} \
  -H "Authorization: Bearer $SKILLBOSS_WHOLESALE_KEY"

Status enum — the full lifecycle:

StatusMeaningTerminal?Billed?
IN_QUEUEJob accepted, awaiting worker pickup. Cancellable.nono
IN_PROGRESSWorker has claimed the job; vendor call in flight. Cancel returns 409 from here on.nono
COMPLETEDSuccess. result field contains generated_images / videos URLs.yesyes
FAILEDVendor error or insufficient balance. error field has details.yesno
CANCELLEDClient called the cancel endpoint while IN_QUEUE.yesno

Polling loop: hit the status endpoint every 5–10s; stop the moment you see COMPLETED / FAILED / CANCELLED — those are terminal. Result payload (when COMPLETED) is the same shape as the synchronous response — fetched via the result field. We retain completed results for 7 days, then they expire.

3. Cancel (optional — only effective while IN_QUEUE)
bashcurl -X POST https://api.skillboss.co/v1/run/cancel/{request_id} \
  -H "Authorization: Bearer $SKILLBOSS_WHOLESALE_KEY"

Returns 200 with cancelled: true on success, 200 idempotent no-op if already terminal, 409if the worker has already started the vendor call (the cost is already being incurred upstream and we don't support mid-flight abort), or 404 if the request_id is unknown or not owned by your account.

4. Webhook (alternative to polling)

Add "webhook_url": "https://your-server.com/cb" to the submit body. We POST the result to that URL once the job reaches a terminal state. Payload format:

json// On success (COMPLETED → status "OK")
{
  "request_id": "c546...",
  "status": "OK",
  "payload": { "generated_images": [{ "url": "https://..." }] },
  "error": null
}

// On failure (FAILED → status "ERROR")
{
  "request_id": "c546...",
  "status": "ERROR",
  "payload": null,
  "error": "<error description>"
}
Two different status fields — by design. The status endpoint returns the 5-value lifecycle enum (IN_QUEUE / IN_PROGRESS / COMPLETED / FAILED / CANCELLED). The webhook body uses the 2-value 2-value success enum (OK / ERROR) because webhooks fire only on terminal states and a binary outcome is all the receiver needs. Webhooks are not sent on CANCELLED (you initiated it, no notification needed).

Webhook security: the URL must be HTTPS and resolve to a public IP (loopback / RFC1918 / link-local / metadata addresses are rejected at submit time as an SSRF guard). Delivery is best-effort with one retry; have your endpoint be idempotent on request_id.

Recommendation: Video generation routinely exceeds 60s — always use async mode in production. Sync is fine for one-off testing. Billing rule: you're charged only on COMPLETED FAILED and CANCELLED jobs incur no charge.

Endpoint

MethodPOST
URLhttps://api.skillboss.co/v1/run
Auth headerAuthorization: Bearer $SKILLBOSS_WHOLESALE_KEY
Content-Typeapplication/json
StreamingNo SSE streaming, but supports async submit (set `"async": true`) which is the recommended path for long jobs — see the Async mode section.

Errors

The API uses standard HTTP status codes:

200OKRequest succeeded.
400Bad RequestInvalid model, missing required field, or malformed JSON.
401UnauthorizedMissing or invalid wholesale key. Non-wholesale console keys are rejected here.
402Insufficient CreditsWholesale balance too low — top up on the wholesale dashboard.
429Rate LimitedToo many requests. Back off with exponential delay.
500Server ErrorTransient upstream issue. Safe to retry.
503Upstream UnavailableDiscount pool capacity issue (lite tier). Retry or fall back to standard tier.

Pricing

Wholesale pricing is your account-specific discount × vendor list price. Discount rate depends on your contract — see the live numbers on the wholesale dashboard. The dashboard shows your current cost per 1M tokens (or per image / per second) for every model.

No platform markup on standard token billing. Volume tiers + monthly caps are configurable per key.