Second StudioDocs llms.txtRequest access

REST API reference

Base URL: https://frugal-anteater-681.convex.site · All bodies are JSON · Authenticate every /v1 request with

Authorization: Bearer ss_live_...

Conventions

{ "error": { "code": "insufficient_credits", "message": "this costs 5 credit(s); balance is 2. …" } }
Status Codes
400 missing_field, invalid_field, invalid_json, invalid_id, invalid_url, invalid_pack, unknown_account, platform_mismatch
401 unauthorized — missing, invalid or revoked key
402 insufficient_credits
403 key_pending_approval, forbidden (needs an admin key), fetch_disabled
404 not_found
409 conflict, not_pending
429 rate_limited, too_many_jobs
502 / 503 zernio_error, not_configured

Account

GET /v1/me

{ "orgId": "js7…", "keyScope": "agent", "name": "Acme", "credits": 93, "autoPublish": false,
  "allowHostedFetch": false, "maxConcurrentJobs": 4, "apiVersion": "2026-10-08" }

`apiVersion` changes whenever the endpoint or MCP tool surface changes; MCP clients that cache the tool
list should reconnect when it does.

Assets

An asset is any file in your account: an uploaded clip or song, a reference, a finished edit, a recording. Uploading takes three calls, so large files go straight to storage instead of through the API.

POST /v1/assets/upload-url

Returns a one-time URL: { "uploadUrl": "https://…" }. Send the raw bytes to it:

curl -X POST "$uploadUrl" -H "Content-Type: video/mp4" --data-binary @clip.mp4
# → { "storageId": "kg2…" }

POST /v1/assets

Register the upload: { "storageId": "kg2…", "filename": "clip.mp4" } → 201 with the asset:

{ "id": "j97…", "kind": "video", "role": "upload", "filename": "clip.mp4", "contentType": "video/mp4",
  "size": 991017, "url": "https://…", "source": null, "jobId": null, "createdAt": 1791328110667 }

kind is video, audio, image, json or other, from the uploaded Content-Type.

GET /v1/assets · GET /v1/assets/{id} · DELETE /v1/assets/{id}

List the 100 most recent, read one (with a download url), or delete one and its file permanently.

Styles

POST /v1/styles — analyze a reference (2 credits)

{ "assetId": "j97…", "semantic": true }

semantic (default true) adds vision-model shot roles, descriptions and caption style on top of the measured analysis. When the job succeeds, result.styleId is the new style and result summarizes it:

{ "styleId": "jn7…", "aspect": "9:16", "duration": 17.8, "shot_count": 7, "bpm": 99.4,
  "cuts_on_beat_ratio": 0.71, "semantic": true, "summary": "Fast result-first hook, …",
  "pacing": { "shot_count": 7, "mean_shot": 2.54, "median_shot": 0.73, "cuts_per_minute": 20.3, … } }

GET /v1/styles · GET /v1/styles/{id}

GET /v1/styles/{id} includes the full spec — see Styles and edits.

Edits

POST /v1/edits — cut your clips to a style (5 credits)

Field Type
styleId string Required.
clipAssetIds string[] Required. 1–30 of your video assets.
musicAssetId string An audio asset. Cuts snap to its beat when the style is beat-driven.
musicStart number Seconds into the track to start (default 0).
captions string[] Caption lines in order (up to 40, 200 chars each). The first is the hook.
brief string What the video is about. Used to write captions when captions is omitted.
aspect string 9:16, 4:5, 1:1, 4:3 or 16:9. Defaults to the reference's.
duration number Target length, 3–180 s. Defaults to the reference's.
keepClipAudio boolean Mix your clips' own sound. Default: on without music, off (ducked) with music.
semantic boolean Use the vision model to pick the best moments (default true).

The finished job's outputs contain the edit (mp4) and the plan (JSON: which clip and in-point filled each shot). result.qa is the automatic quality report; result.notes explains decisions such as beat snapping and layout.

Generation

See Generating images, characters and video for every option.

Endpoint
POST /v1/characters { name, description, referenceAssetIds?, aspect?, resolution? } → a stored character whose sheet is generated; poll until ready
GET /v1/characters · GET /v1/characters/{id} · DELETE /v1/characters/{id} List, read (with sheetUrl), delete
POST /v1/images { kind, brief, characterIds?, references?, aspect?, resolution?, n?, estimate? } → job; outputs are images
POST /v1/videos { brief, characterIds?, duration?, resolution?, aspect?, imageAssetId?, referenceAssetIds?, referenceVideoAssetIds?, referenceAudioAssetIds?, estimate? } → job, or a price with estimate: true
POST /v1/voice { text, voice?, direction?, stability?, perform? } → job; output is audio
POST /v1/lipsync { videoAssetId, audioAssetId, pro? } → job

Generation results include notes on choices made. The production craft behind them stays server-side.

Models, skills, swaps, edits

