[{"data":1,"prerenderedAt":1402},["ShallowReactive",2],{"pricing-plans":3,"content-page-\u002Fdocs\u002Fvideo":4,"api-docs-metadata":909,"i-ph:list":3,"i-ph:caret-right":3,"i-ph:copy":3,"i-ph:caret-down":3,"i-ph:twitter-logo":3,"i-ph:youtube-logo":3},null,{"id":5,"title":6,"body":7,"description":899,"extension":900,"meta":901,"navigation":904,"path":905,"seo":906,"stem":907,"__hash__":908},"all\u002Fdocs\u002Fvideo.md","Video",{"type":8,"value":9,"toc":878},"minimark",[10,14,32,50,55,102,106,114,117,122,248,257,264,267,328,339,343,349,352,442,458,462,468,475,553,560,570,576,579,704,708,722,807,816,820,874],[11,12,6],"h1",{"id":13},"video",[15,16,17,18,21,22,25,26,31],"p",{},"Bannx renders ",[19,20,13],"strong",{}," the same way it renders images: a video template is a set of ",[19,23,24],{},"scenes"," built in the ",[27,28,30],"a",{"href":29},"\u002Fvideo","video editor",", with variables you can override per render. The pipeline produces MP4s server-side (frames are rasterized in Node — no per-render browser), plus single-frame stills and bulk generation from data rows.",[33,34,35],"blockquote",{},[15,36,37,40,41,44,45,49],{},[19,38,39],{},"Authentication note:"," the video endpoints currently use ",[19,42,43],{},"dashboard session authentication"," — they power the video editor and are not yet callable with an ",[46,47,48],"code",{},"Authorization: Bearer"," API key.",[51,52,54],"h2",{"id":53},"concepts","Concepts",[56,57,58,90,96],"ul",{},[59,60,61,64,65,68,69,68,72,68,75,68,78,81,82,85,86,89],"li",{},[19,62,63],{},"Project"," — the serialized editor document: ",[46,66,67],{},"name",", ",[46,70,71],{},"scenes[]",[46,73,74],{},"tracks",[46,76,77],{},"music",[46,79,80],{},"assets",". The editor keeps this in sync; render endpoints accept it as the ",[46,83,84],{},"project"," payload alongside the video template's ",[46,87,88],{},"id",".",[59,91,92,95],{},[19,93,94],{},"Scenes"," — each scene is a timed segment with layers (text, images, video, audio, Lottie). Variables work like image templates: mark a field once, override it per render.",[59,97,98,101],{},[19,99,100],{},"Renderers"," — previews run in the editor (HTML or Takumi); server MP4 renders rasterize frames with the Takumi engine in Node, then encode and upload.",[51,103,105],{"id":104},"render-an-mp4","Render an MP4",[107,108,110,111],"h3",{"id":109},"post-apivideorender","POST ",[46,112,113],{},"\u002Fapi\u002Fvideo\u002Frender",[15,115,116],{},"Enqueues a render job and returns a job ID to poll.",[15,118,119],{},[19,120,121],{},"Request body:",[123,124,125,141],"table",{},[126,127,128],"thead",{},[129,130,131,135,138],"tr",{},[132,133,134],"th",{},"Field",[132,136,137],{},"Type",[132,139,140],{},"Description",[142,143,144,160,174,190,205,220],"tbody",{},[129,145,146,151,154],{},[147,148,149],"td",{},[46,150,88],{},[147,152,153],{},"string",[147,155,156,159],{},[19,157,158],{},"Required."," The video template ID.",[129,161,162,166,169],{},[147,163,164],{},[46,165,84],{},[147,167,168],{},"object",[147,170,171,173],{},[19,172,158],{}," The serialized editor project.",[129,175,176,181,184],{},[147,177,178],{},[46,179,180],{},"width",[147,182,183],{},"number",[147,185,186,187,89],{},"320–3840. Default: ",[46,188,189],{},"1920",[129,191,192,197,199],{},[147,193,194],{},[46,195,196],{},"height",[147,198,183],{},[147,200,201,202,89],{},"180–2160. Default: ",[46,203,204],{},"1080",[129,206,207,212,214],{},[147,208,209],{},[46,210,211],{},"fps",[147,213,183],{},[147,215,216,217,89],{},"1–60. Default: ",[46,218,219],{},"30",[129,221,222,227,239],{},[147,223,224],{},[46,225,226],{},"quality",[147,228,229,232,233,232,236],{},[46,230,231],{},"draft"," | ",[46,234,235],{},"standard",[46,237,238],{},"high",[147,240,241,242,244,245,247],{},"Default: ",[46,243,235],{},". ",[46,246,231],{}," caps capture width at 960px for fast previews.",[15,249,250,253,254],{},[19,251,252],{},"Response:"," ",[46,255,256],{},"{ \"jobId\": \"…\" }",[107,258,260,261],{"id":259},"get-apivideorenderjobid","GET ",[46,262,263],{},"\u002Fapi\u002Fvideo\u002Frender\u002F:jobId",[15,265,266],{},"Poll the job until it finishes.",[123,268,269,279],{},[126,270,271],{},[129,272,273,276],{},[132,274,275],{},"Status",[132,277,278],{},"Response shape",[142,280,281,308,318],{},[129,282,283,286],{},[147,284,285],{},"Rendering",[147,287,288,291,292,295,296,295,299,295,302,295,305],{},[46,289,290],{},"{ \"status\": \"rendering\", \"progress\": 0.35, \"totalFrames\": 180, \"stage\": \"frames\" }"," — stages: ",[46,293,294],{},"frames"," → ",[46,297,298],{},"audio",[46,300,301],{},"encode",[46,303,304],{},"upload",[46,306,307],{},"done",[129,309,310,313],{},[147,311,312],{},"Done",[147,314,315],{},[46,316,317],{},"{ \"status\": \"done\", \"progress\": 1, \"url\": \"https:\u002F\u002F…\u002Fvideo-media\u002F….mp4\", \"totalFrames\": 180 }",[129,319,320,323],{},[147,321,322],{},"Failed",[147,324,325],{},[46,326,327],{},"{ \"status\": \"error\", \"progress\": 0.2, \"error\": \"…\" }",[15,329,330,331,334,335,338],{},"Progress runs 0–0.8 during frame capture; the remainder covers audio, encoding, and upload. Errors: ",[46,332,333],{},"400"," missing jobId, ",[46,336,337],{},"404"," unknown job.",[51,340,342],{"id":341},"render-a-still-frame","Render a still frame",[107,344,110,346],{"id":345},"post-apivideostill",[46,347,348],{},"\u002Fapi\u002Fvideo\u002Fstill",[15,350,351],{},"Synchronous — returns raw image bytes of one frame. Useful for thumbnails and scene previews.",[123,353,354,364],{},[126,355,356],{},[129,357,358,360,362],{},[132,359,134],{},[132,361,137],{},[132,363,140],{},[142,365,366,379,394,407,420],{},[129,367,368,372,374],{},[147,369,370],{},[46,371,84],{},[147,373,168],{},[147,375,376,378],{},[19,377,158],{}," Serialized editor project.",[129,380,381,386,388],{},[147,382,383],{},[46,384,385],{},"time",[147,387,183],{},[147,389,390,391,89],{},"Seek position in seconds. Default: ",[46,392,393],{},"0",[129,395,396,400,402],{},[147,397,398],{},[46,399,180],{},[147,401,183],{},[147,403,404,405,89],{},"64–3840. Default: ",[46,406,189],{},[129,408,409,413,415],{},[147,410,411],{},[46,412,196],{},[147,414,183],{},[147,416,417,418,89],{},"64–2160. Default: ",[46,419,204],{},[129,421,422,427,438],{},[147,423,424],{},[46,425,426],{},"format",[147,428,429,232,432,232,435],{},[46,430,431],{},"png",[46,433,434],{},"webp",[46,436,437],{},"svg",[147,439,241,440,89],{},[46,441,431],{},[15,443,444,446,447,68,450,453,454,457],{},[19,445,252],{}," raw image body (",[46,448,449],{},"image\u002Fpng",[46,451,452],{},"image\u002Fwebp",", or ",[46,455,456],{},"image\u002Fsvg+xml","). Video and Lottie layers are omitted from stills (server-side rasterization).",[51,459,461],{"id":460},"bulk-generation","Bulk generation",[107,463,110,465],{"id":464},"post-apivideobulk",[46,466,467],{},"\u002Fapi\u002Fvideo\u002Fbulk",[15,469,470,471,474],{},"One MP4 per content row — the video equivalent of bulk image generation. Each row's ",[46,472,473],{},"data"," is merged into the project's variables.",[123,476,477,487],{},[126,478,479],{},[129,480,481,483,485],{},[132,482,134],{},[132,484,137],{},[132,486,140],{},[142,488,489,502,514,535],{},[129,490,491,495,497],{},[147,492,493],{},[46,494,88],{},[147,496,153],{},[147,498,499,501],{},[19,500,158],{}," Video template ID.",[129,503,504,508,510],{},[147,505,506],{},[46,507,84],{},[147,509,168],{},[147,511,512,378],{},[19,513,158],{},[129,515,516,521,526],{},[147,517,518],{},[46,519,520],{},"rows",[147,522,523],{},[46,524,525],{},"{ name, data }[]",[147,527,528,531,532,534],{},[19,529,530],{},"Required",", at least one. ",[46,533,473],{}," = variable overrides for that video.",[129,536,537,547,550],{},[147,538,539,68,541,68,543,68,545],{},[46,540,180],{},[46,542,196],{},[46,544,211],{},[46,546,226],{},[147,548,549],{},"—",[147,551,552],{},"Same ranges\u002Fdefaults as single render.",[15,554,555,253,557],{},[19,556,252],{},[46,558,559],{},"{ \"jobId\": \"…\", \"total\": 12, \"creditsNeeded\": 120 }",[15,561,562,565,566,569],{},[19,563,564],{},"Credits:"," 10 credits per successful video; failed rows are not billed (",[46,567,568],{},"402"," when the space has insufficient credits). Each row is retried up to 3 times.",[107,571,260,573],{"id":572},"get-apivideobulkjobidstream",[46,574,575],{},"\u002Fapi\u002Fvideo\u002Fbulk\u002F:jobId\u002Fstream",[15,577,578],{},"Server-sent events with live progress (every ~500ms):",[580,581,586],"pre",{"className":582,"code":583,"language":584,"meta":585,"style":585},"language-js shiki shiki-themes github-light github-dark","{ type: 'progress', progress: { total, completed, succeeded, failed, currentItem,\n    videos: [{ name, status: 'pending'|'rendering'|'done'|'failed', url?, error? }] } }\n{ type: 'done', result: { success: true, videos, succeeded, failed } }\n{ type: 'error', error: '…' }\n","js","",[46,587,588,616,648,679],{"__ignoreMap":585},[589,590,593,597,601,604,608,610,613],"span",{"class":591,"line":592},"line",1,[589,594,596],{"class":595},"sVt8B","{ ",[589,598,600],{"class":599},"sScJk","type",[589,602,603],{"class":595},": ",[589,605,607],{"class":606},"sZZnC","'progress'",[589,609,68],{"class":595},[589,611,612],{"class":599},"progress",[589,614,615],{"class":595},": { total, completed, succeeded, failed, currentItem,\n",[589,617,619,622,625,628,632,635,637,640,642,645],{"class":591,"line":618},2,[589,620,621],{"class":599},"    videos",[589,623,624],{"class":595},": [{ name, status: ",[589,626,627],{"class":606},"'pending'",[589,629,631],{"class":630},"szBVR","|",[589,633,634],{"class":606},"'rendering'",[589,636,631],{"class":630},[589,638,639],{"class":606},"'done'",[589,641,631],{"class":630},[589,643,644],{"class":606},"'failed'",[589,646,647],{"class":595},", url?, error? }] } }\n",[589,649,651,653,655,657,659,661,664,667,670,672,676],{"class":591,"line":650},3,[589,652,596],{"class":595},[589,654,600],{"class":599},[589,656,603],{"class":595},[589,658,639],{"class":606},[589,660,68],{"class":595},[589,662,663],{"class":599},"result",[589,665,666],{"class":595},": { ",[589,668,669],{"class":599},"success",[589,671,603],{"class":595},[589,673,675],{"class":674},"sj4cs","true",[589,677,678],{"class":595},", videos, succeeded, failed } }\n",[589,680,682,684,686,688,691,693,696,698,701],{"class":591,"line":681},4,[589,683,596],{"class":595},[589,685,600],{"class":599},[589,687,603],{"class":595},[589,689,690],{"class":606},"'error'",[589,692,68],{"class":595},[589,694,695],{"class":599},"error",[589,697,603],{"class":595},[589,699,700],{"class":606},"'…'",[589,702,703],{"class":595}," }\n",[51,705,707],{"id":706},"uploading-source-media-tus","Uploading source media (tus)",[15,709,710,711,717,718,721],{},"Video\u002Faudio\u002Fimage assets upload via the ",[27,712,716],{"href":713,"rel":714},"https:\u002F\u002Ftus.io",[715],"nofollow","tus 1.0"," resumable protocol — chunked (8 MB), resumable after network drops, up to ",[19,719,720],{},"2 GB"," per file.",[123,723,724,737],{},[126,725,726],{},[129,727,728,731,734],{},[132,729,730],{},"Method",[132,732,733],{},"Path",[132,735,736],{},"Purpose",[142,738,739,757,772,793],{},[129,740,741,746,751],{},[147,742,743],{},[46,744,745],{},"POST",[147,747,748],{},[46,749,750],{},"\u002Fapi\u002Fvideo\u002Ftus",[147,752,753,754,89],{},"Create (or resume) an upload. Send ",[46,755,756],{},"Upload-Metadata: filename \u003Cbase64>, filetype \u003Cbase64>",[129,758,759,764,769],{},[147,760,761],{},[46,762,763],{},"HEAD",[147,765,766],{},[46,767,768],{},"\u002Fapi\u002Fvideo\u002Ftus\u002F:id",[147,770,771],{},"Probe the current offset to resume.",[129,773,774,779,783],{},[147,775,776],{},[46,777,778],{},"PATCH",[147,780,781],{},[46,782,768],{},[147,784,785,786,789,790,89],{},"Append a chunk. The ",[19,787,788],{},"final"," PATCH responds with the file descriptor: ",[46,791,792],{},"{ \"url\", \"name\", \"kind\": \"image\"|\"video\"|\"audio\"|\"lottie\"|\"svg\" }",[129,794,795,800,804],{},[147,796,797],{},[46,798,799],{},"DELETE",[147,801,802],{},[46,803,768],{},[147,805,806],{},"Cancel an in-flight upload.",[15,808,809,812,813,89],{},[19,810,811],{},"Accepted types:"," PNG, JPEG, GIF, WebP, AVIF, SVG (sanitized), MP4, WebM, MOV, MP3, WAV, OGG, M4A, AAC, WebA, and Lottie JSON. Unsupported types return ",[46,814,815],{},"415",[51,817,819],{"id":818},"limits","Limits",[123,821,822,832],{},[126,823,824],{},[129,825,826,829],{},[132,827,828],{},"Limit",[132,830,831],{},"Value",[142,833,834,842,850,858,866],{},[129,835,836,839],{},[147,837,838],{},"Resolution",[147,840,841],{},"320×180 – 3840×2160 (stills from 64×64)",[129,843,844,847],{},[147,845,846],{},"Frame rate",[147,848,849],{},"1–60 fps",[129,851,852,855],{},[147,853,854],{},"Output format",[147,856,857],{},"MP4 (H.264); stills as PNG\u002FWebP\u002FSVG",[129,859,860,863],{},[147,861,862],{},"Upload size",[147,864,865],{},"2 GB per file (8 MB chunks)",[129,867,868,871],{},[147,869,870],{},"Bulk credits",[147,872,873],{},"10 per successful video",[875,876,877],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":585,"searchDepth":618,"depth":618,"links":879},[880,881,887,891,897,898],{"id":53,"depth":618,"text":54},{"id":104,"depth":618,"text":105,"children":882},[883,885],{"id":109,"depth":650,"text":884},"POST \u002Fapi\u002Fvideo\u002Frender",{"id":259,"depth":650,"text":886},"GET \u002Fapi\u002Fvideo\u002Frender\u002F:jobId",{"id":341,"depth":618,"text":342,"children":888},[889],{"id":345,"depth":650,"text":890},"POST \u002Fapi\u002Fvideo\u002Fstill",{"id":460,"depth":618,"text":461,"children":892},[893,895],{"id":464,"depth":650,"text":894},"POST \u002Fapi\u002Fvideo\u002Fbulk",{"id":572,"depth":650,"text":896},"GET \u002Fapi\u002Fvideo\u002Fbulk\u002F:jobId\u002Fstream",{"id":706,"depth":618,"text":707},{"id":818,"depth":618,"text":819},"The Bannx video editor and rendering pipeline — MP4 renders, stills, bulk generation from data rows, and resumable media uploads.","md",{"layout":902,"updatedAt":903},"docs","2026-07-06",true,"\u002Fdocs\u002Fvideo",{"title":6,"description":899},"docs\u002Fvideo","otYPhjamSdYE7AgwRQlBwvKqnLe4r_0t5iIJk0hoBoQ",{"success":904,"routes":910,"total":1400,"generatedAt":1401,"canViewAllApiDocs":977},[911,951,963,1017,1074,1095,1116,1130,1145,1157,1169,1186,1213,1239,1258,1270,1281,1292,1301,1307,1325,1336,1351,1362,1375],{"path":912,"method":745,"summary":913,"description":914,"tags":915,"group":285,"requestBody":916,"responses":943,"actionName":950},"\u002Fapi\u002Fcode-to-image","Render code snippets as images","Render source code with syntax highlighting to PNG, WebP, or JPEG. No API token required.",[285],{"content":917},{"application\u002Fjson":918},{"schema":919},{"type":168,"required":920,"properties":921},[46],{"code":922,"lang":924,"theme":926,"format":928,"width":932,"height":934,"quality":936,"showLineNumbers":938,"style":941},{"type":153,"description":923},"Source code to render",{"type":153,"description":925},"Language for highlighting (e.g. js, ts). Default: js",{"type":153,"description":927},"Shiki theme. Default: github-dark",{"type":153,"enum":929,"description":931},[431,434,930],"jpeg","Output format. Default: png (lossless)",{"type":183,"description":933},"Optional width",{"type":183,"description":935},"Optional height",{"type":183,"description":937},"Optional quality",{"type":939,"description":940},"boolean","Show 1-based line numbers in a left gutter. Default: false",{"type":168,"description":942},"Optional style options",{"200":944,"400":946,"500":948},{"description":945},"Image (data URL or binary depending on format)",{"description":947},"Missing or invalid code",{"description":949},"Failed to generate code image","codeToImage",{"path":952,"method":745,"summary":953,"description":954,"tags":955,"group":956,"responses":957,"actionName":962},"\u002Fapi\u002Fdemo-token","Create a demo token","Mint a short-lived, IP-throttled demo token (stored only in Redis, ~1h TTL) that can render PUBLIC templates with tweaks — no account or API key required. Each client IP can mint up to 5 tokens per rolling hour. Use the token as `Authorization: Bearer demo_…` or `?demo=demo_…` against GET \u002Fapi\u002Frender\u002F:pageId.",[956],"Authentication",{"200":958,"429":960},{"description":959},"Demo token created",{"description":961},"Per-IP demo token quota reached","createDemoToken",{"path":964,"method":965,"summary":966,"description":967,"tags":968,"group":285,"parameters":969,"responses":1009,"actionName":1016},"\u002Fapi\u002Frender\u002F:pageId","GET","Render a page by ID (GET)","Render by page ID with query parameters. Supports draft (database), publish cache, png\u002Fsvg\u002Fwebp\u002Fpdf, JSON or binary responses, tweaks, and brandTweaks — aligned with POST \u002Fapi\u002Frender. Auth depends on template requireGetRenderToken (Bearer or gt query).",[285],[970,975,983,986,993,997,1001,1005],{"in":971,"name":972,"required":904,"schema":973,"description":974},"path","pageId",{"type":153},"Page ID to render",{"in":976,"name":426,"required":977,"schema":978,"description":982},"query",false,{"type":153,"enum":979},[431,437,434,980,981],"pdf","pptx","Output format. Default: png",{"in":976,"name":231,"required":977,"schema":984,"description":985},{"type":939},"If true, load from database instead of publish cache. Default: false",{"in":976,"name":987,"required":977,"schema":988,"description":992},"output",{"type":153,"enum":989},[990,991],"json","binary","Response shape: omit or json for metadata + file URL; binary for raw bytes",{"in":976,"name":994,"required":977,"schema":995,"description":996},"pageIds",{"type":153},"Comma-separated page IDs for merged PDF (format=pdf only)",{"in":976,"name":998,"required":977,"schema":999,"description":1000},"gt",{"type":153},"GET render secret when Bearer is not used",{"in":976,"name":1002,"required":977,"schema":1003,"description":1004},"scale",{"type":183,"minimum":592,"maximum":681},"Output resolution multiplier for png\u002Fwebp. Overrides the template's renderScale. Default 2.",{"in":976,"name":226,"required":977,"schema":1006,"description":1008},{"type":183,"minimum":592,"maximum":1007},100,"WebP encode quality (webp only). Overrides the template's webpQuality. Default 90.",{"200":1010,"401":1012,"404":1014},{"description":1011},"Binary image\u002FPDF or application\u002Fjson with file metadata",{"description":1013},"Missing or invalid API token",{"description":1015},"Page or template not found","renderPage",{"path":1018,"method":745,"summary":1019,"description":1020,"tags":1021,"group":285,"requestBody":1022,"responses":1066,"actionName":1073},"\u002Fapi\u002Frender\u002Findex","Render by page ID","Render a page by ID from the publish cache, or from the database when draft: true. Requires API token. Does not accept full inline page payloads. Optional body field renderType (satori, takumi, html) overrides the template's rendererType. Use format pdf for the HTML + Chrome PDF pipeline (always uses the HTML renderer). For multi-page PDFs, send pageIds and optional tweaksPerPage (same length). Default response is application\u002Fjson with timings and a URL to the uploaded render; set output to binary (or binary: true) to return raw bytes.",[285],{"content":1023},{"application\u002Fjson":1024},{"schema":1025},{"type":168,"description":1026,"properties":1027},"For raster formats use pageId. For PDF use pageId (single) or pageIds (merged in order).",{"pageId":1028,"pageIds":1030,"tweaksPerPage":1034,"templateId":1037,"draft":1039,"format":1041,"tweaks":1045,"brandTweaks":1047,"emojiType":1049,"output":1051,"binary":1056,"renderType":1058,"scale":1063,"quality":1065},{"type":153,"description":1029},"Page ID to render (required for png\u002Fsvg\u002Fwebp; optional for pdf when pageIds is set)",{"type":1031,"items":1032,"description":1033},"array",{"type":153},"Multiple pages for merged PDF (format pdf only)",{"type":1031,"items":1035,"description":1036},{"type":168},"Per-page tweaks aligned with pageIds when rendering PDF",{"type":153,"description":1038},"Optional; when set, validated against the page's template (parallel fetch)",{"type":939,"description":1040},"If true, load page and template from database instead of publish cache. Default: false",{"type":153,"enum":1042,"description":1044},[431,437,434,980,981,1043],"html5","Output format. Default: png. pdf and pptx use HTML + Chrome; pptx builds an editable slide per page. html5 returns a self-contained HTML5 display-ad ZIP (Google Ads) for a single page.",{"type":168,"description":1046},"Variable overrides; keys may use dot paths for nested values. For Variable[] sources, use \"varId.nested.path\" when patching object values.",{"type":168,"description":1048},"Brand token overrides by dot path (e.g. logos.icon or brand.logos.icon). Merged into resolved brand tokens before render.",{"type":153,"description":1050},"e.g. twemoji, openmoji. Default from template",{"type":153,"enum":1052,"description":1055},[990,991,1053,1054],"image","raw","Response shape: omit or json for application\u002Fjson (default); binary, image, or raw for raw body",{"type":939,"description":1057},"If true, same as output binary (raw body)",{"type":153,"enum":1059,"description":1062},[1060,1061],"takumi","html","Override rendering engine (takumi or html). Ignored when format is pdf (HTML pipeline). Legacy value 'satori' is accepted and treated as 'takumi'.",{"type":183,"minimum":592,"maximum":681,"description":1064},"Output resolution multiplier for png\u002Fwebp (logical layout unchanged, pixels multiplied). Overrides the template's renderScale. Default 2.",{"type":183,"minimum":592,"maximum":1007,"description":1008},{"200":1067,"400":1069,"401":1071,"404":1072},{"description":1068},"Default: application\u002Fjson with render metadata and file.url. With output binary: image\u002Fpng, image\u002Fsvg+xml, image\u002Fwebp, or application\u002Fpdf.",{"description":1070},"Invalid body (e.g. missing pageId)",{"description":1013},{"description":1015},"render",{"path":1075,"method":965,"summary":1076,"description":1077,"tags":1078,"parameters":1079,"responses":1089,"actionName":1094},"\u002Fapi\u002Frenders\u002Flogs","List render logs","Render request logs for the current space, optionally narrowed to one template. Session-authenticated (dashboard login) — not callable with an API key.",[285],[1080,1083,1086],{"in":976,"name":1081,"required":977,"description":1082},"templateId","Only logs for this template's pages",{"in":976,"name":1084,"required":977,"description":1085},"page","Page number",{"in":976,"name":1087,"required":977,"description":1088},"perPage","Items per page (default 50)",{"200":1090,"401":1092},{"description":1091},"JSON { list, count, pagesCount } of render log entries",{"description":1093},"Not logged in","listRenderLogs",{"path":1096,"method":965,"summary":1097,"description":1098,"tags":1099,"parameters":1101,"responses":1112,"actionName":1115},"\u002Fapi\u002Ftemplates\u002Fpublic","List public templates","List published community\u002Fgallery templates with their cached pages. No authentication required.",[1100],"Templates",[1102,1105,1108,1110],{"in":976,"name":1103,"required":977,"description":1104},"search","Search name + description (max 80 chars)",{"in":976,"name":1106,"required":977,"description":1107},"category","Category filter, or \"featured\" for the curated list",{"in":976,"name":1084,"required":977,"description":1109},"Page number (default 1)",{"in":976,"name":1087,"required":977,"description":1111},"Items per page (max 100)",{"200":1113},{"description":1114},"JSON { list, count, pagesCount } — templates include their published pages","listPublicTemplates",{"path":1117,"method":965,"summary":1118,"description":1119,"tags":1120,"parameters":1121,"responses":1124,"actionName":1129},"\u002Fapi\u002Ftemplates\u002Fpublic\u002F:id","Get a public template","Fetch one published template (with its pages) by ID. Only templates with publicOn are returned; private IDs 404. No authentication required.",[1100],[1122],{"in":971,"name":88,"required":904,"description":1123},"Template ID",{"200":1125,"404":1127},{"description":1126},"JSON { doc } — the template including published pages",{"description":1128},"Template not found or not public","getPublicTemplateDoc",{"path":1131,"method":799,"summary":1132,"description":1133,"tags":1134,"parameters":1136,"responses":1139,"actionName":1144},"\u002Fapi\u002Fv1\u002Fbrands\u002F:id","Delete a brand","Soft-delete a brand by ID. Session-authenticated (dashboard login; owner\u002Fadmin\u002Feditor).",[1135],"Brands",[1137],{"in":971,"name":88,"required":904,"description":1138},"Brand ID",{"200":1140,"404":1142},{"description":1141},"JSON { success: true, id }",{"description":1143},"Brand not found in your space","deleteBrand",{"path":1131,"method":965,"summary":1146,"description":1147,"tags":1148,"parameters":1149,"responses":1151,"actionName":1156},"Get a brand","Fetch one brand by ID. Public brands (publicOn set) need no auth; private brands require a dashboard session in the owning space. For API-key access use the MCP server (get_brand).",[1135],[1150],{"in":971,"name":88,"required":904,"description":1138},{"200":1152,"404":1154},{"description":1153},"JSON { doc } — the brand with its token sets",{"description":1155},"Not found or not accessible","getBrand",{"path":1131,"method":1158,"summary":1159,"description":1160,"tags":1161,"parameters":1162,"responses":1164,"actionName":1168},"PUT","Update a brand","Update a brand by ID (same fields as create, all optional). Session-authenticated (dashboard login; owner\u002Fadmin\u002Feditor). For API-key access use the MCP server (update_brand).",[1135],[1163],{"in":971,"name":88,"required":904,"description":1138},{"200":1165,"404":1167},{"description":1166},"JSON { doc } — the updated brand",{"description":1143},"updateBrand",{"path":1170,"method":965,"summary":1171,"description":1172,"tags":1173,"parameters":1174,"responses":1180,"actionName":1185},"\u002Fapi\u002Fv1\u002Fbrands\u002Findex","List brands","List brands in the current space. Session-authenticated (dashboard login); pass ?public=true to list public brands anonymously. For API-key access use the MCP server (list_brands).",[1135],[1175,1176,1177],{"in":976,"name":1084,"required":977,"description":1109},{"in":976,"name":1087,"required":977,"description":1088},{"in":976,"name":1178,"required":977,"description":1179},"public","\"true\" to list public brands without auth",{"200":1181,"401":1183},{"description":1182},"JSON { list, count, pagesCount } of brands",{"description":1184},"Not logged in (when public is not set)","listBrands",{"path":1170,"method":745,"summary":1187,"description":1188,"tags":1189,"requestBody":1190,"responses":1208,"actionName":1212},"Create a brand","Create a brand in the current space. Session-authenticated (dashboard login; owner\u002Fadmin\u002Feditor). External image URLs inside tokens are re-uploaded to your space. For API-key access use the MCP server (create_brand).",[1135],{"content":1191},{"application\u002Fjson":1192},{"schema":1193},{"type":168,"required":1194,"properties":1195},[67],{"name":1196,"draftTokens":1198,"liveTokens":1200,"tokens":1202,"variants":1204,"extra":1206},{"type":153,"description":1197},"Brand name",{"type":168,"description":1199},"Token kit being edited (logos, colors, typography, …)",{"type":168,"description":1201},"Token kit used by published renders",{"type":168,"description":1203},"Resolved token set",{"type":168,"description":1205},"Named variations of the kit",{"type":168,"description":1207},"Free-form extras",{"200":1209,"401":1211},{"description":1210},"JSON { doc } — the created brand",{"description":1093},"createBrand",{"path":1214,"method":965,"summary":1215,"description":1216,"tags":1217,"group":1218,"parameters":1219,"responses":1232,"actionName":1238},"\u002Fapi\u002Fv1\u002Fpublic\u002Fcontent\u002F:collection\u002F:slug","Get an entry","Read a single PUBLISHED entry by slug. Authenticate with a content.read API key (Authorization: Bearer …). The slug is matched against the collection's configured preview.slugField (defaults to \"slug\"). Only liveData is returned; use ?depth= to resolve references and ?variants= for personalization.",[1218],"Content",[1220,1223,1226,1229],{"in":971,"name":1221,"required":904,"description":1222},"collection","The collection's API name",{"in":971,"name":1224,"required":904,"description":1225},"slug","The entry slug",{"in":976,"name":1227,"required":977,"description":1228},"depth","Resolve reference fields to this depth (default 0)",{"in":976,"name":1230,"required":977,"description":1231},"variants","Comma-separated variant ids; returns personalization-resolved values",{"200":1233,"401":1235,"404":1236},{"description":1234},"JSON { doc } — the published entry",{"description":1013},{"description":1237},"Collection or entry not found","publicGetContentBySlug",{"path":1240,"method":965,"summary":1241,"description":1242,"tags":1243,"group":1218,"parameters":1244,"responses":1251,"actionName":1257},"\u002Fapi\u002Fv1\u002Fpublic\u002Fcontent\u002F:collection\u002Findex","List entries","List PUBLISHED entries in a collection. Authenticate with a content.read API key (Authorization: Bearer …). Only liveData is returned — never drafts. Values under `data` are keyed by field API name. Supports pagination, reference resolution (?depth=), and personalization (?variants=).",[1218],[1245,1246,1247,1249,1250],{"in":971,"name":1221,"required":904,"description":1222},{"in":976,"name":1084,"required":977,"description":1109},{"in":976,"name":1087,"required":977,"description":1248},"Items per page (default 20)",{"in":976,"name":1227,"required":977,"description":1228},{"in":976,"name":1230,"required":977,"description":1231},{"200":1252,"401":1254,"404":1255},{"description":1253},"JSON { list, count, pagesCount } of published entries",{"description":1013},{"description":1256},"Collection not found","publicListContent",{"path":1259,"method":799,"summary":1260,"description":1261,"tags":1262,"responses":1264,"actionName":1269},"\u002Fapi\u002Fv1\u002Fshaders\u002F:id","Delete a shader","Permanently remove a shader from the current space.",[1263],"Shaders",{"200":1265,"404":1267},{"description":1266},"JSON { deleted: true }",{"description":1268},"No such shader","deleteShader",{"path":1259,"method":965,"summary":1271,"description":1272,"tags":1273,"responses":1274,"actionName":1280},"Get a shader","Fetch one shader including its vetted `program` — the only source a client should compile. Status is enforced here on every request, which is what makes revoking a working kill switch: a quarantined or revoked shader returns 410 and stops loading everywhere immediately.",[1263],{"200":1275,"404":1277,"410":1278},{"description":1276},"JSON { doc }",{"description":1268},{"description":1279},"Shader is quarantined or revoked","getShader",{"path":1259,"method":1158,"summary":1282,"description":1283,"tags":1284,"responses":1285,"actionName":1291},"Update a shader","Editing source or the manifest re-runs the full vetting pipeline and produces a new content hash — an existing approval is never inherited by code that was not vetted. A rejected edit returns 422 and leaves the stored shader untouched.",[1263],{"200":1286,"404":1288,"422":1289},{"description":1287},"JSON { doc, report }",{"description":1268},{"description":1290},"Rejected by vetting; the stored shader is unchanged","updateShader",{"path":1293,"method":745,"summary":1294,"description":1295,"tags":1296,"responses":1297,"actionName":1300},"\u002Fapi\u002Fv1\u002Fshaders\u002F:id\u002Fstatus","Set a shader status (kill switch)","Revoke, quarantine, or restore a shader. Because GET enforces status on every fetch, revoking stops the shader loading everywhere at once — there is no client deny-list to push and no cache to wait out. Restoring also clears the accumulated watchdog trips.",[1263],{"200":1298,"404":1299},{"description":1276},{"description":1268},"setShaderStatus",{"path":1302,"method":745,"summary":1303,"description":1304,"tags":1305,"actionName":1306},"\u002Fapi\u002Fv1\u002Fshaders\u002F:id\u002Ftelemetry","Report a client watchdog trip","Called by a viewer whose frame watchdog disabled this shader. Enough independent trips ",[1263],"reportShaderTrip",{"path":1308,"method":965,"summary":1309,"description":1310,"tags":1311,"parameters":1312,"responses":1320,"actionName":1324},"\u002Fapi\u002Fv1\u002Fshaders\u002Findex","List shaders","List the current space's shaders. Pass ?public=true to list published shaders anonymously. Program source is omitted from the listing — fetch a single shader to obtain it.",[1263],[1313,1314,1315,1318],{"in":976,"name":1084,"required":977,"description":1109},{"in":976,"name":1087,"required":977,"description":1088},{"in":976,"name":1316,"required":977,"description":1317},"status","approved | quarantined | revoked",{"in":976,"name":1178,"required":977,"description":1319},"\"true\" to list public shaders without auth",{"200":1321,"401":1323},{"description":1322},"JSON { list, count, pagesCount }",{"description":1184},"listShaders",{"path":1308,"method":745,"summary":1326,"description":1327,"tags":1328,"responses":1329,"actionName":1335},"Create a shader","Submit a GLSL fragment body plus a typed input manifest. The shader is vetted before anything is stored: byte caps, a static policy scan, loop normalisation to constant bounds, a cost model, then a real compile and fuzz render inside a sandboxed child process. A rejected submission returns 422 with the stage-by-stage report and is not saved.",[1263],{"200":1330,"401":1332,"422":1333},{"description":1331},"JSON { doc, report } — the stored shader and its vetting report",{"description":1093},{"description":1334},"Rejected by vetting; data.report explains which stage refused","createShader",{"path":1337,"method":799,"summary":1338,"description":1339,"tags":1340,"parameters":1342,"responses":1345,"actionName":1350},"\u002Fapi\u002Fv1\u002Ftokens\u002Fapi-keys\u002F:id","Delete an API key","Revoke an API key immediately. Session-authenticated (dashboard login; owner\u002Fadmin).",[1341],"Tokens",[1343],{"in":971,"name":88,"required":904,"description":1344},"Token ID",{"200":1346,"404":1348},{"description":1347},"JSON { message } confirmation",{"description":1349},"Token not found in your space","deleteApiKey",{"path":1337,"method":778,"summary":1352,"description":1353,"tags":1354,"parameters":1355,"responses":1357,"actionName":1361},"Update an API key","Rename, change expiry, or adjust scopes of an API key. Session-authenticated (dashboard login; owner\u002Fadmin).",[1341],[1356],{"in":971,"name":88,"required":904,"description":1344},{"200":1358,"404":1360},{"description":1359},"JSON { doc } — the updated key",{"description":1349},"updateApiKey",{"path":1363,"method":965,"summary":1364,"description":1365,"tags":1366,"parameters":1367,"responses":1370,"actionName":1374},"\u002Fapi\u002Fv1\u002Ftokens\u002Fapi-keys\u002Findex","List API keys","List API keys for the current space. Session-authenticated (dashboard login; owner\u002Fadmin).",[1341],[1368,1369],{"in":976,"name":1084,"required":977,"description":1109},{"in":976,"name":1087,"required":977,"description":1248},{"200":1371,"401":1373},{"description":1372},"JSON { list, count, pagesCount } of API keys",{"description":1093},"listApiKeys",{"path":1363,"method":745,"summary":1376,"description":1377,"tags":1378,"requestBody":1379,"responses":1395,"actionName":1399},"Create an API key","Create a space-scoped API key. The plain token is returned once, on creation. Session-authenticated (dashboard login; owner\u002Fadmin).",[1341],{"content":1380},{"application\u002Fjson":1381},{"schema":1382},{"type":168,"required":1383,"properties":1384},[67],{"name":1385,"expiresAt":1387,"neverExpires":1389,"shortToken":1391,"scopes":1393},{"type":153,"description":1386},"Key name (max 200 chars)",{"type":153,"description":1388},"ISO datetime expiry",{"type":939,"description":1390},"No expiry. Default: false",{"type":939,"description":1392},"Shorter ~96-bit token instead of ~256-bit. Default: false",{"type":168,"description":1394},"Optional restrictions: { mcpTools?: string[], apiEndpoints?: string[] }. Omit a list to allow all; [] denies all.",{"200":1396,"401":1398},{"description":1397},"JSON { doc } including the plain token (shown only once)",{"description":1093},"createApiKey",25,"2026-08-19T19:21:11.342Z",1787167272953]