{"openapi":"3.1.0","info":{"title":"Monkeygun API","version":"3.1.0","description":"Data in, videos out. Every tool the Monkeygun studio has, over HTTP. Quote before you spend; paid calls return `charged`. 1 credit = $0.01. Docs: https://monkey-gun.gitbook.io/monkeygun · MCP: npx @monkeygun/mcp"},"servers":[{"url":"https://api.monkeygun.com/v1"}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"API key (mk_live_…) from Settings → Developer"}},"schemas":{"VideoStatus":{"type":"string","enum":["draft","scripted","rendering","rendered","error"],"description":"draft → scripted (script, voice, images exist) → rendering → rendered, or error (see lastError)"},"Media":{"type":"object","description":"Keyed, absolute links — usable without a session. Present on every video response, on jobs (as `media`) and on webhooks.","properties":{"public":{"type":"boolean"},"mediaKey":{"type":"string"},"url":{"type":"string","description":"Current cut (mutable, revalidates)"},"renderUrl":{"type":"string","description":"This version's file (immutable, cache forever); null until rendered"},"thumbnail":{"type":"string"},"webUrl":{"type":"string","nullable":true,"description":"Light 720p copy for feeds and autoplay (~2–3 MB); null for videos rendered before Sep 27 2026"},"watchUrl":{"type":"string","description":"Hosted share page"}}},"Video":{"type":"object","properties":{"videoId":{"type":"string"},"title":{"type":"string"},"status":{"$ref":"#/components/schemas/VideoStatus"},"duration":{"type":"number"},"format":{"type":"string"},"language":{"type":"string"},"version":{"type":"integer"},"scenes":{"type":"array","items":{"type":"object","properties":{"n":{"type":"integer"},"type":{"type":"string"},"text":{"type":"string"},"duration":{"type":"number"},"media":{"type":"string","nullable":true}}}},"captions":{"type":"boolean"},"presenter":{"type":"boolean"},"music":{"type":"boolean"},"sourcePackId":{"type":"string","nullable":true},"video":{"type":"string","description":"Relative file path (needs a session or ?k=mediaKey). Prefer url / renderUrl."},"lastError":{"type":"string","nullable":true},"cost":{"type":"object","nullable":true},"charged":{"type":"number"},"external_id":{"type":"string","nullable":true},"public":{"type":"boolean"},"mediaKey":{"type":"string"},"url":{"type":"string"},"renderUrl":{"type":"string","nullable":true},"thumbnail":{"type":"string","nullable":true},"watchUrl":{"type":"string"}}},"Job":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["creating","rendering","done","failed"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"videoId":{"type":"string","nullable":true},"videoStatus":{"$ref":"#/components/schemas/VideoStatus"},"media":{"$ref":"#/components/schemas/Media"},"result":{"type":"object","nullable":true},"error":{"type":"string","nullable":true}}},"WebhookEvent":{"type":"object","description":"POST to your URL with X-Monkeygun-Event and X-Monkeygun-Signature: sha256=HMAC-SHA256(secret, raw body). One attempt, 15 s timeout, no retry — poll GET /videos/{id} as the fallback.","properties":{"id":{"type":"string"},"event":{"type":"string","enum":["video.created","video.rendered","video.render_failed","episode.ready","episode.published","series.error"]},"createdAt":{"type":"string"},"data":{"type":"object","properties":{"videoId":{"type":"string"},"external_id":{"type":"string","nullable":true},"externalUserId":{"type":"string","nullable":true,"description":"Embed sessions: your user id"},"channelId":{"type":"string","nullable":true},"showId":{"type":"string","nullable":true},"seriesId":{"type":"string","nullable":true},"title":{"type":"string"},"status":{"$ref":"#/components/schemas/VideoStatus"},"duration":{"type":"number","nullable":true},"url":{"type":"string","nullable":true,"description":"rendered / render_failed: keyed current cut"},"renderUrl":{"type":"string","nullable":true,"description":"rendered: keyed immutable per-version file"},"thumbnail":{"type":"string","nullable":true},"watchUrl":{"type":"string"},"mediaKey":{"type":"string"},"version":{"type":"integer"},"video":{"type":"string","nullable":true,"description":"video.created only: relative path"},"error":{"type":"string","nullable":true},"warnings":{"type":"array","items":{"type":"string"}},"jobId":{"type":"string","description":"video.created from an async job"}}}}}}},"tags":[{"name":"videos"},{"name":"sources"},{"name":"library"},{"name":"voices"},{"name":"channels"},{"name":"series"},{"name":"account"},{"name":"webhooks"},{"name":"embed"},{"name":"billing"}],"paths":{"/tools/inspect_source":{"post":{"operationId":"inspect_source","summary":"Inspect source","description":"Read a source before cutting from it. Give a URL, library asset ids, or pasted text. A data API URL (JSON or CSV: an exchange ticker, standings, a storm feed, a leaderboard) is read as structured rows, one verbatim fact per row. Returns a source pack: title, summary, verbatim facts, stills, brand colors/fonts, and an error if the page did not load or had no readable text. Free.","tags":["sources"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Public URL to read (page or PDF)"},"assetIds":{"type":"array","items":{"type":"string"},"description":"Library asset ids (images become stills; video/audio become footage/music; PDF/text become text)"},"text":{"type":"string","description":"Pasted notes or a script the person gave you"},"data":{"type":"object","description":"Structured facts from an API caller (e.g. a token snapshot: symbol, priceUsd, change24hPct, holders…). Every value becomes a quotable fact; numbers are formatted for speech. Optional imageUrl/logoUrl and statsPage inside are used as the still and source link.","additionalProperties":true},"title":{"type":"string","description":"Title for a data source"},"summary":{"type":"string","description":"One-line summary for a data source"},"imageUrl":{"type":"string","description":"Logo/hero image URL for a data source"},"note":{"type":"string","description":"What they said this source is, if useful"}},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/market_data":{"post":{"operationId":"market_data","summary":"Market data","description":"Structured numbers from real data APIs — prices, market caps, changes, OHLC, weather, FX. Use this INSTEAD of web_search for anything with a number: crypto (CoinGecko), stocks / indices / ETFs (Yahoo), weather (Open-Meteo), currencies (Frankfurter). Free. Returns facts and a sourcePackId ready for create_video.","tags":["sources"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["crypto","stock","weather","fx"],"description":"crypto = coins by symbol or name; stock = tickers, indices (^IXIC, ^GSPC), ETFs; weather = a place; fx = currency pairs"},"symbols":{"type":"array","items":{"type":"string","description":""},"description":"e.g. [\"BTC\",\"ETH\"], [\"NVDA\",\"^IXIC\"], [\"EUR\",\"JPY\"] (vs USD unless base given), or a place name for weather"},"range":{"type":"string","enum":["1d","7d","30d","90d","1y"],"description":"history window (default 7d)"},"base":{"type":"string","description":"fx only: base currency, default USD"}},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/web_search":{"post":{"operationId":"web_search","summary":"Web search","description":"Search the web (titles, urls, snippets) when you need a source you do not have yet — a company page, a news item, a stat. 2 credits. Follow up with inspect_source on the best result; never quote a snippet as fact.","tags":["sources"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","description":""},"count":{"type":"number","description":"default 6"}},"required":["query"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/list_sources":{"post":{"operationId":"list_sources","summary":"List sources","description":"List recently inspected sources (id, title, url, whether it errored). Free.","tags":["sources"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/read_wallet":{"post":{"operationId":"read_wallet","summary":"Read wallet","description":"Current credit balance and plan for the signed-in account. Free.","tags":["billing"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/quote":{"post":{"operationId":"quote","summary":"Quote","description":"Price a video before making it. Returns credits and a component breakdown. Free.","tags":["billing"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"images":{"type":"string","enum":["none","source","library","generate","auto"],"description":"Visuals policy. 'source' = real stills only (default when a source has stills); 'auto' = stills first, generate only where nothing real exists; 'generate' = generated image on every visual scene (25cr each); 'none' = typography only."},"clips":{"type":"object","description":"AI motion clips made from stills on some scenes, billed per second. Only when asked or configured.","properties":{"provider":{"type":"string","enum":["minimax","kling","seedance-lite","seedance-pro"],"description":"Per second of footage: minimax (MiniMax H3, 768p) 15cr · kling (1080p) 20cr · seedance-lite (Seedance 2.0 fast) 50cr · seedance-pro (Seedance 2.5, native audio, up to 30s) 100cr"},"count":{"type":"number","description":"How many scenes get a clip (1-4)"},"seconds":{"type":"number","description":"Seconds per clip (default 6)"}},"required":["provider","count"]},"aiVideo":{"type":"object","description":"Full AI video: one generated shot for the whole runtime (voice + captions on top). seedance-pro up to 30s; minimax up to 15s. Expensive — quote first.","properties":{"provider":{"type":"string","enum":["minimax","kling","seedance-lite","seedance-pro"],"description":"Per second of footage: minimax (MiniMax H3, 768p) 15cr · kling (1080p) 20cr · seedance-lite (Seedance 2.0 fast) 50cr · seedance-pro (Seedance 2.5, native audio, up to 30s) 100cr"},"withAudio":{"type":"boolean","description":"seedance-pro only: generate ambient audio under the voiceover"},"prompt":{"type":"string","description":"Visual direction for the footage; default derived from the script"},"shots":{"type":"number","description":"Number of shots to stitch. Default: enough to cover the runtime (a 60s MiniMax video = 4 × 15s). Each shot is seeded with the last frame of the previous one."},"secondsPerShot":{"type":"number","description":"Length of each shot (default: the provider maximum — minimax 15, seedance-pro 30, kling 10)"},"prompts":{"type":"array","items":{"type":"string"},"description":"One visual direction per shot, for a story that changes scene"}},"required":["provider"]},"avatar":{"type":"boolean","description":"Include a presenter"},"scenes":{"type":"number","description":"Expected scene count (default 6)"},"targetSeconds":{"type":"number","description":"Runtime in seconds — drives script/voice/render units and AI footage cost. Default 30"},"voiceover":{"type":"boolean","description":"Default true"},"render":{"type":"boolean","description":"Default true"}},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/read_profile":{"post":{"operationId":"read_profile","summary":"Read profile","description":"What is saved about this account: brand kit, voices, audiences, CTAs, never-say, preferences, sources. Free. Usually already in the runtime context.","tags":["account"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/update_profile":{"post":{"operationId":"update_profile","summary":"Update profile","description":"Remember something about them for every future video: brandKit {accent, ground, fonts[], watermark, pack}, audiences[], ctas[], never[], styleNotes, prefs {tier, format, language}, voices[{voiceId,name,kind,default}]. Also decision: a one-line note of what they told you. Free.","tags":["account"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"brandKit":{"type":"object","additionalProperties":true},"audiences":{"type":"array","items":{"type":"string","description":""}},"ctas":{"type":"array","items":{"type":"string","description":""}},"never":{"type":"array","items":{"type":"string","description":""}},"styleNotes":{"type":"string","description":""},"prefs":{"type":"object","additionalProperties":true},"voices":{"type":"array","items":{"type":"object","additionalProperties":true}},"decision":{"type":"string","description":""}},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/learn_brand":{"post":{"operationId":"learn_brand","summary":"Learn brand","description":"Build their brand kit from a site (colors, primary, fonts) and save it on the profile; every later video inherits it. Free. Give url or sourcePackId; optional watermark text and pack (classic | editorial | bold | cinematic).","tags":["account"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":""},"sourcePackId":{"type":"string","description":""},"watermark":{"type":"string","description":""},"pack":{"type":"string","enum":["classic","editorial","bold","cinematic"],"description":""}},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/plan":{"post":{"operationId":"plan","summary":"Plan","description":"Plan before making, when the spend is over ~200 credits, the ask was unformed, or they asked to see a plan: drafts the script (charged as a script), returns storyboard frames (beat · what is on screen · duration), the settings you chose (format, length, tier, voice, visuals), the full cost and the proof cost, and a planId. The web shows it as a card with \"Make it\" and \"Proof first\". Pass what you settled: brief, sourcePackId(s), libraryAssetIds, format, targetSeconds, tier, workflow, voiceover, and plan {message, audience, outcome, look, stated[], inferred[]}.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"brief":{"type":"string","description":"The ask in your words: subject, audience, angle, CTA, anything they specified"},"sourcePackId":{"type":"string","description":""},"sourcePackIds":{"type":"array","items":{"type":"string","description":""},"description":"several sources"},"libraryAssetIds":{"type":"array","items":{"type":"string","description":""},"description":"their files to use (a track, footage, images, a logo)"},"format":{"type":"string","enum":["9:16","16:9","1:1","4:5"],"description":"Aspect ratio. Default 9:16."},"targetSeconds":{"type":"number","description":"Runtime; music video = the track length automatically"},"tier":{"type":"string","enum":["fast","standard","cinematic"],"description":"fast = stills + motion; standard = 1080p AI clips; cinematic = full AI footage"},"workflow":{"type":"string","enum":["faceless-explainer","product-launch","motion-graphics","talking-head","slideshow","general","music-video"],"description":""},"voiceover":{"type":"boolean"},"language":{"type":"string","description":""},"voiceId":{"type":"string","description":""},"lyrics":{"type":"string","description":""},"pacing":{"type":"string","enum":["calm","standard","fast"],"description":""},"styleNotes":{"type":"string","description":""},"channelContext":{"type":"string","description":""},"plan":{"type":"object","description":"{ message, audience, outcome, look, stated: [what they told you], inferred: [what you decided and why] }","additionalProperties":true}},"required":["brief"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/proof":{"post":{"operationId":"proof","summary":"Proof","description":"Render the first ~8 seconds of a plan in its look, voice and tier (one clip at most) so they can judge before the full spend. Costs the proof price the plan quoted. Returns proofVideoId.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"planId":{"type":"string","description":""}},"required":["planId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/create_video":{"post":{"operationId":"create_video","summary":"Create video","description":"Make a video from YOUR script: records the voiceover, places the stills you chose / library media / generated images, optional clips or presenter, times captions. Costs credits (quote first for a new video). Returns the video (status \"scripted\") — call render_video next to produce the MP4.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"engine":{"type":"string","enum":["opus","director"],"description":"'opus' (default for data, a page, a token or a brief): the designer writes the whole video — layout, motion, charts, voiceover — from the source pack's verbatim facts; pass sourcePackId/brief/format/targetSeconds and no script. 'director': your own script (footage edits, presenters, AI clips, music videos, shows)."},"planId":{"type":"string","description":"Make the video from a saved plan (after \"make it\"): the plan's script, settings and files are used; anything else you pass overrides. The script draft is not charged again."},"brief":{"type":"string","description":"What the video is about and for — the ask in your words, including audience, angle, CTA, and anything the person specified"},"script":{"type":"object","description":"The script you wrote (see \"Writing the script\"). Omit only for a quick engine-written first pass.","properties":{"title":{"type":"string","description":"≤ 80 chars, specific"},"vo":{"type":"string","description":"Full voiceover narration, ~2.5 words/second"},"cta":{"type":"string","description":"Closing line"},"music":{"type":"object","properties":{"mood":{"type":"string","enum":["sparse","tense","driving","hype","stately","urgent","triumphant","warm"],"description":""},"bpm":{"type":"number","description":""}}},"scenes":{"type":"array","items":{"type":"object","required":["type","text","duration"],"properties":{"type":{"type":"string","enum":["title","visual","chart","data","quote","cta"],"description":""},"text":{"type":"string","description":"On-screen text, 2-10 words"},"duration":{"type":"number","description":"Seconds"},"grounding":{"type":"string","description":"Exact source phrase this rests on; \"\" for framing/CTA"},"stillIndex":{"type":"number","description":"Index of a source still to show (each at most once)"},"clipRef":{"type":"object","description":"A cut from indexed footage (see index_footage): which asset, where to start, how long","properties":{"assetId":{"type":"string","description":""},"start":{"type":"number","description":"seconds into the file"},"duration":{"type":"number","description":"seconds (≤ scene duration)"}},"required":["assetId","start"]},"imagePrompt":{"type":"string","description":"Generated image prompt — only when images allow generation and no real still fits"},"frame":{"type":"string","enum":["phone","laptop","card"],"description":"Show this scene's image inside a device: phone for app screens, laptop for websites and dashboards, card for a plain screenshot. Use on almost every screenshot beat."},"stats":{"type":"array","description":"Stat pills for a data scene instead of one figure, e.g. [{value:\"84.6k\",label:\"stars\"},{value:\"448\",label:\"forks\"}] (2–4)","items":{"type":"object","properties":{"value":{"type":"string","description":""},"label":{"type":"string","description":""}}}},"transition":{"type":"string","enum":["wipe","cut","dissolve"],"description":"How this scene hands off to the next: wipe (accent bar sweep, the pack default), cut (hard cut), dissolve (this scene fades out, the next fades in). Mix them: dissolve into a mood shot, cut into a stat, wipe into the CTA."},"sfx":{"description":"Sound effect on this scene: 'impact' | 'whoosh' | 'riser' | 'tick' | 'keys' | 'none', or { assetId } for your own library audio (generate_sfx lands one there; optional volume 0–1). Omit for the pack's automatic pick."},"chart":{"type":"object","description":"chart scenes: a real chart drawn from your numbers. line = draw-on with glowing endpoint and the last value labeled; bars = grow-in, accent above the baseline / negativeColor below, value labels. text = the title above it.","properties":{"kind":{"type":"string","enum":["line","bars"],"description":""},"series":{"type":"array","description":"number[] or [{ t: label, v: number }] in order (2–60 points; bars ≤ 12)","items":{}},"labels":{"type":"array","items":{"type":"string","description":""},"description":"x labels (bars: one per bar; line: first/last shown)"},"color":{"type":"string","description":"hex; default accent (line: red-ish when the series ends lower)"},"negativeColor":{"type":"string","description":"hex for values below the baseline"},"baseline":{"description":"bars: 0 (zero line, negatives hang down) or 'min' (default when all values are positive)"},"valueFormat":{"type":"string","enum":["usd","pct","raw"],"description":""},"title":{"type":"string","description":"small caption under the chart: source, window"}},"required":["kind","series"]},"motion":{"type":"string","enum":["kinetic","countup","slide","zoom","typewriter","still","slam"],"description":"How the scene moves. Default is picked per type (title→kinetic, data→countup, visual→slide/zoom, quote→typewriter); slam = hit-in with a shake for a hero number or word; set it to change rhythm."},"asset":{"type":"object","description":"Media for this scene: a public http(s) image or mp4 url (fetched at create time, full-bleed under the text, videos muted) or a library file path","properties":{"url":{"type":"string","description":"https://… image or mp4"},"kind":{"type":"string","enum":["image","video"],"description":"inferred from the file when omitted"},"path":{"type":"string","description":"library path, e.g. libraries/u/<scope>/files/<assetId>.mp4"},"mediaStart":{"type":"number","description":"video: seconds into the file to start"}}},"clipPrompt":{"type":"string","description":"Motion description for an AI clip — only when clips are enabled"}}}}},"required":["title","vo","scenes"]},"sourcePackId":{"type":"string","description":"From inspect_source. Omit only for a deliberately ungrounded topic video."},"sourcePackIds":{"type":"array","items":{"type":"string","description":""},"description":"Several sources at once (multi-link briefs, market_data + a page) — merged into one grounded pack"},"format":{"type":"string","enum":["9:16","16:9","1:1","4:5"],"description":"Aspect ratio. Default 9:16."},"lyrics":{"type":"string","description":"music-video only: the lyrics to show on screen, one line per scene in order. Leave out for a pure visual (default)."},"tier":{"type":"string","enum":["fast","standard","cinematic"],"description":"Quality tier you told them: fast = stills + motion; standard = 1080p AI clips (kling); cinematic = full AI footage (seedance-pro). Picks the clip model when clips has no provider."},"plan":{"type":"object","description":"The brief you settled on, saved on the video: { message, audience, outcome, look, stated: [what they told you], inferred: [what you decided and why] }","additionalProperties":true},"workflow":{"type":"string","enum":["faceless-explainer","product-launch","motion-graphics","talking-head","slideshow","general","music-video"],"description":"Composition approach. music-video for a person's own track (no VO, no captions, no SFX, no on-screen text unless lyrics; runtime = the track); product-launch for a company/site/product page; faceless-explainer for an article/notes; talking-head when a presenter is used; motion-graphics for a short unnarrated stat hit."},"images":{"type":"string","enum":["none","source","library","generate","auto"],"description":"Visuals policy. 'source' = real stills only (default when a source has stills); 'auto' = stills first, generate only where nothing real exists; 'generate' = generated image on every visual scene (25cr each); 'none' = typography only."},"clips":{"type":"object","description":"AI motion clips made from stills on some scenes, billed per second. Only when asked or configured.","properties":{"provider":{"type":"string","enum":["minimax","kling","seedance-lite","seedance-pro"],"description":"Per second of footage: minimax (MiniMax H3, 768p) 15cr · kling (1080p) 20cr · seedance-lite (Seedance 2.0 fast) 50cr · seedance-pro (Seedance 2.5, native audio, up to 30s) 100cr"},"count":{"type":"number","description":"How many scenes get a clip (1-4)"},"seconds":{"type":"number","description":"Seconds per clip (default 6)"}},"required":["provider","count"]},"aiVideo":{"type":"object","description":"Full AI video: one generated shot for the whole runtime (voice + captions on top). seedance-pro up to 30s; minimax up to 15s. Expensive — quote first.","properties":{"provider":{"type":"string","enum":["minimax","kling","seedance-lite","seedance-pro"],"description":"Per second of footage: minimax (MiniMax H3, 768p) 15cr · kling (1080p) 20cr · seedance-lite (Seedance 2.0 fast) 50cr · seedance-pro (Seedance 2.5, native audio, up to 30s) 100cr"},"withAudio":{"type":"boolean","description":"seedance-pro only: generate ambient audio under the voiceover"},"prompt":{"type":"string","description":"Visual direction for the footage; default derived from the script"},"shots":{"type":"number","description":"Number of shots to stitch. Default: enough to cover the runtime (a 60s MiniMax video = 4 × 15s). Each shot is seeded with the last frame of the previous one."},"secondsPerShot":{"type":"number","description":"Length of each shot (default: the provider maximum — minimax 15, seedance-pro 30, kling 10)"},"prompts":{"type":"array","items":{"type":"string"},"description":"One visual direction per shot, for a story that changes scene"}},"required":["provider"]},"avatar":{"type":"object","description":"A talking presenter lip-synced to the voiceover. Per second of runtime: stock 3cr/s, photo 25cr/s.","properties":{"mode":{"type":"string","enum":["photo","stock"],"description":"'photo' animates a library photo with a clear face; 'stock' uses a stock presenter"},"imageAssetId":{"type":"string","description":"photo mode: library asset id of the face photo"},"avatarId":{"type":"string","description":"stock mode: presenter id or a hint like 'emily', 'marcus', 'any_female'. Vertical presenters are picked automatically for 9:16 / 4:5."}},"required":["mode"]},"public":{"type":"boolean","description":"true = the finished file is playable without a key (share links, feeds). Default false: media needs the keyed url / mediaKey returned with the video."},"mode":{"type":"string","enum":["data","story"],"description":"engine 'opus' only: 'story' = a narrative/meme video with reaction-GIF cutaways (pass clipQueries); omit for data videos"},"clipQueries":{"type":"array","items":{"type":"string"},"description":"engine 'opus' + mode 'story': 3–5 short GIF searches for cutaways (animals/anonymous people only). Prefix 'stock:' for licensed stock footage instead of GIFs (required for political content)."},"style":{"type":"string","description":"engine 'opus' only: a look from the style bank (e.g. comic, arcade, nature-doc, trading-terminal, luxury-minimal, chaos-meme); omit to let the designer choose"},"layout":{"type":"string","enum":["full","split"],"description":"'split' = the presenter (avatar or their footage) fills the bottom third while your scenes/motion graphics play in the top two-thirds — the talking-head-with-changing-content format. Needs avatar or footage. Default 'full'."},"captions":{"type":"boolean","description":"Timed captions from the voiceover. Default true."},"voiceId":{"type":"string","description":"Voice for the voiceover (a show's configured voice, or a cloned voice id the person owns). Default: house voice."},"language":{"type":"string","description":"Language for narration and on-screen text (e.g. \"Spanish\", \"pt-BR\", \"Japanese\"). Default English / the source language."},"voiceover":{"type":"boolean","description":"false = silent piece (no narration, no captions). Default true; auto-false under 3s."},"targetSeconds":{"type":"number","description":"Target runtime in seconds — anything from 1 to long form (a 10-minute episode = 600). Default follows the source (25-40s). Cost scales with it."},"pacing":{"type":"string","enum":["calm","standard","fast"],"description":"Scene density: calm ≈ 9s scenes (documentary), standard ≈ 6s, fast ≈ 3.5s (roast, hype). Default standard, or the show's setting."},"libraryAssetIds":{"type":"array","items":{"type":"string"},"description":"Library assets to place: images/videos go on visual scenes, an audio file becomes the music bed"},"brand":{"type":"object","description":"Override brand tokens (otherwise taken from the source page)","properties":{"pack":{"type":"string","enum":["classic","editorial","bold","cinematic"],"description":"Style pack: one coherent look — editorial (serif, warm, slow), bold (condensed uppercase, hot accent, fast), cinematic (letterbox, filmic grade, slow push-ins), classic (default). Sets fonts, palette, motion, grade and sound design; explicit brand fields still win."},"accent":{"type":"string","description":"hex color"},"ground":{"type":"string","description":"hex background"},"ink":{"type":"string","description":"hex text"},"displayFont":{"type":"string","description":"Google font"},"bodyFont":{"type":"string","description":"Google font"},"watermark":{"type":"string","description":"Small corner text; empty string removes it"},"disclaimer":{"type":"string","description":"Required legal line shown for the whole video, exactly as given"}}},"channelId":{"type":"string","description":"Make it as an episode of this channel"},"showId":{"type":"string","description":"…in this show"},"seriesId":{"type":"string","description":"…in this series"}},"required":["brief"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/render_video":{"post":{"operationId":"render_video","summary":"Render video","description":"Produce the MP4 for a video (10cr). Runs the quality check first; on failure returns the problems so you can fix and retry. Takes 1-3 minutes; progress streams to the person. If it returns an error (including \"Already rendering\"), no new cut exists — say exactly that; never tell the person it rendered.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":"Video id, e.g. vid-012"}},"required":["videoId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/edit_video":{"post":{"operationId":"edit_video","summary":"Edit video","description":"Apply a typed edit to an existing video: shorter, new hook, different CTA, drop a scene, lead with the price, tone. Pass the person's words and your revised script (get_video shows the current one); keep stillIndex on scenes whose picture should stay. Keeps source, brand, voice; re-records voice only if the words changed; re-times captions. 20-50cr (scales with length). Then render_video.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":"Video id"},"notes":{"type":"string","description":"The person's edit verbatim, plus your concrete reading of it"},"script":{"type":"object","description":"The script you wrote (see \"Writing the script\"). Omit only for a quick engine-written first pass.","properties":{"title":{"type":"string","description":"≤ 80 chars, specific"},"vo":{"type":"string","description":"Full voiceover narration, ~2.5 words/second"},"cta":{"type":"string","description":"Closing line"},"music":{"type":"object","properties":{"mood":{"type":"string","enum":["sparse","tense","driving","hype","stately","urgent","triumphant","warm"],"description":""},"bpm":{"type":"number","description":""}}},"scenes":{"type":"array","items":{"type":"object","required":["type","text","duration"],"properties":{"type":{"type":"string","enum":["title","visual","chart","data","quote","cta"],"description":""},"text":{"type":"string","description":"On-screen text, 2-10 words"},"duration":{"type":"number","description":"Seconds"},"grounding":{"type":"string","description":"Exact source phrase this rests on; \"\" for framing/CTA"},"stillIndex":{"type":"number","description":"Index of a source still to show (each at most once)"},"clipRef":{"type":"object","description":"A cut from indexed footage (see index_footage): which asset, where to start, how long","properties":{"assetId":{"type":"string","description":""},"start":{"type":"number","description":"seconds into the file"},"duration":{"type":"number","description":"seconds (≤ scene duration)"}},"required":["assetId","start"]},"imagePrompt":{"type":"string","description":"Generated image prompt — only when images allow generation and no real still fits"},"frame":{"type":"string","enum":["phone","laptop","card"],"description":"Show this scene's image inside a device: phone for app screens, laptop for websites and dashboards, card for a plain screenshot. Use on almost every screenshot beat."},"stats":{"type":"array","description":"Stat pills for a data scene instead of one figure, e.g. [{value:\"84.6k\",label:\"stars\"},{value:\"448\",label:\"forks\"}] (2–4)","items":{"type":"object","properties":{"value":{"type":"string","description":""},"label":{"type":"string","description":""}}}},"transition":{"type":"string","enum":["wipe","cut","dissolve"],"description":"How this scene hands off to the next: wipe (accent bar sweep, the pack default), cut (hard cut), dissolve (this scene fades out, the next fades in). Mix them: dissolve into a mood shot, cut into a stat, wipe into the CTA."},"sfx":{"description":"Sound effect on this scene: 'impact' | 'whoosh' | 'riser' | 'tick' | 'keys' | 'none', or { assetId } for your own library audio (generate_sfx lands one there; optional volume 0–1). Omit for the pack's automatic pick."},"chart":{"type":"object","description":"chart scenes: a real chart drawn from your numbers. line = draw-on with glowing endpoint and the last value labeled; bars = grow-in, accent above the baseline / negativeColor below, value labels. text = the title above it.","properties":{"kind":{"type":"string","enum":["line","bars"],"description":""},"series":{"type":"array","description":"number[] or [{ t: label, v: number }] in order (2–60 points; bars ≤ 12)","items":{}},"labels":{"type":"array","items":{"type":"string","description":""},"description":"x labels (bars: one per bar; line: first/last shown)"},"color":{"type":"string","description":"hex; default accent (line: red-ish when the series ends lower)"},"negativeColor":{"type":"string","description":"hex for values below the baseline"},"baseline":{"description":"bars: 0 (zero line, negatives hang down) or 'min' (default when all values are positive)"},"valueFormat":{"type":"string","enum":["usd","pct","raw"],"description":""},"title":{"type":"string","description":"small caption under the chart: source, window"}},"required":["kind","series"]},"motion":{"type":"string","enum":["kinetic","countup","slide","zoom","typewriter","still","slam"],"description":"How the scene moves. Default is picked per type (title→kinetic, data→countup, visual→slide/zoom, quote→typewriter); slam = hit-in with a shake for a hero number or word; set it to change rhythm."},"asset":{"type":"object","description":"Media for this scene: a public http(s) image or mp4 url (fetched at create time, full-bleed under the text, videos muted) or a library file path","properties":{"url":{"type":"string","description":"https://… image or mp4"},"kind":{"type":"string","enum":["image","video"],"description":"inferred from the file when omitted"},"path":{"type":"string","description":"library path, e.g. libraries/u/<scope>/files/<assetId>.mp4"},"mediaStart":{"type":"number","description":"video: seconds into the file to start"}}},"clipPrompt":{"type":"string","description":"Motion description for an AI clip — only when clips are enabled"}}}}},"required":["title","vo","scenes"]},"language":{"type":"string","description":"Switch the video's language as part of the edit (prefer translate_video for a straight translation)"}},"required":["videoId","notes"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/translate_video":{"post":{"operationId":"translate_video","summary":"Translate video","description":"Make another language version of an existing video: narration, on-screen text, title and CTA translated (names, brands, figures unchanged), voice re-recorded, captions re-timed, same stills and brand. Costs like an edit with a new voice (scales with length). Then render_video.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":"Video id"},"language":{"type":"string","description":"Target language, e.g. \"Spanish\", \"pt-BR\", \"Japanese\""},"notes":{"type":"string","description":"Anything to adapt beyond translation (local idiom, currency wording…)"},"script":{"type":"object","description":"The script you wrote (see \"Writing the script\"). Omit only for a quick engine-written first pass.","properties":{"title":{"type":"string","description":"≤ 80 chars, specific"},"vo":{"type":"string","description":"Full voiceover narration, ~2.5 words/second"},"cta":{"type":"string","description":"Closing line"},"music":{"type":"object","properties":{"mood":{"type":"string","enum":["sparse","tense","driving","hype","stately","urgent","triumphant","warm"],"description":""},"bpm":{"type":"number","description":""}}},"scenes":{"type":"array","items":{"type":"object","required":["type","text","duration"],"properties":{"type":{"type":"string","enum":["title","visual","chart","data","quote","cta"],"description":""},"text":{"type":"string","description":"On-screen text, 2-10 words"},"duration":{"type":"number","description":"Seconds"},"grounding":{"type":"string","description":"Exact source phrase this rests on; \"\" for framing/CTA"},"stillIndex":{"type":"number","description":"Index of a source still to show (each at most once)"},"clipRef":{"type":"object","description":"A cut from indexed footage (see index_footage): which asset, where to start, how long","properties":{"assetId":{"type":"string","description":""},"start":{"type":"number","description":"seconds into the file"},"duration":{"type":"number","description":"seconds (≤ scene duration)"}},"required":["assetId","start"]},"imagePrompt":{"type":"string","description":"Generated image prompt — only when images allow generation and no real still fits"},"frame":{"type":"string","enum":["phone","laptop","card"],"description":"Show this scene's image inside a device: phone for app screens, laptop for websites and dashboards, card for a plain screenshot. Use on almost every screenshot beat."},"stats":{"type":"array","description":"Stat pills for a data scene instead of one figure, e.g. [{value:\"84.6k\",label:\"stars\"},{value:\"448\",label:\"forks\"}] (2–4)","items":{"type":"object","properties":{"value":{"type":"string","description":""},"label":{"type":"string","description":""}}}},"transition":{"type":"string","enum":["wipe","cut","dissolve"],"description":"How this scene hands off to the next: wipe (accent bar sweep, the pack default), cut (hard cut), dissolve (this scene fades out, the next fades in). Mix them: dissolve into a mood shot, cut into a stat, wipe into the CTA."},"sfx":{"description":"Sound effect on this scene: 'impact' | 'whoosh' | 'riser' | 'tick' | 'keys' | 'none', or { assetId } for your own library audio (generate_sfx lands one there; optional volume 0–1). Omit for the pack's automatic pick."},"chart":{"type":"object","description":"chart scenes: a real chart drawn from your numbers. line = draw-on with glowing endpoint and the last value labeled; bars = grow-in, accent above the baseline / negativeColor below, value labels. text = the title above it.","properties":{"kind":{"type":"string","enum":["line","bars"],"description":""},"series":{"type":"array","description":"number[] or [{ t: label, v: number }] in order (2–60 points; bars ≤ 12)","items":{}},"labels":{"type":"array","items":{"type":"string","description":""},"description":"x labels (bars: one per bar; line: first/last shown)"},"color":{"type":"string","description":"hex; default accent (line: red-ish when the series ends lower)"},"negativeColor":{"type":"string","description":"hex for values below the baseline"},"baseline":{"description":"bars: 0 (zero line, negatives hang down) or 'min' (default when all values are positive)"},"valueFormat":{"type":"string","enum":["usd","pct","raw"],"description":""},"title":{"type":"string","description":"small caption under the chart: source, window"}},"required":["kind","series"]},"motion":{"type":"string","enum":["kinetic","countup","slide","zoom","typewriter","still","slam"],"description":"How the scene moves. Default is picked per type (title→kinetic, data→countup, visual→slide/zoom, quote→typewriter); slam = hit-in with a shake for a hero number or word; set it to change rhythm."},"asset":{"type":"object","description":"Media for this scene: a public http(s) image or mp4 url (fetched at create time, full-bleed under the text, videos muted) or a library file path","properties":{"url":{"type":"string","description":"https://… image or mp4"},"kind":{"type":"string","enum":["image","video"],"description":"inferred from the file when omitted"},"path":{"type":"string","description":"library path, e.g. libraries/u/<scope>/files/<assetId>.mp4"},"mediaStart":{"type":"number","description":"video: seconds into the file to start"}}},"clipPrompt":{"type":"string","description":"Motion description for an AI clip — only when clips are enabled"}}}}},"required":["title","vo","scenes"]}},"required":["videoId","language"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/make_another":{"post":{"operationId":"make_another","summary":"Make another","description":"A fresh take on the same source: new angle, new script, same brand/format/options. Costs like a new video. Then render_video.","tags":["channels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":"The video to take another swing at"},"angle":{"type":"string","description":"What should be different this time"}},"required":["videoId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/reorder_scenes":{"post":{"operationId":"reorder_scenes","summary":"Reorder scenes","description":"Reorder or drop scenes without touching their content: pass the new order as 1-based scene numbers (omit a number to cut that scene). Free; render to see it. The voiceover is not re-recorded, so only use it when the narration order still makes sense — otherwise edit_video.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":""},"order":{"type":"array","items":{"type":"number"},"description":"e.g. [1,3,2,4]"}},"required":["videoId","order"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/update_scene":{"post":{"operationId":"update_scene","summary":"Update scene","description":"Edit one scene without touching the rest: its on-screen text, type, duration, or image prompt. Free; then render_video.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":"Video id"},"sceneNumber":{"type":"number","description":"1-based scene number as shown in the preview"},"text":{"type":"string","description":"New on-screen text"},"type":{"type":"string","enum":["title","visual","chart","data","quote","cta"],"description":"Scene type"},"duration":{"type":"number","description":"Seconds"},"imagePrompt":{"type":"string","description":"New generated-image prompt (only used if images are generated for this video)"}},"required":["videoId","sceneNumber"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/update_video":{"post":{"operationId":"update_video","summary":"Update video","description":"Change title, format, brand (accent, watermark, disclaimer), layout, or music volume of a video. Free; a format/layout/volume change needs a re-render to show.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"musicVolume":{"type":"number","description":"Music bed volume 0-1 (default 0.14 under narration). Re-render to apply."},"layout":{"type":"string","enum":["full","split"],"description":"'split' = presenter bottom third, scenes top two-thirds. Re-render to apply."},"videoId":{"type":"string","description":"Video id"},"title":{"type":"string","description":"New title"},"format":{"type":"string","enum":["9:16","16:9","1:1","4:5"],"description":"Aspect ratio. Default 9:16."},"brand":{"type":"object","properties":{"pack":{"type":"string","enum":["classic","editorial","bold","cinematic"],"description":"Style pack (see create_video)"},"accent":{"type":"string","description":"hex"},"ground":{"type":"string","description":"hex"},"ink":{"type":"string","description":"hex"},"displayFont":{"type":"string","description":""},"bodyFont":{"type":"string","description":""},"watermark":{"type":"string","description":"empty string removes"},"disclaimer":{"type":"string","description":"exact legal text; empty string removes"}}}},"required":["videoId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/generate_clip":{"post":{"operationId":"generate_clip","summary":"Generate clip","description":"Turn one scene's still into a short AI motion clip, billed per second (minimax 15cr/s default). Only when asked.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":"Video id"},"sceneNumber":{"type":"number","description":"1-based"},"provider":{"type":"string","enum":["minimax","kling","seedance-lite","seedance-pro"],"description":"Per second of footage: minimax (MiniMax H3, 768p) 15cr · kling (1080p) 20cr · seedance-lite (Seedance 2.0 fast) 50cr · seedance-pro (Seedance 2.5, native audio, up to 30s) 100cr"},"seconds":{"type":"number","description":"Clip length (default: the scene's duration, clamped to the provider's range)"},"prompt":{"type":"string","description":"Camera/motion description, one sentence. Default: gentle motion faithful to the still."}},"required":["videoId","sceneNumber"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/add_presenter":{"post":{"operationId":"add_presenter","summary":"Add presenter","description":"Add a talking presenter to an existing video, lip-synced to its voiceover (stock 3cr/s, photo 25cr/s of runtime). Scenes become lower-third overlays. Then render_video.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":"Video id"},"mode":{"type":"string","enum":["photo","stock"],"description":""},"imageAssetId":{"type":"string","description":"photo mode: library asset with a clear face"},"avatarId":{"type":"string","description":"stock mode: presenter id or hint"}},"required":["videoId","mode"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/get_video":{"post":{"operationId":"get_video","summary":"Get video","description":"Full state of a video: script (vo + scenes with stillIndex/grounding), assets, status, cost, last check result. Free. Load before an edit.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":""}},"required":["videoId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/list_videos":{"post":{"operationId":"list_videos","summary":"List videos","description":"Recent videos (id, title, status, duration). Free.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"limit":{"type":"number","description":"Default 20"}},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/read_library":{"post":{"operationId":"read_library","summary":"Read library","description":"What the person has uploaded or connected: images, video, audio, documents. Free.","tags":["library"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","description":"Filename contains"},"type":{"type":"string","enum":["image","video","audio","application"],"description":"MIME family filter"}},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/import_drive":{"post":{"operationId":"import_drive","summary":"Import drive","description":"Bring files in from a Google Drive link shared to \"anyone with the link\". First call with just the url → a list of files (id, name, kind). Then call again with fileIds to import the ones they want (or all: true). Imported files land in the library and can be used on scenes. Free.","tags":["library"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Drive folder or file link"},"fileIds":{"type":"array","items":{"type":"string"},"description":"Ids from the listing to import"},"all":{"type":"boolean","description":"Import every file in the listing"},"kinds":{"type":"array","items":{"type":"string","enum":["image","video","audio","document"],"description":""},"description":"With all: true, limit to these kinds"}},"required":["url"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/list_voices":{"post":{"operationId":"list_voices","summary":"List voices","description":"House voices plus the person's cloned voices (voiceId, name). Free.","tags":["voices"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/clone_voice":{"post":{"operationId":"clone_voice","summary":"Clone voice","description":"Clone the person's voice from their own audio samples (200cr, once). Requires consent in their words.","tags":["voices"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Voice name"},"assetIds":{"type":"array","items":{"type":"string"},"description":"Library audio/video assets with their speech (1–5 minutes total)"},"consent":{"type":"boolean","description":"They confirmed it is their voice or they have permission"},"consentText":{"type":"string","description":"Their confirmation, verbatim"},"language":{"type":"string","description":"Primary language of the samples"}},"required":["name","assetIds","consent","consentText"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/delete_voice":{"post":{"operationId":"delete_voice","summary":"Delete voice","description":"Remove a cloned voice.","tags":["voices"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"voiceId":{"type":"string","description":""}},"required":["voiceId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/index_footage":{"post":{"operationId":"index_footage","summary":"Index footage","description":"Scan video files in the library so the director can cut from them: scene cuts, a description of every scene, the speech. 20 credits per minute of footage. quoteOnly: true prices it first.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"assetIds":{"type":"array","items":{"type":"string"},"description":"Video assets from read_library / import_drive"},"context":{"type":"string","description":"What the footage is (helps the descriptions): \"karaoke lounge rooms and parties\""},"transcript":{"type":"boolean","description":"Also transcribe speech (default true)"},"quoteOnly":{"type":"boolean","description":"Only return the price and durations"}},"required":["assetIds"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/attach_asset":{"post":{"operationId":"attach_asset","summary":"Attach asset","description":"Put a library file on a video: an image/video on a scene, an audio file as the music bed, or an image as the end-card logo. Free; then render_video.","tags":["library"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":""},"assetId":{"type":"string","description":"Library asset id"},"sceneNumber":{"type":"number","description":"1-based scene to place it on (for image/video)"},"as":{"type":"string","enum":["visual","music","logo"],"description":"Default 'visual' for images/video, 'music' for audio"}},"required":["videoId","assetId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/create_channel":{"post":{"operationId":"create_channel","summary":"Create channel","description":"Create a channel (a property/brand). Only when they want ongoing content, not a one-off.","tags":["channels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","description":"Name"},"promise":{"type":"string","description":"What the channel promises its audience, one sentence"},"audience":{"type":"string","description":"Who it is for"},"industry":{"type":"string","description":"Industry label"},"compliance":{"type":"string","description":"Regulatory notes / required disclaimers"}},"required":["label","promise"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/create_show":{"post":{"operationId":"create_show","summary":"Create show","description":"Create a recurring format inside a channel.","tags":["channels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"label":{"type":"string","description":"Show name"},"promise":{"type":"string","description":"What each episode delivers"},"mode":{"type":"string","enum":["passive","realtime","both"],"description":"passive = made on demand; realtime = fires when a source changes"},"host":{"type":"string","enum":["none","human","ai-avatar"],"description":"Default none"},"voice":{"type":"string","description":"One sentence on tone"},"voiceId":{"type":"string","description":"Voice id for every episode of this show (e.g. a cloned voice). Default: house voice."},"language":{"type":"string","description":"Language for every episode (e.g. \"Spanish\")"},"maxSeconds":{"type":"number","description":"Longest episode this show makes (default none — long form allowed)"},"format":{"type":"string","enum":["9:16","16:9","1:1","4:5"],"description":"Aspect ratio. Default 9:16."},"styleNotes":{"type":"string","description":"Visual rules the director should keep every episode"},"persona":{"type":"object","description":"A named host the director writes every episode as: {name, tone, opener (verbatim first line), closer, catchphrases[], never[] (banned words)}","properties":{"name":{"type":"string","description":""},"tone":{"type":"string","description":""},"opener":{"type":"string","description":""},"closer":{"type":"string","description":""},"catchphrases":{"type":"array","items":{"type":"string"}},"never":{"type":"array","items":{"type":"string"}}}},"pacing":{"type":"string","enum":["calm","standard","fast"],"description":"Scene density for every episode: calm ≈ 9s scenes, standard ≈ 6s, fast ≈ 3.5s"}},"required":["channelId","label","promise"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/create_series":{"post":{"operationId":"create_series","summary":"Create series","description":"Create a series (season / running unit) inside a show.","tags":["series"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"showId":{"type":"string","description":""},"label":{"type":"string","description":""},"promise":{"type":"string","description":""}},"required":["channelId","showId","label"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/get_channel_context":{"post":{"operationId":"get_channel_context","summary":"Get channel context","description":"Channel definition, shows, and series. Free. Load before making channel content.","tags":["channels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""}},"required":["channelId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/get_knowledge_graph":{"post":{"operationId":"get_knowledge_graph","summary":"Get knowledge graph","description":"A channel's real data-source entities (with fetch status and fields). Free. The only facts a channel video may use besides its source pack.","tags":["channels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""}},"required":["channelId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/list_channels":{"post":{"operationId":"list_channels","summary":"List channels","description":"All channels. Free.","tags":["channels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/rename_channel":{"post":{"operationId":"rename_channel","summary":"Rename channel","description":"Rename a channel.","tags":["channels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"newLabel":{"type":"string","description":""}},"required":["channelId","newLabel"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/start_series":{"post":{"operationId":"start_series","summary":"Start series","description":"Make a series listen: watch a page or RSS/Atom feed, or run on a schedule, and make an episode when the source changes. First check is a silent baseline. Costs nothing to start; each episode costs like a video from this account.","tags":["series"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"showId":{"type":"string","description":""},"seriesId":{"type":"string","description":"Existing series id (create_series first if needed)"},"kind":{"type":"string","enum":["page","rss","adapter","schedule"],"description":"page/rss = check on the cadence and make an episode ONLY when the source changed ('watch this page'); adapter = same, from an adapter spec you wrote (JSON API / CSV / structured page); schedule = make an episode EVERY run, changed or not ('every weekday at 8am make one') — from the url, or from the adapter when one is given (e.g. weekly prices); the first run makes an episode right away"},"url":{"type":"string","description":"Page or feed URL. Required for page/rss; for schedule it is the source each episode is cut from"},"adapter":{"type":"object","description":"An adapter spec (data, not code) for a JSON API, CSV, or regular HTML page","properties":{"kind":{"type":"string","enum":["json","csv","html"],"description":""},"url":{"type":"string","description":""},"headers":{"type":"object","additionalProperties":{"type":"string"}},"itemsPath":{"type":"string","description":"json: path to the items array (e.g. \"data\" or \"results.items\"); html: a regex with named groups matching one item"},"sections":{"type":"array","description":"json only: several lists from one response, each tagged: [{path:'gainers', label:'gainer', limit:3}] — use {section} in factTemplate","items":{"type":"object","properties":{"path":{"type":"string","description":""},"label":{"type":"string","description":""},"limit":{"type":"number","description":""}}}},"fields":{"type":"object","additionalProperties":{"type":"string"},"description":"fact label → item path (json), column name (csv) or named group (html)"},"meaningFields":{"type":"array","items":{"type":"string"},"description":"fields that define \"changed\" (default all)"},"factTemplate":{"type":"string","description":"e.g. \"{project} {name}: {apy} APY on {tvlUsd} TVL\""},"limit":{"type":"number","description":"items to keep (default 10)"},"notes":{"type":"string","description":""}},"required":["kind","url","fields"]},"schedule":{"type":"string","description":"How often to check or run: 'hourly', 'every 30m', 'daily 9am', 'weekdays 8am', 'weekly mon 9am'. Default: pages hourly, feeds every 30m."},"policy":{"type":"string","enum":["hold","approval","digest","autopost","review"],"description":"Omit to use the show's policy. review = an AI reviewer checks each render, then posts it (or holds it with the issues). approval = the show's named approvers must sign off (a show with policy approval overrides this)"},"destination":{"type":"string","enum":["share-link","download","buffer"],"description":"Where autopost/review sends episodes (and what publish defaults to). YouTube, TikTok, Instagram etc. go through their Buffer channels"},"channelIds":{"type":"array","items":{"type":"string"},"description":"Buffer channel ids for this series (default: the show's picks, else the account's selection)"},"tz":{"type":"string","description":"IANA time zone for the schedule's clock times, e.g. 'America/New_York' (default: server time, UTC)"},"style":{"type":"string","description":"Look for every episode (a style-bank id such as trading-terminal, tabloid, swiss-poster, breaking-news); omit for a varied pick"},"targetSeconds":{"type":"number","description":"Episode length in seconds (default 30; each started 30s is one episode charge)"},"brief":{"type":"string","description":"Standing brief for every episode: audience, angle, CTA, what to lead with"},"format":{"type":"string","enum":["9:16","16:9","1:1","4:5"],"description":"Aspect ratio. Default 9:16."},"voiceId":{"type":"string","description":"Voice for every episode (default: the show's voice or the house voice)"}},"required":["channelId","showId","seriesId","kind","policy"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/list_series":{"post":{"operationId":"list_series","summary":"List series","description":"All listening series with source, cadence, policy, last check, next check, episode count. Free.","tags":["series"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/run_series":{"post":{"operationId":"run_series","summary":"Run series","description":"Check a series right now. dry: true previews what would happen without advancing state or spending credits.","tags":["series"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"showId":{"type":"string","description":""},"seriesId":{"type":"string","description":""},"dry":{"type":"boolean","description":"Preview only"}},"required":["channelId","showId","seriesId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/pause_series":{"post":{"operationId":"pause_series","summary":"Pause series","description":"Pause or resume a listening series.","tags":["series"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"showId":{"type":"string","description":""},"seriesId":{"type":"string","description":""},"active":{"type":"boolean","description":"false to pause, true to resume"}},"required":["channelId","showId","seriesId","active"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/connect_feed":{"post":{"operationId":"connect_feed","summary":"Connect feed","description":"Register a source on a channel's knowledge graph after a real fetch (records the actual HTTP status and latest items). Pass an adapter spec for JSON APIs / CSV / structured pages. Free.","tags":["series"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"url":{"type":"string","description":"Feed or page URL (or the adapter's url)"},"label":{"type":"string","description":""},"adapter":{"type":"object","description":"An adapter spec (data, not code) for a JSON API, CSV, or regular HTML page","properties":{"kind":{"type":"string","enum":["json","csv","html"],"description":""},"url":{"type":"string","description":""},"headers":{"type":"object","additionalProperties":{"type":"string"}},"itemsPath":{"type":"string","description":"json: path to the items array (e.g. \"data\" or \"results.items\"); html: a regex with named groups matching one item"},"sections":{"type":"array","description":"json only: several lists from one response, each tagged: [{path:'gainers', label:'gainer', limit:3}] — use {section} in factTemplate","items":{"type":"object","properties":{"path":{"type":"string","description":""},"label":{"type":"string","description":""},"limit":{"type":"number","description":""}}}},"fields":{"type":"object","additionalProperties":{"type":"string"},"description":"fact label → item path (json), column name (csv) or named group (html)"},"meaningFields":{"type":"array","items":{"type":"string"},"description":"fields that define \"changed\" (default all)"},"factTemplate":{"type":"string","description":"e.g. \"{project} {name}: {apy} APY on {tvlUsd} TVL\""},"limit":{"type":"number","description":"items to keep (default 10)"},"notes":{"type":"string","description":""}},"required":["kind","url","fields"]}},"required":["channelId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/publish":{"post":{"operationId":"publish","summary":"Publish","description":"Send a rendered video to a destination: share-link / download (a URL they can send), or buffer (queue to the Buffer channels they connected in Account → Publishing; saved as a draft unless autopost is true). If Buffer is not connected, say where to paste the token.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":""},"destination":{"type":"string","enum":["share-link","download","buffer","youtube"],"description":"youtube = upload straight to their connected YouTube channel (unlisted unless autopost); say 'connect YouTube in Settings → Publishing' if it isn't"},"privacy":{"type":"string","enum":["public","unlisted","private"],"description":"youtube only; default unlisted"},"caption":{"type":"string","description":"Post text (buffer)"},"captions":{"type":"object","additionalProperties":{"type":"string"},"description":"Per-service post text, e.g. {\"instagram\": \"…link in bio\", \"tiktok\": \"…\"}; services without one use caption"},"autopost":{"type":"boolean","description":"publish immediately instead of a draft"},"channelIds":{"type":"array","items":{"type":"string"},"description":"Buffer channel ids to post to (default: the show's picks, else the account default)"}},"required":["videoId","destination"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/read_analytics":{"post":{"operationId":"read_analytics","summary":"Read analytics","description":"How their posted videos performed (Buffer): views, reactions, comments, reposts, reach per video and per post, last N days. Free. Use when they ask what worked, or before planning the next episodes of a show.","tags":["series"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"days":{"type":"number","description":"default 30"}},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/list_notifications":{"post":{"operationId":"list_notifications","summary":"List notifications","description":"What finished, what is waiting for review, what failed — newest first. Free.","tags":["series"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"unreadOnly":{"type":"boolean","description":""}},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/share_channel":{"post":{"operationId":"share_channel","summary":"Share channel","description":"Give someone access to a channel by email: editor (make videos, edit shows) or viewer. They see it when they sign in with that email. Owner only. Free.","tags":["channels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"person":{"type":"string","description":"their email"},"role":{"type":"string","enum":["editor","viewer"],"description":"default editor"}},"required":["channelId","person"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/remove_member":{"post":{"operationId":"remove_member","summary":"Remove member","description":"Remove someone from a channel. Owner only (people can also remove themselves). Free.","tags":["channels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"person":{"type":"string","description":"their email"}},"required":["channelId","person"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/list_people":{"post":{"operationId":"list_people","summary":"List people","description":"Who owns a channel and who else is on it. Free.","tags":["channels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""}},"required":["channelId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/transfer_ownership":{"post":{"operationId":"transfer_ownership","summary":"Transfer ownership","description":"Hand a channel — or one show — to someone by email. Channel: they become owner, the current owner stays as editor. Show: the show folder (series, episodes, sources) moves into a channel they own (created if needed). Confirm with the person first; this is not undoable from chat. Free.","tags":["channels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"showId":{"type":"string","description":"Only to transfer a single show"},"person":{"type":"string","description":"their email"}},"required":["channelId","person"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/update_channel":{"post":{"operationId":"update_channel","summary":"Update channel","description":"Change a channel: label, promise, audience, compliance, cta (a line every video must end on), brand ({accent, ground, ink, watermark text, logo = a library file path, disclaimer}), bufferChannelIds. Brand and cta lock every show and video in the channel unless a show overrides. Free.","tags":["channels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"patch":{"type":"object","description":"fields to change","additionalProperties":true}},"required":["channelId","patch"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/learn_style":{"post":{"operationId":"learn_style","summary":"Learn style","description":"Learn a visual style from references and apply it: library images/videos (assetIds) and/or pasted HTML/CSS. Derives ground/accent/ink, fonts, and style notes; applies to a video (brand) and/or a show (brand + styleNotes, optionally locked). 5 credits.","tags":["account"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"assetIds":{"type":"array","items":{"type":"string"},"description":"Library images or videos to sample (a brand PDF page exported as an image works too)"},"html":{"type":"string","description":"Raw HTML/CSS from a composition or a site — colors, fonts, motion cues are read from it"},"videoId":{"type":"string","description":"Apply the learned brand to this video"},"channelId":{"type":"string","description":"With showId: apply brand + styleNotes to the show"},"showId":{"type":"string","description":""},"lock":{"type":"boolean","description":"Lock the style on the show so every episode inherits it"}},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/update_show":{"post":{"operationId":"update_show","summary":"Update show","description":"Change a show's settings: label, promise, host, voiceId, format, styleNotes, persona ({name, tone, opener, closer, catchphrases[], never[]} — a named host the director writes every episode as), pacing (calm | standard | fast — scene density), language, maxSeconds, presenter, characters (recurring cast: [{name, role, look, voiceId?}]), policy (hold | approval | digest | autopost | review), disclaimer, brandLock ({logo, accent, ground, ink, displayFont, bodyFont, disclaimer, cta, bannedWords[]} — enforced at render; you can set it but never remove or change a locked disclaimer or drop banned words), brand, cta, defaults (production defaults every episode inherits: {images: 'generate', clips: {provider, count, seconds}, aiVideo: {provider}, musicAssetId, voiceId, sfx: 'one-line sound direction'}). Free.","tags":["channels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"showId":{"type":"string","description":""},"patch":{"type":"object","description":"fields to change","additionalProperties":true}},"required":["channelId","showId","patch"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/research":{"post":{"operationId":"research","summary":"Research","description":"Build knowledge about a topic: crawl one or more sites (same-host links, depth 1-3, up to 80 pages), extract people / companies / funds / products / industries and cited facts, and pull recent news. Files a brief and, with channelId, puts the entities into that channel's knowledge graph. 2 credits per page read + 10 for news. Quote first.","tags":["sources"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"topic":{"type":"string","description":"What this research is about, e.g. \"Hallstone Ventures portfolio\""},"urls":{"type":"array","items":{"type":"string"},"description":"seed URLs to crawl (site home, team page, portfolio page)"},"depth":{"type":"number","description":"link depth from the seeds, 1-3 (default 2)"},"maxPages":{"type":"number","description":"page cap, 1-80 (default 25)"},"news":{"type":"boolean","description":"also search recent news (default true)"},"channelId":{"type":"string","description":"file entities into this channel's graph"}},"required":["topic"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/read_research":{"post":{"operationId":"read_research","summary":"Read research","description":"Read earlier research: all briefs, or one brief in full (entities + facts + news). Free.","tags":["sources"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"briefId":{"type":"string","description":""}},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/create_campaign":{"post":{"operationId":"create_campaign","summary":"Create campaign","description":"Save a batch as a campaign: name, who it is for, the CTA/offer, tags, and the video ids that belong to it. Free.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":""},"channelId":{"type":"string","description":""},"audience":{"type":"string","description":""},"cta":{"type":"string","description":""},"offer":{"type":"string","description":""},"tags":{"type":"array","items":{"type":"string"}},"videoIds":{"type":"array","items":{"type":"string"}},"notes":{"type":"string","description":""}},"required":["name"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/update_campaign":{"post":{"operationId":"update_campaign","summary":"Update campaign","description":"Add or remove videos, or change a campaign's brief. Free.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"campaignId":{"type":"string","description":""},"channelId":{"type":"string","description":""},"name":{"type":"string","description":""},"audience":{"type":"string","description":""},"cta":{"type":"string","description":""},"offer":{"type":"string","description":""},"tags":{"type":"array","items":{"type":"string"}},"addVideoIds":{"type":"array","items":{"type":"string"}},"removeVideoIds":{"type":"array","items":{"type":"string"}},"notes":{"type":"string","description":""}},"required":["campaignId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/list_campaigns":{"post":{"operationId":"list_campaigns","summary":"List campaigns","description":"Campaigns (saved batches) — all, or one in full. Free.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"campaignId":{"type":"string","description":""}},"required":[]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/create_stills":{"post":{"operationId":"create_stills","summary":"Create stills","description":"Make still images — an infographic, a carousel, quote cards, a stat card — as a set of designed slides rendered to PNG. You write the slides from the source (kinds: cover, stat, quote, list, text, compare, cta, image). 15cr per image, up to 12. Formats: square 1080², portrait 1080×1350 (Instagram carousel), story 1080×1920, landscape 1920×1080, x 1600×900.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"name of the set"},"format":{"type":"string","enum":["square","portrait","story","landscape","x"],"description":"default portrait"},"slides":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"kind":{"type":"string","enum":["cover","stat","quote","list","text","compare","cta","image"],"description":""},"eyebrow":{"type":"string","description":""},"title":{"type":"string","description":""},"body":{"type":"string","description":""},"stat":{"type":"string","description":""},"statLabel":{"type":"string","description":""},"quote":{"type":"string","description":""},"attribution":{"type":"string","description":""},"items":{"type":"array","items":{"type":"string"}},"left":{"type":"object","additionalProperties":true},"right":{"type":"object","additionalProperties":true},"imageUrl":{"type":"string","description":""},"footer":{"type":"string","description":""}}}},"brand":{"type":"object","additionalProperties":true,"description":"{ bg, ink, accent, font (Google font name), logoText, dark }"}},"required":["title","slides"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/find_highlights":{"post":{"operationId":"find_highlights","summary":"Find highlights","description":"For footage without speech (gameplay, b-roll, events, music): find the moments — loudness peaks, scene cuts, and a one-line look at each. Returns start/end/peak per moment for clipRef cuts. 5cr per minute of footage.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"assetId":{"type":"string","description":"library video asset"},"count":{"type":"number","description":"how many moments (default 8, max 20)"},"minGap":{"type":"number","description":"seconds between moments (default 6)"},"clipSeconds":{"type":"number","description":"length of each moment (default 6)"},"context":{"type":"string","description":"what the footage is, e.g. \"Valorant ranked match\""},"vision":{"type":"boolean","description":"describe each moment with vision (default true)"}},"required":["assetId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/list_versions":{"post":{"operationId":"list_versions","summary":"List versions","description":"A video's version history (every edit keeps the previous script). Free.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":""}},"required":["videoId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/restore_version":{"post":{"operationId":"restore_version","summary":"Restore version","description":"Go back to an earlier version of a video (then render). Free.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":""},"version":{"type":"number","description":""}},"required":["videoId","version"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/fork_video":{"post":{"operationId":"fork_video","summary":"Fork video","description":"Duplicate a video as a new draft (assets copied) so edits don't touch the original — for variants, A/B, or handing a copy to someone. Free.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":""},"title":{"type":"string","description":""}},"required":["videoId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/search_stock":{"post":{"operationId":"search_stock","summary":"Search stock","description":"Search stock video or photos (Pexels). Returns candidates with preview URLs and durations. Free. Says 'not configured' if no PEXELS_API_KEY.","tags":["library"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","description":""},"kind":{"type":"string","enum":["video","photo"],"description":"default video"},"orientation":{"type":"string","enum":["portrait","landscape","square"],"description":""},"count":{"type":"number","description":"default 8"}},"required":["query"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/search_gif":{"post":{"operationId":"search_gif","summary":"Search gif","description":"Search Giphy for a reaction GIF / loop. Free. Says 'not configured' without GIPHY_API_KEY.","tags":["library"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","description":""},"count":{"type":"number","description":"default 8"}},"required":["query"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/fetch_stock":{"post":{"operationId":"fetch_stock","summary":"Fetch stock","description":"Download a stock pick (from search_stock / search_gif) into the library so it can be attached to a scene. Free.","tags":["library"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"the file url from the search result"},"filename":{"type":"string","description":""},"kind":{"type":"string","enum":["video","image"],"description":""}},"required":["url"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/generate_sfx":{"post":{"operationId":"generate_sfx","summary":"Generate sfx","description":"Generate a sound effect from a description (ElevenLabs). 5cr. Lands in the library.","tags":["library"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","description":"e.g. cash register cha-ching, soft whoosh"},"seconds":{"type":"number","description":"0.5–22, default 2"}},"required":["text"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/generate_music":{"post":{"operationId":"generate_music","summary":"Generate music","description":"Generate an original music bed from a description (ElevenLabs Music). 40cr. Lands in the library; attach_asset makes it the bed.","tags":["library"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"prompt":{"type":"string","description":"e.g. warm lo-fi hip hop, 85 bpm, no vocals, for a cooking show"},"seconds":{"type":"number","description":"10–300, default 30"}},"required":["prompt"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/brand_footage":{"post":{"operationId":"brand_footage","summary":"Brand footage","description":"Brand pass on a finished clip from the library: the channel's logo watermark bottom-right and a branded end card (CTA pill + disclaimer). For footage people made elsewhere and just want stamped. 5cr. Returns a new library asset.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"assetId":{"type":"string","description":"library video asset"},"channelId":{"type":"string","description":"take brand + cta from this channel"},"showId":{"type":"string","description":"show override"},"cta":{"type":"string","description":"end-card line if no channel"},"brand":{"type":"object","additionalProperties":true,"description":"{accent, ground, ink, logo, disclaimer} if no channel"},"endCardSeconds":{"type":"number","description":"default 2.5"}},"required":["assetId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/tools/clean_footage":{"post":{"operationId":"clean_footage","summary":"Clean footage","description":"Clean cut a talking-head clip from the library: transcribe with word timing, drop filler words (um, uh) and dead air longer than maxSilence, pad every cut edge, 30ms audio fades, never split a word. New clip lands in the library. 10cr per minute of source.","tags":["videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"assetId":{"type":"string","description":"library asset id (video/audio)"},"fillers":{"type":"boolean","description":"drop filler words (default true)"},"maxSilence":{"type":"number","description":"collapse silences longer than this many seconds (default 0.6)"},"pad":{"type":"number","description":"seconds kept around each cut edge (default 0.06)"},"language":{"type":"string","description":"ISO code if not English"}},"required":["assetId"]}}}},"responses":{"200":{"description":"Tool result (JSON). Paid tools return `charged` (credits)."},"400":{"description":"Bad arguments — `error` explains"},"401":{"description":"Missing/invalid API key"},"402":{"description":"Insufficient credits — `error` names the shortfall. With a card on file, pay-as-you-go tops up first; `payment_failed (…)` means the card could not be charged."}}}},"/sources":{"post":{"operationId":"post__sources","summary":"Read a source","description":"Alias of POST /tools/inspect_source.","tags":["sources"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Public URL to read (page or PDF)"},"assetIds":{"type":"array","items":{"type":"string"},"description":"Library asset ids (images become stills; video/audio become footage/music; PDF/text become text)"},"text":{"type":"string","description":"Pasted notes or a script the person gave you"},"data":{"type":"object","description":"Structured facts from an API caller (e.g. a token snapshot: symbol, priceUsd, change24hPct, holders…). Every value becomes a quotable fact; numbers are formatted for speech. Optional imageUrl/logoUrl and statsPage inside are used as the still and source link.","additionalProperties":true},"title":{"type":"string","description":"Title for a data source"},"summary":{"type":"string","description":"One-line summary for a data source"},"imageUrl":{"type":"string","description":"Logo/hero image URL for a data source"},"note":{"type":"string","description":"What they said this source is, if useful"}},"required":[]}}}},"responses":{"200":{"description":"OK"}}}},"/quote":{"post":{"operationId":"post__quote","summary":"Quote a video","description":"Alias of POST /tools/quote.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"images":{"type":"string","enum":["none","source","library","generate","auto"],"description":"Visuals policy. 'source' = real stills only (default when a source has stills); 'auto' = stills first, generate only where nothing real exists; 'generate' = generated image on every visual scene (25cr each); 'none' = typography only."},"clips":{"type":"object","description":"AI motion clips made from stills on some scenes, billed per second. Only when asked or configured.","properties":{"provider":{"type":"string","enum":["minimax","kling","seedance-lite","seedance-pro"],"description":"Per second of footage: minimax (MiniMax H3, 768p) 15cr · kling (1080p) 20cr · seedance-lite (Seedance 2.0 fast) 50cr · seedance-pro (Seedance 2.5, native audio, up to 30s) 100cr"},"count":{"type":"number","description":"How many scenes get a clip (1-4)"},"seconds":{"type":"number","description":"Seconds per clip (default 6)"}},"required":["provider","count"]},"aiVideo":{"type":"object","description":"Full AI video: one generated shot for the whole runtime (voice + captions on top). seedance-pro up to 30s; minimax up to 15s. Expensive — quote first.","properties":{"provider":{"type":"string","enum":["minimax","kling","seedance-lite","seedance-pro"],"description":"Per second of footage: minimax (MiniMax H3, 768p) 15cr · kling (1080p) 20cr · seedance-lite (Seedance 2.0 fast) 50cr · seedance-pro (Seedance 2.5, native audio, up to 30s) 100cr"},"withAudio":{"type":"boolean","description":"seedance-pro only: generate ambient audio under the voiceover"},"prompt":{"type":"string","description":"Visual direction for the footage; default derived from the script"},"shots":{"type":"number","description":"Number of shots to stitch. Default: enough to cover the runtime (a 60s MiniMax video = 4 × 15s). Each shot is seeded with the last frame of the previous one."},"secondsPerShot":{"type":"number","description":"Length of each shot (default: the provider maximum — minimax 15, seedance-pro 30, kling 10)"},"prompts":{"type":"array","items":{"type":"string"},"description":"One visual direction per shot, for a story that changes scene"}},"required":["provider"]},"avatar":{"type":"boolean","description":"Include a presenter"},"scenes":{"type":"number","description":"Expected scene count (default 6)"},"targetSeconds":{"type":"number","description":"Runtime in seconds — drives script/voice/render units and AI footage cost. Default 30"},"voiceover":{"type":"boolean","description":"Default true"},"render":{"type":"boolean","description":"Default true"}},"required":[]}}}},"responses":{"200":{"description":"OK"}}}},"/videos":{"post":{"operationId":"post__videos","summary":"Create a video","description":"Alias of POST /tools/create_video.","tags":["videos"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"engine":{"type":"string","enum":["opus","director"],"description":"'opus' (default for data, a page, a token or a brief): the designer writes the whole video — layout, motion, charts, voiceover — from the source pack's verbatim facts; pass sourcePackId/brief/format/targetSeconds and no script. 'director': your own script (footage edits, presenters, AI clips, music videos, shows)."},"planId":{"type":"string","description":"Make the video from a saved plan (after \"make it\"): the plan's script, settings and files are used; anything else you pass overrides. The script draft is not charged again."},"brief":{"type":"string","description":"What the video is about and for — the ask in your words, including audience, angle, CTA, and anything the person specified"},"script":{"type":"object","description":"The script you wrote (see \"Writing the script\"). Omit only for a quick engine-written first pass.","properties":{"title":{"type":"string","description":"≤ 80 chars, specific"},"vo":{"type":"string","description":"Full voiceover narration, ~2.5 words/second"},"cta":{"type":"string","description":"Closing line"},"music":{"type":"object","properties":{"mood":{"type":"string","enum":["sparse","tense","driving","hype","stately","urgent","triumphant","warm"],"description":""},"bpm":{"type":"number","description":""}}},"scenes":{"type":"array","items":{"type":"object","required":["type","text","duration"],"properties":{"type":{"type":"string","enum":["title","visual","chart","data","quote","cta"],"description":""},"text":{"type":"string","description":"On-screen text, 2-10 words"},"duration":{"type":"number","description":"Seconds"},"grounding":{"type":"string","description":"Exact source phrase this rests on; \"\" for framing/CTA"},"stillIndex":{"type":"number","description":"Index of a source still to show (each at most once)"},"clipRef":{"type":"object","description":"A cut from indexed footage (see index_footage): which asset, where to start, how long","properties":{"assetId":{"type":"string","description":""},"start":{"type":"number","description":"seconds into the file"},"duration":{"type":"number","description":"seconds (≤ scene duration)"}},"required":["assetId","start"]},"imagePrompt":{"type":"string","description":"Generated image prompt — only when images allow generation and no real still fits"},"frame":{"type":"string","enum":["phone","laptop","card"],"description":"Show this scene's image inside a device: phone for app screens, laptop for websites and dashboards, card for a plain screenshot. Use on almost every screenshot beat."},"stats":{"type":"array","description":"Stat pills for a data scene instead of one figure, e.g. [{value:\"84.6k\",label:\"stars\"},{value:\"448\",label:\"forks\"}] (2–4)","items":{"type":"object","properties":{"value":{"type":"string","description":""},"label":{"type":"string","description":""}}}},"transition":{"type":"string","enum":["wipe","cut","dissolve"],"description":"How this scene hands off to the next: wipe (accent bar sweep, the pack default), cut (hard cut), dissolve (this scene fades out, the next fades in). Mix them: dissolve into a mood shot, cut into a stat, wipe into the CTA."},"sfx":{"description":"Sound effect on this scene: 'impact' | 'whoosh' | 'riser' | 'tick' | 'keys' | 'none', or { assetId } for your own library audio (generate_sfx lands one there; optional volume 0–1). Omit for the pack's automatic pick."},"chart":{"type":"object","description":"chart scenes: a real chart drawn from your numbers. line = draw-on with glowing endpoint and the last value labeled; bars = grow-in, accent above the baseline / negativeColor below, value labels. text = the title above it.","properties":{"kind":{"type":"string","enum":["line","bars"],"description":""},"series":{"type":"array","description":"number[] or [{ t: label, v: number }] in order (2–60 points; bars ≤ 12)","items":{}},"labels":{"type":"array","items":{"type":"string","description":""},"description":"x labels (bars: one per bar; line: first/last shown)"},"color":{"type":"string","description":"hex; default accent (line: red-ish when the series ends lower)"},"negativeColor":{"type":"string","description":"hex for values below the baseline"},"baseline":{"description":"bars: 0 (zero line, negatives hang down) or 'min' (default when all values are positive)"},"valueFormat":{"type":"string","enum":["usd","pct","raw"],"description":""},"title":{"type":"string","description":"small caption under the chart: source, window"}},"required":["kind","series"]},"motion":{"type":"string","enum":["kinetic","countup","slide","zoom","typewriter","still","slam"],"description":"How the scene moves. Default is picked per type (title→kinetic, data→countup, visual→slide/zoom, quote→typewriter); slam = hit-in with a shake for a hero number or word; set it to change rhythm."},"asset":{"type":"object","description":"Media for this scene: a public http(s) image or mp4 url (fetched at create time, full-bleed under the text, videos muted) or a library file path","properties":{"url":{"type":"string","description":"https://… image or mp4"},"kind":{"type":"string","enum":["image","video"],"description":"inferred from the file when omitted"},"path":{"type":"string","description":"library path, e.g. libraries/u/<scope>/files/<assetId>.mp4"},"mediaStart":{"type":"number","description":"video: seconds into the file to start"}}},"clipPrompt":{"type":"string","description":"Motion description for an AI clip — only when clips are enabled"}}}}},"required":["title","vo","scenes"]},"sourcePackId":{"type":"string","description":"From inspect_source. Omit only for a deliberately ungrounded topic video."},"sourcePackIds":{"type":"array","items":{"type":"string","description":""},"description":"Several sources at once (multi-link briefs, market_data + a page) — merged into one grounded pack"},"format":{"type":"string","enum":["9:16","16:9","1:1","4:5"],"description":"Aspect ratio. Default 9:16."},"lyrics":{"type":"string","description":"music-video only: the lyrics to show on screen, one line per scene in order. Leave out for a pure visual (default)."},"tier":{"type":"string","enum":["fast","standard","cinematic"],"description":"Quality tier you told them: fast = stills + motion; standard = 1080p AI clips (kling); cinematic = full AI footage (seedance-pro). Picks the clip model when clips has no provider."},"plan":{"type":"object","description":"The brief you settled on, saved on the video: { message, audience, outcome, look, stated: [what they told you], inferred: [what you decided and why] }","additionalProperties":true},"workflow":{"type":"string","enum":["faceless-explainer","product-launch","motion-graphics","talking-head","slideshow","general","music-video"],"description":"Composition approach. music-video for a person's own track (no VO, no captions, no SFX, no on-screen text unless lyrics; runtime = the track); product-launch for a company/site/product page; faceless-explainer for an article/notes; talking-head when a presenter is used; motion-graphics for a short unnarrated stat hit."},"images":{"type":"string","enum":["none","source","library","generate","auto"],"description":"Visuals policy. 'source' = real stills only (default when a source has stills); 'auto' = stills first, generate only where nothing real exists; 'generate' = generated image on every visual scene (25cr each); 'none' = typography only."},"clips":{"type":"object","description":"AI motion clips made from stills on some scenes, billed per second. Only when asked or configured.","properties":{"provider":{"type":"string","enum":["minimax","kling","seedance-lite","seedance-pro"],"description":"Per second of footage: minimax (MiniMax H3, 768p) 15cr · kling (1080p) 20cr · seedance-lite (Seedance 2.0 fast) 50cr · seedance-pro (Seedance 2.5, native audio, up to 30s) 100cr"},"count":{"type":"number","description":"How many scenes get a clip (1-4)"},"seconds":{"type":"number","description":"Seconds per clip (default 6)"}},"required":["provider","count"]},"aiVideo":{"type":"object","description":"Full AI video: one generated shot for the whole runtime (voice + captions on top). seedance-pro up to 30s; minimax up to 15s. Expensive — quote first.","properties":{"provider":{"type":"string","enum":["minimax","kling","seedance-lite","seedance-pro"],"description":"Per second of footage: minimax (MiniMax H3, 768p) 15cr · kling (1080p) 20cr · seedance-lite (Seedance 2.0 fast) 50cr · seedance-pro (Seedance 2.5, native audio, up to 30s) 100cr"},"withAudio":{"type":"boolean","description":"seedance-pro only: generate ambient audio under the voiceover"},"prompt":{"type":"string","description":"Visual direction for the footage; default derived from the script"},"shots":{"type":"number","description":"Number of shots to stitch. Default: enough to cover the runtime (a 60s MiniMax video = 4 × 15s). Each shot is seeded with the last frame of the previous one."},"secondsPerShot":{"type":"number","description":"Length of each shot (default: the provider maximum — minimax 15, seedance-pro 30, kling 10)"},"prompts":{"type":"array","items":{"type":"string"},"description":"One visual direction per shot, for a story that changes scene"}},"required":["provider"]},"avatar":{"type":"object","description":"A talking presenter lip-synced to the voiceover. Per second of runtime: stock 3cr/s, photo 25cr/s.","properties":{"mode":{"type":"string","enum":["photo","stock"],"description":"'photo' animates a library photo with a clear face; 'stock' uses a stock presenter"},"imageAssetId":{"type":"string","description":"photo mode: library asset id of the face photo"},"avatarId":{"type":"string","description":"stock mode: presenter id or a hint like 'emily', 'marcus', 'any_female'. Vertical presenters are picked automatically for 9:16 / 4:5."}},"required":["mode"]},"public":{"type":"boolean","description":"true = the finished file is playable without a key (share links, feeds). Default false: media needs the keyed url / mediaKey returned with the video."},"mode":{"type":"string","enum":["data","story"],"description":"engine 'opus' only: 'story' = a narrative/meme video with reaction-GIF cutaways (pass clipQueries); omit for data videos"},"clipQueries":{"type":"array","items":{"type":"string"},"description":"engine 'opus' + mode 'story': 3–5 short GIF searches for cutaways (animals/anonymous people only). Prefix 'stock:' for licensed stock footage instead of GIFs (required for political content)."},"style":{"type":"string","description":"engine 'opus' only: a look from the style bank (e.g. comic, arcade, nature-doc, trading-terminal, luxury-minimal, chaos-meme); omit to let the designer choose"},"layout":{"type":"string","enum":["full","split"],"description":"'split' = the presenter (avatar or their footage) fills the bottom third while your scenes/motion graphics play in the top two-thirds — the talking-head-with-changing-content format. Needs avatar or footage. Default 'full'."},"captions":{"type":"boolean","description":"Timed captions from the voiceover. Default true."},"voiceId":{"type":"string","description":"Voice for the voiceover (a show's configured voice, or a cloned voice id the person owns). Default: house voice."},"language":{"type":"string","description":"Language for narration and on-screen text (e.g. \"Spanish\", \"pt-BR\", \"Japanese\"). Default English / the source language."},"voiceover":{"type":"boolean","description":"false = silent piece (no narration, no captions). Default true; auto-false under 3s."},"targetSeconds":{"type":"number","description":"Target runtime in seconds — anything from 1 to long form (a 10-minute episode = 600). Default follows the source (25-40s). Cost scales with it."},"pacing":{"type":"string","enum":["calm","standard","fast"],"description":"Scene density: calm ≈ 9s scenes (documentary), standard ≈ 6s, fast ≈ 3.5s (roast, hype). Default standard, or the show's setting."},"libraryAssetIds":{"type":"array","items":{"type":"string"},"description":"Library assets to place: images/videos go on visual scenes, an audio file becomes the music bed"},"brand":{"type":"object","description":"Override brand tokens (otherwise taken from the source page)","properties":{"pack":{"type":"string","enum":["classic","editorial","bold","cinematic"],"description":"Style pack: one coherent look — editorial (serif, warm, slow), bold (condensed uppercase, hot accent, fast), cinematic (letterbox, filmic grade, slow push-ins), classic (default). Sets fonts, palette, motion, grade and sound design; explicit brand fields still win."},"accent":{"type":"string","description":"hex color"},"ground":{"type":"string","description":"hex background"},"ink":{"type":"string","description":"hex text"},"displayFont":{"type":"string","description":"Google font"},"bodyFont":{"type":"string","description":"Google font"},"watermark":{"type":"string","description":"Small corner text; empty string removes it"},"disclaimer":{"type":"string","description":"Required legal line shown for the whole video, exactly as given"}}},"channelId":{"type":"string","description":"Make it as an episode of this channel"},"showId":{"type":"string","description":"…in this show"},"seriesId":{"type":"string","description":"…in this series"}},"required":["brief"]}}}},"responses":{"200":{"description":"OK"}}}},"/videos/{id}":{"get":{"operationId":"get__videos_id_","summary":"Get a video","description":"Alias of POST /tools/get_video.","tags":["videos"],"responses":{"200":{"description":"OK"}}}},"/videos/{id}/render":{"post":{"operationId":"post__videos_id_render","summary":"Render a video","description":"Alias of POST /tools/render_video.","tags":["videos"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":"Video id, e.g. vid-012"}},"required":["videoId"]}}}},"responses":{"200":{"description":"OK"}}}},"/videos/{id}/edit":{"post":{"operationId":"post__videos_id_edit","summary":"Edit a video","description":"Alias of POST /tools/edit_video.","tags":["videos"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":"Video id"},"notes":{"type":"string","description":"The person's edit verbatim, plus your concrete reading of it"},"script":{"type":"object","description":"The script you wrote (see \"Writing the script\"). Omit only for a quick engine-written first pass.","properties":{"title":{"type":"string","description":"≤ 80 chars, specific"},"vo":{"type":"string","description":"Full voiceover narration, ~2.5 words/second"},"cta":{"type":"string","description":"Closing line"},"music":{"type":"object","properties":{"mood":{"type":"string","enum":["sparse","tense","driving","hype","stately","urgent","triumphant","warm"],"description":""},"bpm":{"type":"number","description":""}}},"scenes":{"type":"array","items":{"type":"object","required":["type","text","duration"],"properties":{"type":{"type":"string","enum":["title","visual","chart","data","quote","cta"],"description":""},"text":{"type":"string","description":"On-screen text, 2-10 words"},"duration":{"type":"number","description":"Seconds"},"grounding":{"type":"string","description":"Exact source phrase this rests on; \"\" for framing/CTA"},"stillIndex":{"type":"number","description":"Index of a source still to show (each at most once)"},"clipRef":{"type":"object","description":"A cut from indexed footage (see index_footage): which asset, where to start, how long","properties":{"assetId":{"type":"string","description":""},"start":{"type":"number","description":"seconds into the file"},"duration":{"type":"number","description":"seconds (≤ scene duration)"}},"required":["assetId","start"]},"imagePrompt":{"type":"string","description":"Generated image prompt — only when images allow generation and no real still fits"},"frame":{"type":"string","enum":["phone","laptop","card"],"description":"Show this scene's image inside a device: phone for app screens, laptop for websites and dashboards, card for a plain screenshot. Use on almost every screenshot beat."},"stats":{"type":"array","description":"Stat pills for a data scene instead of one figure, e.g. [{value:\"84.6k\",label:\"stars\"},{value:\"448\",label:\"forks\"}] (2–4)","items":{"type":"object","properties":{"value":{"type":"string","description":""},"label":{"type":"string","description":""}}}},"transition":{"type":"string","enum":["wipe","cut","dissolve"],"description":"How this scene hands off to the next: wipe (accent bar sweep, the pack default), cut (hard cut), dissolve (this scene fades out, the next fades in). Mix them: dissolve into a mood shot, cut into a stat, wipe into the CTA."},"sfx":{"description":"Sound effect on this scene: 'impact' | 'whoosh' | 'riser' | 'tick' | 'keys' | 'none', or { assetId } for your own library audio (generate_sfx lands one there; optional volume 0–1). Omit for the pack's automatic pick."},"chart":{"type":"object","description":"chart scenes: a real chart drawn from your numbers. line = draw-on with glowing endpoint and the last value labeled; bars = grow-in, accent above the baseline / negativeColor below, value labels. text = the title above it.","properties":{"kind":{"type":"string","enum":["line","bars"],"description":""},"series":{"type":"array","description":"number[] or [{ t: label, v: number }] in order (2–60 points; bars ≤ 12)","items":{}},"labels":{"type":"array","items":{"type":"string","description":""},"description":"x labels (bars: one per bar; line: first/last shown)"},"color":{"type":"string","description":"hex; default accent (line: red-ish when the series ends lower)"},"negativeColor":{"type":"string","description":"hex for values below the baseline"},"baseline":{"description":"bars: 0 (zero line, negatives hang down) or 'min' (default when all values are positive)"},"valueFormat":{"type":"string","enum":["usd","pct","raw"],"description":""},"title":{"type":"string","description":"small caption under the chart: source, window"}},"required":["kind","series"]},"motion":{"type":"string","enum":["kinetic","countup","slide","zoom","typewriter","still","slam"],"description":"How the scene moves. Default is picked per type (title→kinetic, data→countup, visual→slide/zoom, quote→typewriter); slam = hit-in with a shake for a hero number or word; set it to change rhythm."},"asset":{"type":"object","description":"Media for this scene: a public http(s) image or mp4 url (fetched at create time, full-bleed under the text, videos muted) or a library file path","properties":{"url":{"type":"string","description":"https://… image or mp4"},"kind":{"type":"string","enum":["image","video"],"description":"inferred from the file when omitted"},"path":{"type":"string","description":"library path, e.g. libraries/u/<scope>/files/<assetId>.mp4"},"mediaStart":{"type":"number","description":"video: seconds into the file to start"}}},"clipPrompt":{"type":"string","description":"Motion description for an AI clip — only when clips are enabled"}}}}},"required":["title","vo","scenes"]},"language":{"type":"string","description":"Switch the video's language as part of the edit (prefer translate_video for a straight translation)"}},"required":["videoId","notes"]}}}},"responses":{"200":{"description":"OK"}}}},"/videos/{id}/publish":{"post":{"operationId":"post__videos_id_publish","summary":"Publish a video","description":"Alias of POST /tools/publish.","tags":["videos"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","description":""},"destination":{"type":"string","enum":["share-link","download","buffer","youtube"],"description":"youtube = upload straight to their connected YouTube channel (unlisted unless autopost); say 'connect YouTube in Settings → Publishing' if it isn't"},"privacy":{"type":"string","enum":["public","unlisted","private"],"description":"youtube only; default unlisted"},"caption":{"type":"string","description":"Post text (buffer)"},"captions":{"type":"object","additionalProperties":{"type":"string"},"description":"Per-service post text, e.g. {\"instagram\": \"…link in bio\", \"tiktok\": \"…\"}; services without one use caption"},"autopost":{"type":"boolean","description":"publish immediately instead of a draft"},"channelIds":{"type":"array","items":{"type":"string"},"description":"Buffer channel ids to post to (default: the show's picks, else the account default)"}},"required":["videoId","destination"]}}}},"responses":{"200":{"description":"OK"}}}},"/series/{channelId}/{showId}/{seriesId}/run":{"post":{"operationId":"post__series_channelId_showId_seriesId_run","summary":"Run a series","description":"Alias of POST /tools/run_series.","tags":["series"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"type":"string","description":""},"showId":{"type":"string","description":""},"seriesId":{"type":"string","description":""},"dry":{"type":"boolean","description":"Preview only"}},"required":["channelId","showId","seriesId"]}}}},"responses":{"200":{"description":"OK"}}}},"/account":{"get":{"operationId":"get__account","summary":"Account","description":"Alias of POST /tools/read_wallet.","tags":["billing"],"responses":{"200":{"description":"OK"}}}},"/billing/balance":{"get":{"operationId":"balance","summary":"Balance","tags":["billing"],"responses":{"200":{"description":"{ credits, plan, usdPerCredit }"}}}},"/billing/topup":{"post":{"operationId":"topup","summary":"Top up","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"amountUsd":{"type":"number"}},"required":["amountUsd"]}}}},"responses":{"200":{"description":"{ url }"}}}},"/videos/from-data":{"post":{"operationId":"create_video_from_data","summary":"Create a video from data","tags":["videos"],"description":"For system integrations (e.g. a token page, a listing, a filing). Every value in `data` becomes a quotable fact. Returns 202 while rendering; `video.rendered` arrives on your webhook. Creation with `clips`/`aiVideo` can take minutes — pass `pacing` (calm | standard | fast) for scene density; pass `async: true` to get 202 + `jobId` immediately, then poll `GET /v1/jobs/{jobId}` (videoId appears once the script/voice/images exist) or listen for `video.created`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true,"description":"Your structured facts (symbol, priceUsd, change24hPct, holders, …). Optional: omit for a creative brief-driven video."},"script":{"type":"object","description":"Optional: your own script {title, vo, scenes[]} — the engine records and renders it as written"},"channelId":{"type":"string","description":"Make it as an episode of this channel (with showId + seriesId)"},"showId":{"type":"string"},"seriesId":{"type":"string"},"external_id":{"type":"string","description":"Your own id, echoed back in the response and webhooks"},"title":{"type":"string"},"summary":{"type":"string"},"imageUrl":{"type":"string","description":"Logo / hero image used as the opening still"},"sourceUrl":{"type":"string"},"brief":{"type":"string","description":"Angle and audience in plain words"},"cta":{"type":"string","description":"Closing line, verbatim, e.g. \"See FLOCK on tokenslop.fun\""},"format":{"type":"string","enum":["9:16","16:9","1:1","4:5"],"default":"9:16"},"targetSeconds":{"type":"number","default":30,"description":"Runtime in seconds, 1 to long form; cost scales (script 20/min, voice 30/30s, render 10/min)"},"images":{"type":"string","enum":["source","none","auto","generate"],"default":"source"},"brand":{"type":"object","properties":{"accent":{"type":"string"},"ground":{"type":"string"},"watermark":{"type":"string"},"disclaimer":{"type":"string"}}},"voiceId":{"type":"string","description":"Narration voice: a house voice (list_voices) or a voice you cloned. Default: George (house)."},"language":{"type":"string","description":"Narration, on-screen text, title and caption language, e.g. \"Spanish\", \"Portuguese (Brazil)\", \"pt-BR\", \"Japanese\", \"Chinese (Simplified)\", \"Hindi\", \"Arabic\". Names, tickers and figures stay as written. Default English."},"voiceover":{"type":"boolean","default":true,"description":"false = silent piece"},"captions":{"type":"boolean","default":true},"clips":{"type":"object","description":"{ provider: minimax|kling|seedance-lite|seedance-pro, count, seconds } — AI clips on some scenes, billed per second"},"aiVideo":{"type":"object","description":"{ provider, withAudio, prompt } — one generated shot for the whole runtime (seedance-pro up to 30s). Expensive: quote first."},"avatar":{"type":"object","description":"{ mode: stock|photo, avatarId, imageAssetId } — presenter, 300cr"},"layout":{"type":"string","enum":["full","split"],"description":"'split': presenter fills the bottom third, scenes play in the top two-thirds (needs avatar or footage)"},"render":{"type":"boolean","default":true},"async":{"type":"boolean","default":false,"description":"202 + jobId at once; poll GET /v1/jobs/{jobId}"},"public":{"type":"boolean","default":false,"description":"Finished file playable without a key. Otherwise use the keyed url / renderUrl / mediaKey returned on the video, the job, and the webhook."},"musicAssetId":{"type":"string","description":"Library audio asset to use as the music bed"},"music":{"type":"object","description":"{ mood, bpm, generate: true, seconds }: generate an original bed for this video (40cr) and use it","properties":{"mood":{"type":"string"},"bpm":{"type":"number"},"generate":{"type":"boolean"},"seconds":{"type":"number"}}},"libraryAssetIds":{"type":"array","items":{"type":"string"},"description":"Your library files (footage, images, audio) to place"}}}}}},"responses":{"202":{"description":"Created and rendering: { videoId, status, title, duration, charged, url, renderUrl, thumbnail, watchUrl, mediaKey, public }"},"402":{"description":"Insufficient credits"}}}},"/webhooks":{"get":{"summary":"List webhooks","tags":["webhooks"],"responses":{"200":{"description":"OK"}}},"post":{"summary":"Register a webhook","tags":["webhooks"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string"},"events":{"type":"array","items":{"type":"string","enum":["*","video.created","video.rendered","video.render_failed","episode.ready","episode.published","series.error"]}}}}}}},"responses":{"200":{"description":"Returns the webhook with its signing secret (shown once)"}}}},"/webhooks/{id}":{"delete":{"summary":"Remove a webhook","tags":["webhooks"],"responses":{"200":{"description":"OK"}}}},"/webhooks/{id}/deliveries":{"get":{"operationId":"webhook_deliveries","summary":"Webhook deliveries","tags":["webhooks"],"responses":{"200":{"description":"{ id, deliveries: [{ at, event, status, error, ms }] }"}}}},"/jobs/{id}":{"get":{"operationId":"get_job","summary":"Get a job","tags":["videos"],"description":"For `async: true` calls. `videoId` appears once the script, voice and images exist; `media` carries keyed URLs once rendered.","responses":{"200":{"description":"Job","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"404":{"description":"No such job for this account"}}}},"/library/upload":{"post":{"operationId":"library_upload","summary":"Upload to the library","tags":["library"],"description":"Returns an assetId for libraryAssetIds, musicAssetId, avatar.imageAssetId, brand_footage or attach_asset. 250 MB max. Social links are resolved to the media (public posts only).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["filename"],"properties":{"filename":{"type":"string"},"url":{"type":"string","description":"https URL of the file, or a social post permalink"},"data":{"type":"string","description":"base64 file contents (instead of url)"}}}}}},"responses":{"200":{"description":"{ ok, assetId, filename, mimeType, url }"},"413":{"description":"Over 250 MB"},"422":{"description":"Could not fetch the media"}}}},"/embed/token":{"post":{"operationId":"embed_token","summary":"Mint an embed token","tags":["embed"],"description":"Iframe the returned `url` (https://monkeygun.com/embed/studio#t=…). The studio runs on your account for billing and ownership; every video and chat is tagged with `externalUserId`, and the page posts `{ type: \"monkeygun\", event: \"video.created\" | \"video.rendered\", videoId, url }` to the parent window. Rendered-video webhooks carry `externalUserId` too. TTL 5 minutes to 7 days (default 12 h).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["externalUserId"],"properties":{"externalUserId":{"type":"string","description":"Your user id (wallet, account id)"},"channelId":{"type":"string"},"showId":{"type":"string"},"brand":{"type":"object","description":"Brand lock forced on everything made in this session"},"origin":{"type":"string","description":"Parent page origin for postMessage"},"ttlSeconds":{"type":"number"}}}}}},"responses":{"200":{"description":"{ ok, token, expiresAt, url }"}}}}}}