GET /v1/models The image, video and swap models you can pick, with what each supports.
POST /v1/skills · GET /v1/skills · GET/POST/DELETE /v1/skills/{id} Your own versioned image recipes; skillIds on images, characters, edits and brand kits.
POST /v1/images/edit Masked edit of a real photo: only the mask is painted, the rest is untouched.
POST /v1/swaps object_swap / motion_transfer: keep the footage, change the subject.
POST /v1/videos/{id}/finalize · draft: true Cheap 480p drafts, then the keeper at 720p/1080p.
POST /v1/jobs/{id}/cancel Cancel with a full refund.
POST /v1/upscales Lanczos resample to 2160p.
POST /v1/dialogue · GET /v1/voices · POST /v1/voices/clone Multi-speaker tracks with per-line timings; your own ElevenLabs voices and clones when your key is connected.
GET /v1/providers · POST/DELETE /v1/providers/{higgsfield\|elevenlabs} Connect your own provider keys (admin, where enabled).
POST /v1/brands/analyze A suggested brand kit from your boards.

See Generation.

Explainer videos

Brand kits, scripts and renders have their own page: Explainer videos.

POST /v1/brands · GET /v1/brands · GET /v1/brands/{id} · POST /v1/brands/{id} · DELETE /v1/brands/{id} Brand kits: name, description, tone, colors, font, logo, product images with descriptions, music. Free.
POST /v1/scripts { brandId, brief, duration?, aspect?, language? } → job; result.script is an editable scene list. 2 credits.
POST /v1/explainers { brandId, brief | script, aspect?, captions?, voiceover?, musicAssetId? } → job; the video plus the rendered script. 12 credits.

Recordings

POST /v1/recordings — record a public web app (3 credits)

{ "url": "https://example.com", "viewport": "mobile",
  "steps": [ { "type": "hold", "seconds": 2 }, { "type": "click", "selector": "text=Pricing" },
             { "type": "scroll", "pixels": 900 }, { "type": "hold", "seconds": 2 } ] }

See Recording for every step type. Output: a recording asset (mp4) and result.marks, the timestamp of every step for cutting.

Fetching

POST /v1/fetch — a reference from a social URL (1 credit)

{ "url": "https://www.tiktok.com/@…/video/…", "start": 3, "end": 18 }. start/end (seconds, optional) keep only that section — handy for a 4–30 s reference clip for POST /v1/videos. Hosted fetching is a per-account setting: if it is off you get 403 fetch_disabled — ask us to enable it (POST /v1/reports works) and confirm you have the rights to the clips, or fetch on your own machine with the local MCP server and upload instead. Output: a fetched asset with source attribution (and the trim applied).

Jobs

GET /v1/jobs/{id} · GET /v1/jobs

{ "id": "jd7…", "kind": "replicate", "status": "succeeded", "progress": "done", "error": null,
  "result": { … }, "creditsCharged": 5, "refunded": false, "attempts": 1,
  "outputs": [ { "assetId": "j95…", "role": "edit", "kind": "video", "filename": "edit.mp4", "url": "https://…" } ],
  "createdAt": 1791469255706, "startedAt": 1791469256012, "finishedAt": 1791469281420 }

status: queued → running → succeeded | failed. A job with no word from the worker for three hours is marked failed and refunded.

Social accounts and posts

See Posting for the approval model.

Endpoint
GET /v1/social/accounts Connected accounts: { id, platform, username, displayName, status }
POST /v1/social/connect { "platform": "tiktok", "redirectUrl": "https://…" } → { "authUrl": "…" }
POST /v1/posts Draft a post (1 credit). See below.
GET /v1/posts Posts and their status
POST /v1/posts/{id}/approve Admin key. Publish or schedule a pending post.
POST /v1/posts/{id}/reject Admin key. Reject it; its credit is refunded.

POST /v1/posts:

{ "assetId": "j95…", "caption": "Dinner in one search #recipes",
  "targets": [ { "platform": "tiktok", "accountId": "6a62…" } ],
  "scheduledFor": "2026-10-12T18:00:00-04:00" }

Give scheduledFor (ISO 8601 with an offset, or with timezone) or "publishNow": true. Post statuses: pending_approval → approved → scheduled | published | failed, or rejected.

Team

Members, roles, keys, per-person credit caps and the shared library have their own page: Team.

GET /v1/members · POST /v1/members · GET/POST/DELETE /v1/members/{id} · POST /v1/members/{id}/keys People on the account, each with their own key and role.
GET /v1/keys · DELETE /v1/keys/{id} Every live key and whose it is.
GET /v1/library Brand kits, characters, styles, finished videos and uploads the team can reuse, with createdBy.

Reporting problems

Found a bug, want a feature, or have a question? File it through the API — agents can do this on their own when something goes wrong. Reports are free.

POST /v1/reports

Field Type
title string Required. Up to 200 characters.
description string Required. What happened, what you expected, steps to reproduce. Up to 10,000 characters.
kind string bug (default), feature or question.
severity string low, normal (default), high or blocking.
jobId string The job involved. Its status, error, inputs and QA report are attached automatically.
{ "kind": "bug", "severity": "high", "jobId": "jd7…",
  "title": "Captions cut off on 4:5 edits",
  "description": "The second caption line is clipped at the top. Expected it inside the frame." }

Returns 201 with the report. GET /v1/reports and GET /v1/reports/{id} show each report's status — open, acknowledged, fixed, wont_fix or closed — and the team's response.

Credits

Endpoint
GET /v1/billing { credits, costs, packs }
GET /v1/billing/ledger Every charge, refund and purchase, newest first

Agents: this page is also available as Markdown; the whole reference is in llms-full.txt.