<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: useapi.net</title>
    <description>The latest articles on DEV Community by useapi.net (@useapi).</description>
    <link>https://dev.to/useapi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1161316%2Ffeb14d20-dbec-4923-bdaa-dca61f4e5527.png</url>
      <title>DEV Community: useapi.net</title>
      <link>https://dev.to/useapi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/useapi"/>
    <language>en</language>
    <item>
      <title>NotebookLM API Options in 2026: Google Enterprise API, Free Libraries or a Hosted API</title>
      <dc:creator>useapi.net</dc:creator>
      <pubDate>Fri, 16 Oct 2026 21:18:44 +0000</pubDate>
      <link>https://dev.to/useapi/notebooklm-api-options-in-2026-google-enterprise-api-free-libraries-or-a-hosted-api-3cch</link>
      <guid>https://dev.to/useapi/notebooklm-api-options-in-2026-google-enterprise-api-free-libraries-or-a-hosted-api-3cch</guid>
      <description>&lt;h3&gt;
  
  
  Does NotebookLM have an API?
&lt;/h3&gt;

&lt;p&gt;Not for regular Google accounts. Google renamed NotebookLM to Gemini Notebook in July 2026, and its only official API is the &lt;a href="https://docs.cloud.google.com/gemini/enterprise/notebooklm-enterprise/docs/api-notebooks" rel="noopener noreferrer"&gt;Gemini Notebook Enterprise API&lt;/a&gt;: a Preview API for Enterprise licenses in a Google Cloud project, which manages notebooks and sources and creates Audio Overviews.&lt;/p&gt;

&lt;p&gt;If you want to automate NotebookLM on an ordinary free or paid Google account, there are three kinds of options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Google's Enterprise API&lt;/strong&gt;, if your organisation buys Enterprise licenses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free open-source libraries and local MCP servers&lt;/strong&gt;, such as &lt;a href="https://github.com/teng-lin/notebooklm-py" rel="noopener noreferrer"&gt;notebooklm-py&lt;/a&gt; and &lt;a href="https://github.com/jacob-bd/gemini-notebook-mcp-cli" rel="noopener noreferrer"&gt;gemini-notebook-mcp-cli&lt;/a&gt;, which you install and run on your own machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A hosted API&lt;/strong&gt;, such as the &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1" rel="noopener noreferrer"&gt;useapi.net NotebookLM API (Gemini Notebook API)&lt;/a&gt;, which runs on our servers with your own Google account, over REST and as a hosted &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/mcp" rel="noopener noreferrer"&gt;MCP server&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This page is written by the useapi.net maintainers and compares what each option offers from its own documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compared
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;useapi.net&lt;/th&gt;
&lt;th&gt;notebooklm-py&lt;/th&gt;
&lt;th&gt;gemini-notebook-mcp-cli&lt;/th&gt;
&lt;th&gt;Google Enterprise API&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hosted, nothing to install or run locally&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosted MCP server for Claude Code, Cursor, VS Code&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌ (local only)&lt;/td&gt;
&lt;td&gt;❌ (local only)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works on free and paid consumer Google accounts&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sign-in without copying cookies; session kept fresh for you&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;REST API from any language&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Webhook when a job finishes&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automatic load balancing across Google accounts&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ready-to-import n8n templates&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;$15/month, every useapi.net API&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Enterprise licenses&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;small&gt;From each project's own documentation on October 16, 2026: notebooklm-py v0.8.5, gemini-notebook-mcp-cli v0.15.5, Gemini Notebook Enterprise API (Preview). useapi.net is a third-party API and is not affiliated with Google.&lt;/small&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why useapi.net instead of a free library
&lt;/h3&gt;

&lt;p&gt;useapi.net is a third-party API and is not affiliated with Google.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nothing to run on your machine.&lt;/strong&gt; The API is hosted, so jobs keep running when your laptop is off: no Chromium download, no local server, no tunnel and no browser left open.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sign in once, we keep you signed in.&lt;/strong&gt; The guided browser &lt;a href="https://useapi.net/docs/start-here/setup-gemini-notebook" rel="noopener noreferrer"&gt;setup&lt;/a&gt; connects your Google account once, and we keep the session fresh, with no cookies to copy or refresh. If Google ever signs it out, you get an email with a one-minute re-add link.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A hosted &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/mcp" rel="noopener noreferrer"&gt;MCP server&lt;/a&gt;, 56 tools.&lt;/strong&gt; Add it to Claude Code, Cursor or VS Code with one line. Nothing to install, and every notebook, source, chat and Studio output is available to your AI assistant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plain REST from any language.&lt;/strong&gt; Call it from Node.js, Python, bash, n8n, Make or a cron job with an API token. A Postman collection and an LLM-friendly spec cover every endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jobs tracked for you, with webhooks.&lt;/strong&gt; Every podcast, video, slide deck and research run is a server-side job. Poll it, or pass &lt;code&gt;replyUrl&lt;/code&gt; and get the finished result posted to your endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Several Google accounts, balanced automatically.&lt;/strong&gt; Connect 3 accounts per subscription, up to 100; each new job goes to one that is healthy, has a free slot and still has usage left.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Links in, podcast out.&lt;/strong&gt; Send URLs or text to one endpoint and get an Audio Overview, Video Overview, slide deck or quiz back, with no notebook setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ready-made &lt;a href="https://n8n.io/workflows/20476" rel="noopener noreferrer"&gt;n8n workflows&lt;/a&gt; and an agent skill&lt;/strong&gt;, on your free or paid Google plan, for a flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; that covers every useapi.net API.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What the useapi.net NotebookLM API covers
&lt;/h3&gt;

&lt;p&gt;Everything you do in NotebookLM, from code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Notebooks and sources.&lt;/strong&gt; Create, copy and share notebooks and group them in collections. Add web pages, YouTube videos, pasted text, uploaded files (PDF, Word, PowerPoint, EPUB, audio, video), Google Drive files and ebooks from your Google Play Books library.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chat with citations.&lt;/strong&gt; Ask questions grounded in your sources, with numbered citations and follow-up conversations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Research.&lt;/strong&gt; Discover sources and run Deep Research, then import the sources and the report.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every Studio output.&lt;/strong&gt; Audio Overviews (deep dive, brief, critique, debate), Video Overviews (including short and cinematic), slide decks, infographics, reports, data tables, quizzes, flashcards and mind maps, with revise, retry, copy and export.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usage you can see.&lt;/strong&gt; Each account's live usage in Google's 5-hour and weekly windows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full list is in the &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1" rel="noopener noreferrer"&gt;API reference&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to start
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Get a useapi.net &lt;a href="https://useapi.net/docs/start-here/setup-useapi" rel="noopener noreferrer"&gt;API token&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Connect a Google account once with the guided &lt;a href="https://useapi.net/docs/start-here/setup-gemini-notebook" rel="noopener noreferrer"&gt;NotebookLM setup&lt;/a&gt;. The free Google plan works.&lt;/li&gt;
&lt;li&gt;Turn a web page into a podcast with one call:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.useapi.net/v1/gemini-notebook/artifacts &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"type": "audio", "urls": ["https://en.wikipedia.org/wiki/Apollo_11"]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or add the &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/mcp" rel="noopener noreferrer"&gt;MCP server&lt;/a&gt; to Claude Code with one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http useapi-gemini-notebook https://api.useapi.net/v1/gemini-notebook/mcp &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer YOUR_API_TOKEN"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step-by-step tutorials: &lt;a href="https://useapi.net/docs/articles/gemini-notebook-bash" rel="noopener noreferrer"&gt;Deep Research, chat and Audio Overviews with curl&lt;/a&gt;, &lt;a href="https://useapi.net/docs/articles/notebooklm-podcast-example" rel="noopener noreferrer"&gt;a real podcast example&lt;/a&gt; and &lt;a href="https://useapi.net/docs/articles/notebooklm-n8n-podcast" rel="noopener noreferrer"&gt;RSS feeds to podcasts with n8n&lt;/a&gt;. Runnable code: &lt;a href="https://github.com/useapi/notebooklm-api" rel="noopener noreferrer"&gt;useapi/notebooklm-api&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start using the API
&lt;/h3&gt;

&lt;p&gt;A single &lt;strong&gt;$15/month&lt;/strong&gt; subscription covers every API on useapi.net — one token, all services. You connect up to 3 of your own provider accounts per service, and useapi.net handles the REST API, load balancing, and polling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://buy.stripe.com/8x2aEX4Bd8Vh9PMg4qeUU03" rel="noopener noreferrer"&gt;Subscribe — $15/month&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;Pricing, crypto payment, and volume options&lt;/a&gt; — full refund within the first 14 days if you have fewer than 50 successful generations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frequently asked questions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Is there a free NotebookLM API?&lt;/strong&gt; Google offers no free API for regular accounts. Free open-source libraries exist and run on your own machine. The useapi.net API is $15/month, works on the free Google plan, and has a full refund within 14 days if you made fewer than 50 successful generations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is there a NotebookLM API key?&lt;/strong&gt; Not from Google for regular accounts. With useapi.net you use a useapi.net API token and connect your Google account once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use NotebookLM from Python?&lt;/strong&gt; Yes. The useapi.net API is plain REST, so any HTTP client works. The &lt;a href="https://github.com/useapi/notebooklm-api" rel="noopener noreferrer"&gt;examples repository&lt;/a&gt; has Node.js, Python and bash scripts and a Colab notebook.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is there a NotebookLM MCP server?&lt;/strong&gt; Yes. The hosted &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/mcp" rel="noopener noreferrer"&gt;useapi.net NotebookLM MCP server&lt;/a&gt; has 56 tools and is listed in the official MCP Registry as &lt;code&gt;net.useapi/gemini-notebook&lt;/code&gt;. You add it to Claude Code, Cursor or VS Code with one line, with nothing to install.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I have to copy cookies or keep a browser open?&lt;/strong&gt; No. You sign in once through the guided setup, and we keep the session fresh. If Google ever signs the account out, you get an email with a link to re-add it.&lt;/p&gt;

</description>
      <category>notebooklm</category>
      <category>api</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>How to Generate AI Images and Videos with the Muse API</title>
      <dc:creator>useapi.net</dc:creator>
      <pubDate>Mon, 12 Oct 2026 06:14:53 +0000</pubDate>
      <link>https://dev.to/useapi/how-to-generate-ai-images-and-videos-with-the-muse-api-274</link>
      <guid>https://dev.to/useapi/how-to-generate-ai-images-and-videos-with-the-muse-api-274</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The &lt;a href="https://useapi.net/docs/api-muse-v1" rel="noopener noreferrer"&gt;useapi.net Muse API&lt;/a&gt; drives &lt;a href="https://muse.ai" rel="noopener noreferrer"&gt;Muse&lt;/a&gt;, Meta's personal AI agent, from code: one POST makes an image or a 10-second video with spoken dialogue, and every file it makes is an &lt;a href="https://useapi.net/docs/api-muse-v1/get-muse-assets-assetId" rel="noopener noreferrer"&gt;asset id&lt;/a&gt; the next job can take as an input.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The API runs on your own Muse account, and the free plan works. This walkthrough takes three ordinary photos, a vintage BMW motorcycle, a red-haired rider and the beach below the Golden Gate Bridge, and turns them into one picture of her riding that motorcycle through the surf. The picture then becomes a video in which she shouts a line, and in a third job a different woman, taken from a fourth photo, replaces her in that video while the ride stays the same. Along the way it makes images from text, and it restores and colorizes a hundred-year-old portrait that then looks up and speaks. Every request below is the one that made the media on this page.&lt;/p&gt;



&lt;p&gt;&lt;small&gt;The rider from a photo, swapped into a clip Muse made from a still image (step 8).&lt;/small&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What it cost
&lt;/h3&gt;

&lt;p&gt;useapi.net is an API, not an image or video service of its own. Every call runs on a Muse account you add through &lt;a href="https://useapi.net/docs/start-here/setup-muse" rel="noopener noreferrer"&gt;Setup Muse&lt;/a&gt;, and uses that account's weekly Muse allowance. Muse reports it as a whole percent used, so a single image often shows no change. You pay useapi.net a flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; for every API we offer, with no per-image or per-video charge.&lt;/p&gt;

&lt;p&gt;What each step used on the free plan, taken from &lt;code&gt;percentUsed&lt;/code&gt; before and after it, and how long each job took:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;th&gt;Allowance used&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Text to image, 9:16&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-muse-v1/post-muse-jobs-image" rel="noopener noreferrer"&gt;POST /jobs/image&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;1152×2048&lt;/td&gt;
&lt;td&gt;not measured&lt;/td&gt;
&lt;td&gt;30 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Text to image, exactly 16:9&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-muse-v1/post-muse-jobs-image" rel="noopener noreferrer"&gt;POST /jobs/image&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;2048×1152&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;21 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rider + motorcycle + beach&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-muse-v1/post-muse-jobs-image" rel="noopener noreferrer"&gt;POST /jobs/image&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;2048×1152&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;31 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The ride as a video&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-muse-v1/post-muse-jobs-video" rel="noopener noreferrer"&gt;POST /jobs/video&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;1280×720, 10 s&lt;/td&gt;
&lt;td&gt;3%&lt;/td&gt;
&lt;td&gt;88 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Restore an old photo&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-muse-v1/post-muse-jobs-image" rel="noopener noreferrer"&gt;POST /jobs/image&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;1344×1792&lt;/td&gt;
&lt;td&gt;1%&lt;/td&gt;
&lt;td&gt;34 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The portrait speaks&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-muse-v1/post-muse-jobs-video" rel="noopener noreferrer"&gt;POST /jobs/video&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;832×1104, 10 s&lt;/td&gt;
&lt;td&gt;2%&lt;/td&gt;
&lt;td&gt;68 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swap the rider&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-muse-v1/post-muse-jobs-video" rel="noopener noreferrer"&gt;POST /jobs/video&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;1248×704, 10 s&lt;/td&gt;
&lt;td&gt;3%&lt;/td&gt;
&lt;td&gt;138 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Uploads use no allowance. On the free plan a video used 2 to 3 percent of the week and an image 0 to 1 percent, so one free account makes roughly 30 to 50 videos a week, or several hundred images (step 9).&lt;/p&gt;

&lt;h3&gt;
  
  
  Before you start
&lt;/h3&gt;

&lt;p&gt;You need a useapi.net &lt;a href="https://useapi.net/docs/start-here/setup-useapi" rel="noopener noreferrer"&gt;API token&lt;/a&gt; and a Muse account added through &lt;a href="https://useapi.net/docs/start-here/setup-muse" rel="noopener noreferrer"&gt;Setup Muse&lt;/a&gt;. Before you add the account:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finish Muse's onboarding at &lt;a href="https://muse.ai" rel="noopener noreferrer"&gt;muse.ai&lt;/a&gt;, including Meta's age check, and create one image there.&lt;/li&gt;
&lt;li&gt;The account must have email + password sign-in, because the API signs in with the email and password. A Meta account that signs in only with an emailed code has no password yet: create one in &lt;a href="https://accountscenter.meta.com/password_and_security/" rel="noopener noreferrer"&gt;Meta Accounts Center&lt;/a&gt; (Password and security), then add the account here. Without a password the add is refused with &lt;code&gt;400&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use the account only for the API, with no other automation tools on it. Opening it at muse.ai in a browser is fine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every call is also in the &lt;a href="https://useapi.net/assets/postman/muse-v1.json" rel="noopener noreferrer"&gt;Postman collection&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also in Chinese: &lt;a href="https://useapi.net/docs/articles/muse-api-zh" rel="noopener noreferrer"&gt;中文教程&lt;/a&gt;. The whole walkthrough is also on GitHub as one script, in Node.js and Python: &lt;a href="https://github.com/useapi/muse-api/tree/main/images-videos" rel="noopener noreferrer"&gt;&lt;code&gt;images-videos/&lt;/code&gt;&lt;/a&gt; in &lt;a href="https://github.com/useapi/muse-api" rel="noopener noreferrer"&gt;useapi/muse-api&lt;/a&gt;, plus an &lt;a href="https://github.com/useapi/muse-api/tree/main/skills/muse-video" rel="noopener noreferrer"&gt;agent skill&lt;/a&gt; for Claude Code and Codex.&lt;/p&gt;

&lt;p&gt;The steps use &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;jq&lt;/code&gt; and these variables and helpers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;USEAPI_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"user:12345-..."&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;EMAIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"example@gmail.com"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MUSE_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;   &lt;span class="c"&gt;# the Muse account password, used once in step 1&lt;/span&gt;
&lt;span class="nv"&gt;API&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://api.useapi.net/v1/muse
&lt;span class="nv"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
enc&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; jq &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; v &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'$v|@uri'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
post&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$AUTH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
get&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$AUTH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
upload&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/assets?email=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;enc &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$EMAIL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$AUTH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: &lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--data-binary&lt;/span&gt; @&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; .assetId&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
download&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; curl &lt;span class="nt"&gt;-sSf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/assets/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;enc &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$AUTH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# run a job async: submit it, poll GET /jobs/{jobid} every 10 s, save the final job record to $1&lt;/span&gt;
run&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;job &lt;span class="nb"&gt;id
  &lt;/span&gt;&lt;span class="nv"&gt;job&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;post &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="s1"&gt;'. + {async: true}'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .jobid &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$job&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .status &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$job&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; started &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;10
    &lt;span class="nv"&gt;job&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;get &lt;span class="s2"&gt;"jobs/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;enc &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;done
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$job&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  jq &lt;span class="s1"&gt;'{status, error, text: .result.text, asset: .result.assets[0].assetId}'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every generation runs as a job. Without &lt;code&gt;async&lt;/code&gt;, a POST waits up to about 100 seconds and returns the finished job record, or &lt;code&gt;202&lt;/code&gt; with the job still running. A video here took 68 to 138 seconds, so &lt;code&gt;run&lt;/code&gt; sends every job with &lt;code&gt;async: true&lt;/code&gt; and polls &lt;a href="https://useapi.net/docs/api-muse-v1/get-muse-jobs-jobid" rel="noopener noreferrer"&gt;GET /jobs/&lt;code&gt;jobid&lt;/code&gt;&lt;/a&gt;. If &lt;code&gt;run&lt;/code&gt; prints any &lt;code&gt;status&lt;/code&gt; other than &lt;code&gt;completed&lt;/code&gt;, read its &lt;code&gt;error&lt;/code&gt; before going on.&lt;/p&gt;

&lt;p&gt;To be called back instead of polling, add &lt;code&gt;replyUrl: "https://example.com/hooks/muse"&lt;/code&gt; (and optionally &lt;code&gt;replyRef&lt;/code&gt;) to any body below. The API then sends one &lt;code&gt;POST&lt;/code&gt; of the final job record, as JSON, to that URL.&lt;/p&gt;

&lt;p&gt;Ids contain &lt;code&gt;:&lt;/code&gt; and &lt;code&gt;@&lt;/code&gt;, so &lt;code&gt;enc&lt;/code&gt; URL-encodes them whenever they go into a URL path. All inputs of one job must live on the same Muse account, so the uploads pin &lt;code&gt;email&lt;/code&gt;, and a job runs on the account that holds its inputs.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it was built
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Add the account
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-muse-v1/post-muse-accounts" rel="noopener noreferrer"&gt;POST /accounts&lt;/a&gt; takes the Muse account's email and password. The API signs in once, keeps the 30-day session and renews it itself. Muse emails the account a login code at each sign-in. That email is only a notice, nothing needs to be entered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;post accounts &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; email &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$EMAIL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; password &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MUSE_PASSWORD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{email: $email, password: $password}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="s1"&gt;'{health, maxJobs, quota}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The answer shows &lt;code&gt;health: "OK"&lt;/code&gt;, &lt;code&gt;maxJobs&lt;/code&gt; (2 by default) and the account's plan and usage, here &lt;code&gt;tier: "HATCH_FREE"&lt;/code&gt;, the free plan. If it answers &lt;code&gt;596&lt;/code&gt; instead, Meta wants a security check: sign in once at muse.ai in a browser, complete it, and post the same email and password again.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Upload the photos
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-muse-v1/post-muse-assets" rel="noopener noreferrer"&gt;POST /assets&lt;/a&gt; takes the raw file as the body, up to 8.6 MB, and writes it into the account's Muse workspace. Nothing is stored at useapi.net. The answer's &lt;code&gt;assetId&lt;/code&gt; is what a job takes as &lt;code&gt;image_N&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;BMW&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;upload bmw.jpeg image/jpeg&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;RIDER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;upload rider.jpeg image/jpeg&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;BEACH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;upload beach.jpeg image/jpeg&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;OLD_PHOTO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;upload old-photo.jpeg image/jpeg&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;PINK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;upload pink-hair.jpeg image/jpeg&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BMW&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="c"&gt;# user:12345-email:6578616d706c6540676d61696c2e636f6d-image:7db53e7a1f0979cbab6ff46ec3f0a35b60e6ee579a0d738a9628cf46a0c7a0f5.jpg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;/p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://media.discordapp.net/attachments/1239264794394234985/1559040377594314903/muse-input-motorcycle.jpeg" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1559040377594314903%2Fmuse-input-motorcycle.jpeg" alt="&lt;code&gt;image_1&lt;/code&gt; — the motorcycle&amp;quot;&gt;&lt;/a&gt;&lt;figcaption&gt;&lt;code&gt;image_1&lt;/code&gt; — the motorcycle&lt;/figcaption&gt;&lt;br&gt;
&lt;a href=" rel="noopener noreferrer" width="800" height="450"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1559040401510240267%2Fmuse-input-redhead.jpeg" alt="&lt;code&gt;image_2&lt;/code&gt; — the rider&amp;quot;&gt;&lt;/a&gt;&lt;figcaption&gt;&lt;code&gt;image_2&lt;/code&gt; — the rider&lt;/figcaption&gt;&lt;br&gt;
&lt;a href=" rel="noopener noreferrer" width="768" height="1344"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1559040372041187328%2Fmuse-input-beach.jpeg" alt="&lt;code&gt;image_3&lt;/code&gt; — the beach&amp;quot;&gt;&lt;/a&gt;&lt;figcaption&gt;&lt;code&gt;image_3&lt;/code&gt; — the beach&lt;/figcaption&gt;&lt;br&gt;
&lt;a href=" rel="noopener noreferrer" width="800" height="534"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1559040387203731456%2Fmuse-input-oldphoto.jpeg" alt="the old portrait" width="685" height="900"&gt;&lt;/a&gt;the old portrait&lt;br&gt;
&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://media.discordapp.net/attachments/1239264794394234985/1559040392316325888/muse-input-pinkhair.jpeg" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1559040392316325888%2Fmuse-input-pinkhair.jpeg" alt="the second rider" width="768" height="1344"&gt;&lt;/a&gt;the second rider&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;small&gt;The five inputs: the motorcycle, the rider, the beach, the old portrait and the second rider.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;The asset id is built from the file's content, so uploading the same file to the same account again returns the same id and writes nothing.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Images from text
&lt;/h4&gt;

&lt;p&gt;Muse has no aspect-ratio parameter: the prompt says it. A vertical portrait first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;run portrait.json &lt;span class="nb"&gt;jobs&lt;/span&gt;/image &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s1"&gt;'{prompt: "Vertical 9:16 full-body portrait photo: a confident young woman biker with long wavy fiery red hair, green eyes and freckles, in a worn black leather jacket, dark jeans and boots, standing in a rain-soaked neon alley at dusk, looking straight at the camera, cinematic lighting, photorealistic."}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.result.assets[0].assetId'&lt;/span&gt; portrait.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; portrait.webp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1559040423974936586%2Fmuse-A2.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1559040423974936586%2Fmuse-A2.webp" alt="Text to image at 9:16" width="800" height="1422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://media.discordapp.net/attachments/1239264794394234985/1559040423974936586/muse-A2.webp" rel="noopener noreferrer"&gt;open in new tab&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;That came back at exactly 9:16, 1152×2048. A landscape version asked as &lt;code&gt;Cinematic 16:9 landscape photo: …&lt;/code&gt; came back 1920×1280, which is 3:2. Writing the ratio as &lt;code&gt;in exactly 16:9 aspect ratio&lt;/code&gt; fixed it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;run bmw-noir.json &lt;span class="nb"&gt;jobs&lt;/span&gt;/image &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s1"&gt;'{prompt: "In exactly 16:9 aspect ratio (landscape), a cinematic photo of a vintage 1920s black BMW motorcycle with white pinstripes, spoked wheels and a brown leather saddle, parked on wet cobblestones at night in San Francisco, the Golden Gate Bridge glowing through fog in the distance, neo-noir moonlight, reflections on the wet street, shot on 35mm film."}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.result.assets[0].assetId'&lt;/span&gt; bmw-noir.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; bmw-noir.webp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1559040308455669800%2Fmuse-A5.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1559040308455669800%2Fmuse-A5.webp" alt="Text to image at exactly 16:9" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://media.discordapp.net/attachments/1239264794394234985/1559040308455669800/muse-A5.webp" rel="noopener noreferrer"&gt;open in new tab&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Muse answered "That 16:9 frame with the bridge ghosting through the fog is pure neo-noir. Enjoy." Its reply is in &lt;code&gt;result.text&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Three photos into one picture
&lt;/h4&gt;

&lt;p&gt;Up to 9 images go into one job as &lt;code&gt;image_1&lt;/code&gt;..&lt;code&gt;image_9&lt;/code&gt;, and the prompt names them. Here the motorcycle is &lt;code&gt;image_1&lt;/code&gt;, the rider &lt;code&gt;image_2&lt;/code&gt; and the beach &lt;code&gt;image_3&lt;/code&gt;. The prompt asks Muse to use the photographed beach as it is, so the Golden Gate Bridge stays where it was in the photo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;run beach-ride.json &lt;span class="nb"&gt;jobs&lt;/span&gt;/image &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; bmw &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BMW&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; rider &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RIDER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; beach &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BEACH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'{image_1: $bmw, image_2: $rider, image_3: $beach,
  prompt: "In exactly 16:9 aspect ratio (landscape), a cinematic photo: the woman from image_2 (her face, long wavy red hair, light blue top and jeans) riding the exact vintage motorcycle from image_1 along the shoreline of the beach in image_3, the front wheel cutting through the shallow surf and throwing spray, bright afternoon sun, her hair streaming in the wind, photorealistic. Use the beach, rocks and Golden Gate Bridge from image_3 as the background exactly as photographed: same position, same orientation, not mirrored or redrawn. Keep her face and the motorcycle'&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;'s design exactly as in the images."}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;BEACH_RIDE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.result.assets[0].assetId'&lt;/span&gt; beach-ride.json&lt;span class="si"&gt;)&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BEACH_RIDE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; beach-ride.webp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1559040336808910958%2Fmuse-G1.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1559040336808910958%2Fmuse-G1.webp" alt="The rider, the motorcycle and the beach in one picture" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://media.discordapp.net/attachments/1239264794394234985/1559040336808910958/muse-G1.webp" rel="noopener noreferrer"&gt;open in new tab&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;31 seconds, and no visible change in the weekly allowance.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. The picture as a video, no re-upload
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;BEACH_RIDE&lt;/code&gt; is the id of a file Muse made. It is already in the account's workspace, so it goes straight into the next job as &lt;code&gt;image_1&lt;/code&gt;, with no download and no upload. &lt;code&gt;Animate image_1&lt;/code&gt; makes a clip that starts from the picture and keeps its shape, and the line in quotes is spoken.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;run surf.json &lt;span class="nb"&gt;jobs&lt;/span&gt;/video &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; img &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BEACH_RIDE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{image_1: $img,
  prompt: "Animate image_1 into a cinematic video in exactly 16:9 aspect ratio (landscape): she rides the vintage motorcycle along the shoreline, the front wheel slices through the shallow waves and sends spray flying, the old engine roars, she raises one fist and shouts with a laugh: \"Nothing beats this view!\" The camera tracks alongside her. The beach, the rocks and the Golden Gate Bridge stay exactly as in image_1 (same orientation). Keep her face and the motorcycle exactly as in image_1."}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;SURF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.result.assets[0].assetId'&lt;/span&gt; surf.json&lt;span class="si"&gt;)&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SURF&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; surf.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;10 seconds at 1280×720 with sound. Muse said "Done. 10 seconds, 16:9 landscape, straight from your image — no edits, no upscaling."&lt;/p&gt;

&lt;p&gt;The first try of this exact job failed after 37 seconds: Muse answered that "the video worker glitched out before it rendered anything, so no clip was made". The API reports an answer like that as &lt;code&gt;503&lt;/code&gt;, nothing made, and the same request worked when run again. A refusal on content grounds is a &lt;code&gt;403&lt;/code&gt; instead, and needs a different prompt.&lt;/p&gt;

&lt;h4&gt;
  
  
  6. Restore and colorize an old photo
&lt;/h4&gt;

&lt;p&gt;An image job can also repair an image. The old portrait is a faded sepia photo of 685×900 pixels, 3:4. The prompt lists what to fix and insists on the same frame.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;run restored.json &lt;span class="nb"&gt;jobs&lt;/span&gt;/image &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; img &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OLD_PHOTO&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{image_1: $img,
  prompt: "Restore the old photograph image_1 as a high-quality modern photo: remove the scratches, dust, stains, fading and grain, recover sharp detail in the face, hair and fabric, and colorize it naturally (warm natural skin tones, dark brown hair, ivory tulle shawl, a soft pink rose with green leaves, a muted warm background). Keep the exact same person, expression, pose, framing and crop, and the same portrait aspect ratio as image_1 (3:4, 685×900): do not crop, extend or reframe it."}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;RESTORED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.result.assets[0].assetId'&lt;/span&gt; restored.json&lt;span class="si"&gt;)&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RESTORED&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; restored.webp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;/p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://media.discordapp.net/attachments/1239264794394234985/1559040387203731456/muse-input-oldphoto.jpeg" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1559040387203731456%2Fmuse-input-oldphoto.jpeg" alt="Before: the original, 685×900" width="685" height="900"&gt;&lt;/a&gt;Before: the original, 685×900&lt;br&gt;
&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://media.discordapp.net/attachments/1239264794394234985/1559040323257245737/muse-E1.webp" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1559040323257245737%2Fmuse-E1.webp" alt="After: restored and colorized, 1344×1792" width="800" height="1067"&gt;&lt;/a&gt;After: restored and colorized, 1344×1792&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The result is 1344×1792, the same 3:4 frame at about twice the size, with the same pose and crop. Muse said "Done — restored, de-grained, and colorized, same framing and pose."&lt;/p&gt;

&lt;h4&gt;
  
  
  7. The portrait comes to life
&lt;/h4&gt;

&lt;p&gt;The restored image goes straight into a video job. The clip keeps the portrait's shape, so it came back 832×1104.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;run portrait-video.json &lt;span class="nb"&gt;jobs&lt;/span&gt;/video &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; img &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RESTORED&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{image_1: $img,
  prompt: "Animate image_1 into a video with the same portrait frame: the young woman slowly lifts her eyes to the camera, her smile widens, she gently touches the rose on her shoulder and says softly: \"It has been a hundred years... and you still remember me.\" A light breeze moves a few strands of her hair, soft window light, the camera stays still with a very slow push-in. Keep her face exactly as in image_1."}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.result.assets[0].assetId'&lt;/span&gt; portrait-video.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; portrait.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h4&gt;
  
  
  8. Swap the rider in the video
&lt;/h4&gt;

&lt;p&gt;A video job also takes videos. &lt;code&gt;video_1&lt;/code&gt; is the surf clip from step 5, and &lt;code&gt;image_1&lt;/code&gt; is the photo of a second woman with pink hair in two buns. The prompt asks Muse to replace the rider and keep everything else, and gives her a new line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;run swap.json &lt;span class="nb"&gt;jobs&lt;/span&gt;/video &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; vid &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SURF&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; img &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PINK&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{video_1: $vid, image_1: $img,
  prompt: "Edit video_1: replace the rider with the woman from image_1 (her face, pink hair in two buns, colorful makeup and tattoos), and keep everything else the same: the motorcycle, the beach, the waves and spray, the Golden Gate Bridge, the light, the camera move and the timing. Instead of the original line she shouts: \"Catch me if you can, San Francisco!\" Keep the 16:9 frame and the same length."}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.result.assets[0].assetId'&lt;/span&gt; swap.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; swap.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;/p&gt;Before: the original rider&lt;br&gt;
After: the rider from the photo&lt;p&gt;&lt;/p&gt;

&lt;p&gt;At 138 seconds this was the slowest job of the walkthrough, which is why every job here runs async. The clip is the same ride with the other woman on the motorcycle, shouting the new line. Muse said "Done. She's in, 10 seconds, 16:9, same ride, same bridge, same waves."&lt;/p&gt;

&lt;h4&gt;
  
  
  9. Check the weekly allowance
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-muse-v1/get-muse-accounts-email" rel="noopener noreferrer"&gt;GET /accounts/&lt;code&gt;email&lt;/code&gt;&lt;/a&gt; reads the account's plan and usage live:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;get &lt;span class="s2"&gt;"accounts/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;enc &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$EMAIL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="s1"&gt;'{session, quota}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;quota.percentUsed&lt;/code&gt; is the share of the week used, in whole percent, and &lt;code&gt;quota.resetsAt&lt;/code&gt; is when it starts over, a week after it began. The three videos above used 2 to 3 percent each and the images 0 or 1. Over the whole test session, which also ran two jobs not shown here, the free account went from 16 to 28 percent. When an account runs out, new jobs without &lt;code&gt;email&lt;/code&gt; go to your other accounts, and a job pinned to it answers &lt;code&gt;412&lt;/code&gt; until &lt;code&gt;resetsAt&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What we learned
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Write the aspect ratio as &lt;code&gt;in exactly 16:9 aspect ratio&lt;/code&gt;. &lt;code&gt;Cinematic 16:9 landscape photo&lt;/code&gt; came back 3:2 once.&lt;/li&gt;
&lt;li&gt;Every video is about 10 seconds. A prompt asking for 5 seconds still got 10.&lt;/li&gt;
&lt;li&gt;An image-to-video clip keeps the shape of its image unless the prompt asks for another one: &lt;code&gt;in exactly 9:16 aspect ratio&lt;/code&gt; turned our 16:9 beach picture into a vertical 720×1280 clip, re-framed rather than stretched.&lt;/li&gt;
&lt;li&gt;Lines written in quotes in a video prompt are spoken.&lt;/li&gt;
&lt;li&gt;Pass generated files on by &lt;code&gt;assetId&lt;/code&gt;. They stay in the account's workspace, so a chain of edits needs no downloads in between.&lt;/li&gt;
&lt;li&gt;Say what must stay the same. "Same position, same orientation, not mirrored or redrawn" kept the real beach in the composite.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;503&lt;/code&gt; with Muse's own words such as "glitched out" is worth running again. A &lt;code&gt;403&lt;/code&gt; is a refusal and needs a different prompt.&lt;/li&gt;
&lt;li&gt;Send videos with &lt;code&gt;async: true&lt;/code&gt;. A sync request waits about 100 seconds, and the swap took 138.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Frequently asked questions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Is there an API for Meta Muse (muse.ai)?&lt;/strong&gt; useapi.net offers one: the &lt;a href="https://useapi.net/docs/api-muse-v1" rel="noopener noreferrer"&gt;Muse API&lt;/a&gt; runs Muse on your own account. You add the account with its email and password, then make images with &lt;a href="https://useapi.net/docs/api-muse-v1/post-muse-jobs-image" rel="noopener noreferrer"&gt;POST /jobs/image&lt;/a&gt; and videos with &lt;a href="https://useapi.net/docs/api-muse-v1/post-muse-jobs-video" rel="noopener noreferrer"&gt;POST /jobs/video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it work on the free Muse plan?&lt;/strong&gt; Yes. Everything on this page was made on the free plan (&lt;code&gt;HATCH_FREE&lt;/code&gt;), which has a weekly allowance. A video used 2 to 3 percent of it and an image 0 to 1 percent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I set the aspect ratio, length or resolution?&lt;/strong&gt; In the prompt. There are no parameters for them. The aspect ratio is followed when written as &lt;code&gt;in exactly 16:9 aspect ratio&lt;/code&gt;. Videos are always about 10 seconds at about 720p, with sound.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use my own photos and videos?&lt;/strong&gt; Yes. Upload them with &lt;a href="https://useapi.net/docs/api-muse-v1/post-muse-assets" rel="noopener noreferrer"&gt;POST /assets&lt;/a&gt;, up to 8.6 MB each, and pass the &lt;code&gt;assetId&lt;/code&gt; as &lt;code&gt;image_1&lt;/code&gt;..&lt;code&gt;image_9&lt;/code&gt;; &lt;a href="https://useapi.net/docs/api-muse-v1/post-muse-jobs-video" rel="noopener noreferrer"&gt;video jobs&lt;/a&gt; also take &lt;code&gt;video_1&lt;/code&gt;..&lt;code&gt;video_3&lt;/code&gt; and &lt;code&gt;audio_1&lt;/code&gt;..&lt;code&gt;audio_3&lt;/code&gt;. All inputs of one job must be on the same account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I make a photo talk?&lt;/strong&gt; Pass it as &lt;code&gt;image_1&lt;/code&gt; to &lt;a href="https://useapi.net/docs/api-muse-v1/post-muse-jobs-video" rel="noopener noreferrer"&gt;POST /jobs/video&lt;/a&gt; with a prompt like &lt;code&gt;Animate image_1: … she says softly: "…"&lt;/code&gt;, as in step 7.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can it replace a person in a video?&lt;/strong&gt; Yes. Pass the clip as &lt;code&gt;video_1&lt;/code&gt; and a photo of the new person as &lt;code&gt;image_1&lt;/code&gt;, and ask Muse to replace the person and keep everything else, as in step 8.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why did my sync request return 202?&lt;/strong&gt; The job was still running after about 100 seconds. It keeps running on our side. Fetch it with &lt;a href="https://useapi.net/docs/api-muse-v1/get-muse-jobs-jobid" rel="noopener noreferrer"&gt;GET /jobs/&lt;code&gt;jobid&lt;/code&gt;&lt;/a&gt;, or send long jobs with &lt;code&gt;async: true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why did Muse email me a login code?&lt;/strong&gt; The API signed in to the account, which happens when you add it and when the session is renewed, about once every 30 days. The code needs no action. See &lt;a href="https://useapi.net/docs/start-here/setup-muse#what-to-expect" rel="noopener noreferrer"&gt;Setup Muse&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Visit our &lt;a href="https://discord.gg/w28uK3cnmF" rel="noopener noreferrer"&gt;Discord Server&lt;/a&gt; or &lt;a href="https://t.me/use_api" rel="noopener noreferrer"&gt;Telegram Channel&lt;/a&gt; for any support questions and concerns.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>tutorial</category>
      <category>meta</category>
    </item>
    <item>
      <title>How to Make AI Influencer Videos with Avatars via the Google Vids API</title>
      <dc:creator>useapi.net</dc:creator>
      <pubDate>Fri, 09 Oct 2026 05:20:29 +0000</pubDate>
      <link>https://dev.to/useapi/how-to-make-ai-influencer-videos-with-avatars-via-the-google-vids-api-3ide</link>
      <guid>https://dev.to/useapi/how-to-make-ai-influencer-videos-with-avatars-via-the-google-vids-api-3ide</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The &lt;a href="https://useapi.net/docs/api-google-vids-v1" rel="noopener noreferrer"&gt;useapi.net Google Vids API&lt;/a&gt; makes talking AI influencer videos from avatars: save a picture and one of 30 Gemini voices once with POST /avatars, then pass the avatar's id to any &lt;a href="https://blog.google/products-and-platforms/products/workspace/gemini-omni-in-google-vids/" rel="noopener noreferrer"&gt;Gemini Omni 1.1 Flash&lt;/a&gt; clip, where it speaks the lines you write in the prompt.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The API runs on your own &lt;a href="https://docs.google.com/videos" rel="noopener noreferrer"&gt;Google Vids&lt;/a&gt; account. This walkthrough makes two influencers and launches a sneaker with them. Mia's avatar comes from a portrait made with the API, and Leo's is drawn by Google from a written description. They present the AeroLoop, a made-up sneaker, on a theater stage in one 10-second clip with both avatars and a product image, and two extends take it to 30 seconds. An edit moves the scene to a rooftop, and two more clips show what the same calls make without avatars. Every request below is the one that made the media on this page, with the ids replaced and &lt;code&gt;async: true&lt;/code&gt; added by the &lt;code&gt;run&lt;/code&gt; helper.&lt;/p&gt;



&lt;p&gt;&lt;small&gt;The finished 30-second clip at &lt;code&gt;720p&lt;/code&gt;: one 10-second generation and two 10-second extends (steps 6 to 8).&lt;/small&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What it cost
&lt;/h3&gt;

&lt;p&gt;useapi.net is an API, not a video service of its own. Every call runs on a Google account you connect through &lt;a href="https://useapi.net/docs/start-here/setup-google-vids" rel="noopener noreferrer"&gt;Setup Google Vids&lt;/a&gt;, on a paid Google AI plan, and uses that account's monthly Vids allowance: seconds of video and a count of images. Google AI Ultra $199 gets 10,000 seconds of video and 1,000 images a month. You pay useapi.net a flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; for every API we offer, with no per-clip charge. See &lt;a href="https://useapi.net/docs/api-google-vids-v1#plans-and-monthly-allowances" rel="noopener noreferrer"&gt;Plans and monthly allowances&lt;/a&gt; for the other plans.&lt;/p&gt;

&lt;p&gt;What each kept result used, taken from the change in &lt;code&gt;result.quota&lt;/code&gt;, and how long each job took (&lt;code&gt;result.elapsedMs&lt;/code&gt;):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Allowance used&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mia's portrait&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-images" rel="noopener noreferrer"&gt;POST /images&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;1 image&lt;/td&gt;
&lt;td&gt;9 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The AeroLoop product shot&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-images" rel="noopener noreferrer"&gt;POST /images&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;1 image&lt;/td&gt;
&lt;td&gt;9 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mia's avatar, from her portrait&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-avatars" rel="noopener noreferrer"&gt;POST /avatars&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;nothing&lt;/td&gt;
&lt;td&gt;about 2 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leo's avatar, from a description&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-avatars" rel="noopener noreferrer"&gt;POST /avatars&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;1 image&lt;/td&gt;
&lt;td&gt;about 20 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The 10-second launch clip&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-videos" rel="noopener noreferrer"&gt;POST /videos&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;10 s&lt;/td&gt;
&lt;td&gt;38 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extend to 20 seconds&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-videos-extend" rel="noopener noreferrer"&gt;POST /videos/extend&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;10 s&lt;/td&gt;
&lt;td&gt;70 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extend to 30 seconds&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-videos-extend" rel="noopener noreferrer"&gt;POST /videos/extend&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;10 s&lt;/td&gt;
&lt;td&gt;85 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Upscale the 20 seconds to 1080p&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-videos-upscale" rel="noopener noreferrer"&gt;POST /videos/upscale&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;20 s&lt;/td&gt;
&lt;td&gt;62 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rooftop edit&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-videos-edit" rel="noopener noreferrer"&gt;POST /videos/edit&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;10 s&lt;/td&gt;
&lt;td&gt;64 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit of the 30-second clip&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-videos-edit" rel="noopener noreferrer"&gt;POST /videos/edit&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;10 s&lt;/td&gt;
&lt;td&gt;87 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Product hero clip&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-videos" rel="noopener noreferrer"&gt;POST /videos&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;10 s&lt;/td&gt;
&lt;td&gt;62 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The pigeon&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-videos" rel="noopener noreferrer"&gt;POST /videos&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;5 s&lt;/td&gt;
&lt;td&gt;54 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;85 s of video, 3 images&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;An extend uses only the seconds it adds, not the length of the clip. An upscale uses the clip's full length again, and an edit uses the length of the clip it returns. &lt;code&gt;720p&lt;/code&gt; and &lt;code&gt;1080p&lt;/code&gt; cost the same when you generate. A clip you generate again costs its seconds again.&lt;/p&gt;

&lt;h4&gt;
  
  
  What a 10-second Omni clip costs
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Where&lt;/th&gt;
&lt;th&gt;One 10-second Omni 1.1 Flash clip&lt;/th&gt;
&lt;th&gt;10-second clips a month&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Google's metered &lt;a href="https://ai.google.dev/gemini-api/docs/pricing" rel="noopener noreferrer"&gt;Gemini API&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;about $1.01 at &lt;code&gt;720p&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;as many as you pay for&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://useapi.net/docs/api-google-flow-v1" rel="noopener noreferrer"&gt;Google Flow API&lt;/a&gt; on Google AI Ultra ($199)&lt;/td&gt;
&lt;td&gt;15 credits, about $0.12&lt;/td&gt;
&lt;td&gt;about 1,666&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://useapi.net/docs/api-google-vids-v1" rel="noopener noreferrer"&gt;Google Vids API&lt;/a&gt; on Google AI Ultra ($199)&lt;/td&gt;
&lt;td&gt;10 seconds of allowance, about $0.20&lt;/td&gt;
&lt;td&gt;about 1,000, shared by the family plan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flow and Vids on the same Ultra account&lt;/td&gt;
&lt;td&gt;about $0.07&lt;/td&gt;
&lt;td&gt;about 2,666&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Gemini API bills Omni 1.1 Flash at 5,792 tokens per second of &lt;code&gt;720p&lt;/code&gt; video, at $17.50 per million tokens. At that rate, 2,666 ten-second clips would cost about $2,700 a month, against one Ultra plan and the $15 useapi.net subscription. Prices as of October 2026.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before you start
&lt;/h3&gt;

&lt;p&gt;You need a useapi.net &lt;a href="https://useapi.net/docs/start-here/setup-useapi" rel="noopener noreferrer"&gt;API token&lt;/a&gt; and a Google account on a paid Google AI plan connected through &lt;a href="https://useapi.net/docs/start-here/setup-google-vids" rel="noopener noreferrer"&gt;Setup Google Vids&lt;/a&gt;. A free Google account gets no Vids allowance: it can still be added, but only makes avatars. Every call is also in the &lt;a href="https://www.postman.com/useapinet/useapi-net/collection/29112081-9ef3d017-d44c-4f43-a4cb-7351b9b265df" rel="noopener noreferrer"&gt;Postman collection&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also in Chinese: &lt;a href="https://useapi.net/docs/articles/google-vids-api-zh" rel="noopener noreferrer"&gt;中文教程&lt;/a&gt;. The whole pipeline is also on GitHub as one script, in Node.js and Python: &lt;a href="https://github.com/useapi/google-vids-api/tree/main/influencer-avatars" rel="noopener noreferrer"&gt;&lt;code&gt;influencer-avatars/&lt;/code&gt;&lt;/a&gt; in &lt;a href="https://github.com/useapi/google-vids-api" rel="noopener noreferrer"&gt;useapi/google-vids-api&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The steps use &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;jq&lt;/code&gt; and these variables and helpers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;USEAPI_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"user:12345-..."&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;EMAIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"user@example.com"&lt;/span&gt;
&lt;span class="nv"&gt;API&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://api.useapi.net/v1/google-vids
&lt;span class="nv"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
enc&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; jq &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; v &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'$v|@uri'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
post&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$AUTH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
get&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$AUTH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
download&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; curl &lt;span class="nt"&gt;-sSf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/media/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;enc &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$AUTH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# run a video job async: submit it, poll GET /jobs/{jobid} every 10 s, save the final job record to $1&lt;/span&gt;
run&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;job &lt;span class="nb"&gt;id
  &lt;/span&gt;&lt;span class="nv"&gt;job&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;post &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="s1"&gt;'. + {async: true}'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .jobid &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$job&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .status &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$job&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; processing &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;10
    &lt;span class="nv"&gt;job&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;get &lt;span class="s2"&gt;"jobs/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;enc &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;done
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$job&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  jq &lt;span class="s1"&gt;'{status, error, duration: .result.duration, resolution: .result.resolution, videoLeft: .result.quota.video.left}'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every generation runs as a job. Without &lt;code&gt;async&lt;/code&gt;, a POST waits up to about 100 seconds and returns the finished job record, or &lt;code&gt;202&lt;/code&gt; with the job still running. A new 10-second clip took 38 to 62 seconds here, and extends, edits and the upscale took 62 to 87. Some take longer than the sync wait, so &lt;code&gt;run&lt;/code&gt; submits video jobs with &lt;code&gt;async: true&lt;/code&gt; and polls &lt;a href="https://useapi.net/docs/api-google-vids-v1/get-google-vids-jobs-jobid" rel="noopener noreferrer"&gt;GET /jobs/&lt;code&gt;jobid&lt;/code&gt;&lt;/a&gt;. If &lt;code&gt;run&lt;/code&gt; prints any &lt;code&gt;status&lt;/code&gt; other than &lt;code&gt;completed&lt;/code&gt;, stop there and read its &lt;code&gt;error&lt;/code&gt;: the lines after it expect a finished clip.&lt;/p&gt;

&lt;p&gt;To be called back instead of polling, add &lt;code&gt;replyUrl: "https://example.com/hooks/vids"&lt;/code&gt; (and optionally &lt;code&gt;replyRef: "launch-push-in"&lt;/code&gt;) to any body below. The API then sends one &lt;code&gt;POST&lt;/code&gt; of the final job record, as JSON, to that URL when the job completes or fails.&lt;/p&gt;

&lt;p&gt;Ids contain &lt;code&gt;:&lt;/code&gt; and &lt;code&gt;@&lt;/code&gt;, so &lt;code&gt;enc&lt;/code&gt; URL-encodes them whenever they go into a URL path. Every input of one video must come from the same Google account. The images and the upload pin &lt;code&gt;email&lt;/code&gt;, Mia's avatar inherits the portrait's account, and a video job runs on the account that holds its inputs. The pigeon clip has no inputs, so add &lt;code&gt;email&lt;/code&gt; to it if you connect more than one account.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it was built
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Mia's portrait
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-images" rel="noopener noreferrer"&gt;POST /images&lt;/a&gt; makes one JPEG per call, here in portrait (&lt;code&gt;9:16&lt;/code&gt;, 768×1376) with the &lt;code&gt;photography&lt;/code&gt; style.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;post images &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; email &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$EMAIL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{email: $email, aspectRatio: "9:16", style: "photography",
  prompt: "Full-length studio portrait of a confident 24-year-old female fashion influencer, platinum bob, oversized cream hoodie, wide-leg cargo pants, gold hoops, plain light-grey backdrop, facing camera"}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; mia-portrait.json
&lt;span class="nv"&gt;MIA_IMAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .result.mediaId mia-portrait.json&lt;span class="si"&gt;)&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MIA_IMAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; mia-portrait.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1557564504542421142%2Fvids-influencer-mia-portrait-1007.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1557564504542421142%2Fvids-influencer-mia-portrait-1007.jpg" alt="Mia, a generated full-length portrait of a fashion influencer in a cream hoodie and cargo pants, made with POST /images" width="768" height="1376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Generated images stay available for a few hours only. Make the avatar from it right away, and see the product hero clip for using an image later.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. The AeroLoop product shot
&lt;/h4&gt;

&lt;p&gt;The same call in landscape (&lt;code&gt;16:9&lt;/code&gt;, 1376×768) gives the product reference the clips use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;post images &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; email &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$EMAIL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{email: $email, aspectRatio: "16:9", style: "photography",
  prompt: "The AeroLoop sneaker: chunky white-and-electric-blue running shoe with a translucent air sole, on a concrete pedestal, dramatic side light, dark background"}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; aeroloop.json
&lt;span class="nv"&gt;SHOE_IMAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .result.mediaId aeroloop.json&lt;span class="si"&gt;)&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SHOE_IMAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; aeroloop.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1557564452268675112%2Fvids-influencer-aeroloop-product-1007.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1557564452268675112%2Fvids-influencer-aeroloop-product-1007.jpg" alt="The AeroLoop sneaker, a white and electric-blue running shoe with a translucent sole on a concrete pedestal, made with POST /images" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Pick the voices
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/get-google-vids-voices" rel="noopener noreferrer"&gt;GET /voices&lt;/a&gt; lists the 30 voices with Google's English sample of each. It is public and needs no token. Mia speaks with &lt;code&gt;Aoede&lt;/code&gt; (Vids calls it Tova, style "Breezy") and Leo with &lt;code&gt;Puck&lt;/code&gt; (Neo, "Upbeat"). &lt;code&gt;POST /avatars&lt;/code&gt; takes either name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/voices"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.voices[] | "\(.name)\t\(.voice)\t\(.style)\t\(.preview)"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Mia's avatar from her portrait
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-avatars" rel="noopener noreferrer"&gt;POST /avatars&lt;/a&gt; with &lt;code&gt;image&lt;/code&gt; set to the portrait's &lt;code&gt;mediaId&lt;/code&gt; saves Mia as an avatar on the same account in about 2 seconds. It costs nothing beyond the image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;post avatars &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; img &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MIA_IMAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{name: "Mia", voice: "Aoede", image: $img}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; mia-avatar.json
&lt;span class="nv"&gt;MIA_AVATAR_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .avatarId mia-avatar.json&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"avatarId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-user@example.com-avatar:eyJnIjoiaDM5…"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mia"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"voice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tova"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"voiceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Aoede"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"voiceStyle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Breezy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"voicePreview"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://ssl.gstatic.com/docs/videos/audio/voice_samples/gemini-v4s-tts/1.1/en/Aoede.wav"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"image"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An avatar cannot be made from your own photo. A real person's avatar is Google's likeness feature, which needs a live selfie video and a phone check in the browser, so &lt;code&gt;POST /avatars&lt;/code&gt; refuses an uploaded photo with &lt;code&gt;400&lt;/code&gt;. Use an image made with the API, as here, or a description, as in the next step.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. Leo's avatar from a description
&lt;/h4&gt;

&lt;p&gt;With &lt;code&gt;appearance&lt;/code&gt; instead of &lt;code&gt;image&lt;/code&gt;, Google draws the person. &lt;code&gt;outfit&lt;/code&gt; and &lt;code&gt;shot&lt;/code&gt; are optional, and so are &lt;code&gt;expression&lt;/code&gt; and &lt;code&gt;details&lt;/code&gt;. Drawing the picture uses 1 image of the allowance, and the response carries it as &lt;code&gt;previewMediaId&lt;/code&gt;. In our runs a description avatar came out 1280×720 (16:9), whatever &lt;code&gt;shot&lt;/code&gt; we picked.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;post avatars &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; email &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$EMAIL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{email: $email, name: "Leo", voice: "Puck", shot: "upper-body",
  appearance: "a 26-year-old white European male streetwear influencer with short textured hair with a fade and a confident half-smile",
  outfit: "black puffer vest over a white tee, silver chain"}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; leo-avatar.json
&lt;span class="nv"&gt;LEO_AVATAR_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .avatarId leo-avatar.json&lt;span class="si"&gt;)&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .previewMediaId leo-avatar.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; leo-avatar.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"avatarId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-user@example.com-avatar:eyJnIjoiaDM5…"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Leo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"voice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Neo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"voiceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Puck"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"voiceStyle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Upbeat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"voicePreview"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://ssl.gstatic.com/docs/videos/audio/voice_samples/gemini-v4s-tts/1.1/en/Puck.wav"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"generated"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"previewMediaId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-user@example.com-image:eyJ1IjoiaHR0…"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"look"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"appearance"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a 26-year-old white European male streetwear influencer with short textured hair with a fade and a confident half-smile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outfit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"black puffer vest over a white tee, silver chain"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"shot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"upper-body"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1557564500096319691%2Fvids-influencer-leo-avatar-from-description-1007.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1557564500096319691%2Fvids-influencer-leo-avatar-from-description-1007.jpg" alt="Leo, an avatar Google drew from a description: a young man in a black puffer vest over a white tee with a silver chain, 1280x720" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both avatars stay in the account's Vids document until you delete them with &lt;a href="https://useapi.net/docs/api-google-vids-v1/delete-google-vids-avatars-avatarId" rel="noopener noreferrer"&gt;DELETE /avatars/&lt;code&gt;avatarId&lt;/code&gt;&lt;/a&gt;. &lt;a href="https://useapi.net/docs/api-google-vids-v1/get-google-vids-avatars" rel="noopener noreferrer"&gt;GET /avatars&lt;/a&gt; lists them, with their ids, whenever you need them again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;get &lt;span class="s2"&gt;"avatars?email=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;enc &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$EMAIL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.avatars[] | "\(.name)\t\(.voiceId)\t\(.avatarId)"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  6. The launch: two avatars and the product in one clip
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-videos" rel="noopener noreferrer"&gt;POST /videos&lt;/a&gt; takes up to 3 references in all, avatars (&lt;code&gt;avatar_1&lt;/code&gt;..&lt;code&gt;avatar_3&lt;/code&gt;) and images (&lt;code&gt;referenceImage_1&lt;/code&gt;..&lt;code&gt;referenceImage_3&lt;/code&gt;) together. In the prompt, &lt;code&gt;@avatar_1&lt;/code&gt;, &lt;code&gt;@avatar_2&lt;/code&gt; and &lt;code&gt;@referenceImage_1&lt;/code&gt; stand for them, and each avatar speaks its quoted line in its own voice. The product image's &lt;code&gt;mediaId&lt;/code&gt; goes in directly: the API fetches the image and uploads it on that account.&lt;/p&gt;



&lt;p&gt;&lt;small&gt;10 seconds, &lt;code&gt;720p&lt;/code&gt;, 38 seconds to generate.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;The same clip with the visible Gemini ✦ removed by our &lt;a href="https://github.com/useapi/google-vids-api/tree/main/watermark-remover" rel="noopener noreferrer"&gt;watermark remover&lt;/a&gt;, with one command: &lt;code&gt;python3 vids_watermark_remover.py launch-10s.mp4&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;&lt;small&gt;The remover works on clips as generated and on upscales of them, at &lt;code&gt;720p&lt;/code&gt; and &lt;code&gt;1080p&lt;/code&gt;. It does not work on extended or edited clips: Google feeds the marked clip back to the model, which repaints the star into the picture. The invisible SynthID watermark is not touched.&lt;/small&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  7. Extend to 20 seconds
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-videos-extend" rel="noopener noreferrer"&gt;POST /videos/extend&lt;/a&gt; adds 3 to 10 seconds and returns the whole clip with a new &lt;code&gt;mediaId&lt;/code&gt;. An extend takes only the clip and a prompt, not the avatars, so the prompt describes the new action and names people by what they wear ("the man in the black puffer vest"). A fan in a red hoodie storms the stage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PROMPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
A young man in a red hoodie climbs onto the stage from the front right edge and plants himself to the right of the man in the black puffer vest, an arm's length away, so all three stand apart in a row with nobody overlapping. Visibly overexcited, he waves a thick stack of banknotes in his right hand above his head and screams: "Take my money!" The man in the black puffer vest laughs, raises both palms toward him and says: "Whoa, whoa, buddy, be patient!" The blonde woman in the cream hoodie laughs, holding the sneaker. Only these three people are on stage. Same stage, same LED screen with WEAR AEROLOOP, same wide steady shot.
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
run launch-20s.json videos/extend &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LAUNCH_10S&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; p &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PROMPT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{mediaId: $id, prompt: $p, duration: 10}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;LAUNCH_20S&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .result.mediaId launch-20s.json&lt;span class="si"&gt;)&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LAUNCH_20S&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; launch-20s.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;small&gt;20 seconds, &lt;code&gt;720p&lt;/code&gt;, 70 seconds to generate. It used 10 seconds of allowance, the seconds it added.&lt;/small&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  8. Extend to 30 seconds
&lt;/h4&gt;

&lt;p&gt;The second extend continues the 20-second clip.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PROMPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
The blonde woman in the cream hoodie turns to the camera with a big smile and says: "AeroLoop drops Friday. Link in bio!" Right after that, the young man in the red hoodie throws ALL of his banknotes out over the audience in one big toss, keeping none, and the bills flutter down over their heads. From then on his hands are completely empty: he holds no money at all. Then all three cheer together, the man in the black puffer vest and the young man in the red hoodie throwing their empty fists in the air, as blue and white confetti rains down over the stage. Only these three people are on stage. Same stage, same LED screen with WEAR AEROLOOP, same wide steady shot.
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
run launch-30s.json videos/extend &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LAUNCH_20S&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; p &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PROMPT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{mediaId: $id, prompt: $p, duration: 10}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;LAUNCH_30S&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .result.mediaId launch-30s.json&lt;span class="si"&gt;)&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LAUNCH_30S&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; launch-30s.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;The result is the finished clip: 30 seconds, &lt;code&gt;720p&lt;/code&gt;, 85 seconds to generate, and again 10 seconds of allowance. You can keep going: chains of extends work up to 40 seconds, for example four 10-second steps. Past that, Google keeps only about the first 31 seconds of the source and adds the new seconds after them, so the longest clip is about 41 seconds.&lt;/p&gt;

&lt;h4&gt;
  
  
  9. Upscale to 1080p
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-videos-upscale" rel="noopener noreferrer"&gt;POST /videos/upscale&lt;/a&gt; turns a &lt;code&gt;720p&lt;/code&gt; clip into &lt;code&gt;1080p&lt;/code&gt; and keeps its length. It works on clips of up to 20 seconds, so we upscaled the 20-second clip from step 7, not the 30-second one. It used the clip's 20 seconds again and took 62 seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;run launch-20s-1080p.json videos/upscale &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LAUNCH_20S&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{mediaId: $id}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .result.mediaId launch-20s-1080p.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; launch-20s-1080p.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;small&gt;The 20-second clip, upscaled to 1920×1080.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Why not the 30-second clip: Google returned it at 1920×1080, but with its frames out of order, three times out of three. The confetti ending flickered in before the fan arrived. The 20-second clip came back in order, and the Vids editor itself stops at 20 seconds, so the API refuses upscales of clips longer than 20 seconds with &lt;code&gt;400&lt;/code&gt;, before anything is charged.&lt;/p&gt;

&lt;p&gt;So for a &lt;code&gt;1080p&lt;/code&gt; clip:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make, extend and edit at &lt;code&gt;720p&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Upscale the clip once it is finished, while it is 20 seconds or shorter.&lt;/li&gt;
&lt;li&gt;For a longer clip, stay at &lt;code&gt;720p&lt;/code&gt;, set &lt;code&gt;resolution: "1080p"&lt;/code&gt; on the last extend only, or extend at &lt;code&gt;1080p&lt;/code&gt; throughout and accept softer faces.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;More from the same account and inputs: an edit, a product clip from a start image, and a text-only clip.&lt;/p&gt;

&lt;h4&gt;
  
  
  Move the launch to a rooftop
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-videos-edit" rel="noopener noreferrer"&gt;POST /videos/edit&lt;/a&gt; changes a generated clip by prompt and returns a new clip. The source goes in &lt;code&gt;video&lt;/code&gt;. This edit of the 10-second launch clip used 10 seconds and took 64 seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;run launch-rooftop.json videos/edit &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; v &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LAUNCH_10S&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'{video: $v, prompt: "Move the whole scene to a rooftop at sunset, with the city skyline behind them. Same two people, same action, same words."}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .result.mediaId launch-rooftop.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; launch-rooftop.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;An edit works on up to 10 seconds. The same edit of the 30-second clip, with "Same three people", came back 10 seconds long: the first 10 seconds, moved to the rooftop. It used 10 seconds of allowance. To get a longer edited clip, edit the 10-second clip and extend the result, since an extend accepts an edited clip.&lt;/p&gt;



&lt;p&gt;&lt;small&gt;The edit of the 30-second clip: 10 seconds back.&lt;/small&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  A product hero clip from a start image
&lt;/h4&gt;

&lt;p&gt;With &lt;code&gt;startImage&lt;/code&gt; the clip opens on that image. A generated image's link expires within hours, so we uploaded the saved &lt;code&gt;aeroloop.jpg&lt;/code&gt; with &lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-assets" rel="noopener noreferrer"&gt;POST /assets&lt;/a&gt; and passed its &lt;code&gt;assetId&lt;/code&gt;. A single clip has no extends, so it was made at &lt;code&gt;1080p&lt;/code&gt; directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;SHOE_ASSET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/assets?email=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;enc &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$EMAIL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$AUTH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: image/jpeg"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-binary&lt;/span&gt; @aeroloop.jpg | jq &lt;span class="nt"&gt;-r&lt;/span&gt; .assetId&lt;span class="si"&gt;)&lt;/span&gt;
run hero.json videos &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; img &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SHOE_ASSET&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{startImage: $img, duration: 10, resolution: "1080p", aspectRatio: "landscape",
  prompt: "Slow 360° orbit around the sneaker, blue light rippling through the translucent sole, dust sparkling in the air, cinematic."}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .result.mediaId hero.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; hero.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;small&gt;10 seconds, &lt;code&gt;1080p&lt;/code&gt;.&lt;/small&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  A pigeon in AeroLoops
&lt;/h4&gt;

&lt;p&gt;A text-only clip, in portrait at &lt;code&gt;1080p&lt;/code&gt; (1080×1920). The 5 seconds took 54 seconds to generate and used 5 seconds of allowance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;run pigeon.json videos &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s1"&gt;'{duration: 5, resolution: "1080p", aspectRatio: "portrait",
  prompt: "A pigeon in tiny white-and-electric-blue AeroLoop sneakers struts down a city sidewalk like a runway model, head bobbing to the beat. Pedestrians stop and film it with their phones. It pauses, does a slow-motion hair flip with its head feathers, and struts on. Funny, sunny, shot on a phone at pigeon height."}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
download &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .result.mediaId pigeon.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; pigeon.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;The pigeon at &lt;code&gt;1080p&lt;/code&gt; portrait (1080×1920), with the ✦ removed the same way: &lt;code&gt;python3 vids_watermark_remover.py pigeon-5s.mp4&lt;/code&gt;. The script reads the frame size, works out where the star is and how big (it scales with the short side, so here it is 1.5 times the &lt;code&gt;720p&lt;/code&gt; star), reverses the blend on all 120 frames, re-encodes the video at CRF 18 and copies the audio unchanged. The 5-second clip took about 10 seconds on a 14-core PC, the same as the 10-second &lt;code&gt;720p&lt;/code&gt; launch clip above. It needs Python 3.8+, &lt;code&gt;numpy&lt;/code&gt; and &lt;code&gt;ffmpeg&lt;/code&gt;; see the &lt;a href="https://github.com/useapi/google-vids-api/tree/main/watermark-remover" rel="noopener noreferrer"&gt;watermark remover&lt;/a&gt; on GitHub.&lt;/p&gt;



&lt;h3&gt;
  
  
  What we learned
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;1080p&lt;/code&gt; clip behaves like an upscaled &lt;code&gt;720p&lt;/code&gt; one. Build a chain of extends at &lt;code&gt;720p&lt;/code&gt;: at &lt;code&gt;1080p&lt;/code&gt; the faces got softer and more waxy at every step.&lt;/li&gt;
&lt;li&gt;Upscale only clips of up to 20 seconds. Our 30-second upscale came back with its frames out of order every time.&lt;/li&gt;
&lt;li&gt;Generate a single clip at &lt;code&gt;1080p&lt;/code&gt; if you want &lt;code&gt;1080p&lt;/code&gt; and won't extend it. It costs the same as &lt;code&gt;720p&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Write an extend prompt about the new action only. The extend gets the clip, not the avatars, so name people by what they wear.&lt;/li&gt;
&lt;li&gt;Put a prop in a person's hands in the first sentence that mentions them. A verb like "lifts" made the sneaker appear from nowhere.&lt;/li&gt;
&lt;li&gt;Say what must not happen. The fan kept a stack of banknotes until the prompt said his hands were empty.&lt;/li&gt;
&lt;li&gt;Reuse avatars by &lt;code&gt;avatarId&lt;/code&gt;. Each avatar is a fixed picture and voice, kept until you delete it.&lt;/li&gt;
&lt;li&gt;Make avatars and clips from a generated image within a few hours, or upload the saved file with &lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-assets" rel="noopener noreferrer"&gt;POST /assets&lt;/a&gt; first.&lt;/li&gt;
&lt;li&gt;Edit clips of up to 10 seconds. A longer clip comes back as its first 10 seconds.&lt;/li&gt;
&lt;li&gt;Expect on-screen text to waver. The backdrop's "WEAR AEROLOOP" is misspelled in some frames.&lt;/li&gt;
&lt;li&gt;Every MP4 has Google's visible Gemini ✦ in the bottom-right corner and an invisible SynthID watermark (see &lt;a href="https://useapi.net/docs/api-google-vids-v1#watermark" rel="noopener noreferrer"&gt;Watermark&lt;/a&gt;). Our &lt;a href="https://github.com/useapi/google-vids-api/tree/main/watermark-remover" rel="noopener noreferrer"&gt;watermark remover&lt;/a&gt; takes the visible sparkle off a downloaded clip.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Frequently asked questions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How do I make an AI influencer video through an API?&lt;/strong&gt; Create an avatar with &lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-avatars" rel="noopener noreferrer"&gt;POST /avatars&lt;/a&gt;, from a description or from an image made with &lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-images" rel="noopener noreferrer"&gt;POST /images&lt;/a&gt;, and give it a voice from &lt;a href="https://useapi.net/docs/api-google-vids-v1/get-google-vids-voices" rel="noopener noreferrer"&gt;GET /voices&lt;/a&gt;. Then pass its &lt;code&gt;avatarId&lt;/code&gt; as &lt;code&gt;avatar_1&lt;/code&gt; to &lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-videos" rel="noopener noreferrer"&gt;POST /videos&lt;/a&gt; and write its lines in quotes in the prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I make an avatar from my own photo?&lt;/strong&gt; No. Google treats an avatar of a real person as its likeness feature, which needs a live selfie video and a phone check in the browser. The API refuses an uploaded photo with &lt;code&gt;400&lt;/code&gt;. Use a picture made with &lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-images" rel="noopener noreferrer"&gt;POST /images&lt;/a&gt; or describe the person with &lt;code&gt;appearance&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How many avatars can one clip have?&lt;/strong&gt; Up to 3 references in all, avatars and images together. This walkthrough used two avatars and one product image.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does an avatar look and sound the same in every video?&lt;/strong&gt; It uses the same picture and the same voice every time you pass its &lt;code&gt;avatarId&lt;/code&gt;, since both are saved with the avatar in the account's Vids document. The clip around it still varies from take to take. &lt;a href="https://useapi.net/docs/api-google-vids-v1/get-google-vids-avatars" rel="noopener noreferrer"&gt;GET /avatars&lt;/a&gt; lists your avatars, including ones made in the Google Vids web app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can two avatars talk to each other in one clip?&lt;/strong&gt; Yes. Pass &lt;code&gt;avatar_1&lt;/code&gt; and &lt;code&gt;avatar_2&lt;/code&gt; and give each a quoted line in the prompt, as in step 6.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I make a vertical 9:16 video for TikTok or Reels?&lt;/strong&gt; Yes. Set &lt;code&gt;aspectRatio: "portrait"&lt;/code&gt; on &lt;a href="https://useapi.net/docs/api-google-vids-v1/post-google-vids-videos" rel="noopener noreferrer"&gt;POST /videos&lt;/a&gt; for 720×1280, or 1080×1920 at &lt;code&gt;1080p&lt;/code&gt;, as in the pigeon clip. An extend can also turn a landscape clip into portrait.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How long can a video be?&lt;/strong&gt; A generated clip is 3 to 10 seconds. Extends add 3 to 10 seconds each, up to about 41 seconds in all, and each one uses only the seconds it adds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does it cost?&lt;/strong&gt; A flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; to useapi.net, plus the Vids allowance of your own Google AI plan: Ultra $199 gets 10,000 seconds of video and 1,000 images a month. Everything kept on this page used 85 seconds and 3 images (see What it cost).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why did my sync request return 202?&lt;/strong&gt; The job was still running after about 100 seconds. It keeps running on our side. Fetch it with &lt;a href="https://useapi.net/docs/api-google-vids-v1/get-google-vids-jobs-jobid" rel="noopener noreferrer"&gt;GET /jobs/&lt;code&gt;jobid&lt;/code&gt;&lt;/a&gt;, or send long jobs with &lt;code&gt;async: true&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Visit our &lt;a href="https://discord.gg/w28uK3cnmF" rel="noopener noreferrer"&gt;Discord Server&lt;/a&gt; or &lt;a href="https://t.me/use_api" rel="noopener noreferrer"&gt;Telegram Channel&lt;/a&gt; for any support questions and concerns.&lt;/p&gt;

&lt;p&gt;Check our &lt;a href="https://github.com/useapi/google-vids-api" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; with code examples.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>tutorial</category>
      <category>video</category>
    </item>
    <item>
      <title>How to Turn Web Pages, YouTube Videos and RSS Feeds into NotebookLM Podcasts with n8n</title>
      <dc:creator>useapi.net</dc:creator>
      <pubDate>Mon, 05 Oct 2026 05:53:18 +0000</pubDate>
      <link>https://dev.to/useapi/how-to-turn-web-pages-youtube-videos-and-rss-feeds-into-notebooklm-podcasts-with-n8n-1m0g</link>
      <guid>https://dev.to/useapi/how-to-turn-web-pages-youtube-videos-and-rss-feeds-into-notebooklm-podcasts-with-n8n-1m0g</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Two free n8n workflows send your links to NotebookLM through the &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1" rel="noopener noreferrer"&gt;useapi.net NotebookLM API (Gemini Notebook API)&lt;/a&gt; and bring back the finished podcast as an &lt;code&gt;.m4a&lt;/code&gt; file.&lt;/strong&gt; One is a form where you paste web pages and YouTube videos. The other watches a blog's RSS feed and turns every week's new posts into one episode. Both use only core n8n nodes and run on your own Google account, including a free one.&lt;/p&gt;

&lt;p&gt;The episode below came from the RSS workflow, pointed at Google's AI blog feed with &lt;code&gt;format&lt;/code&gt; set to &lt;code&gt;brief&lt;/code&gt; and &lt;code&gt;length&lt;/code&gt; to &lt;code&gt;short&lt;/code&gt;. Run once by hand, it picked up the two posts from the past week and produced a 1 min 43 s episode in 3 min 23 s.&lt;/p&gt;

&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/notebooklm-n8n-podcast#introduction" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;br&gt;
&lt;small&gt;"Google AI Fights Cyberattacks and Disease", made by the RSS workflow from the Google AI blog feed, brief format, short length, 1 min 43 s, generated in 3 min 23 s&lt;/small&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The two workflows
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Workflow&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Links to podcast&lt;/td&gt;
&lt;td&gt;A form: paste web pages and YouTube links, pick a format and a length, get the &lt;code&gt;.m4a&lt;/code&gt; back&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/useapi/notebooklm-api/blob/main/n8n/notebooklm-podcast.json" rel="noopener noreferrer"&gt;&lt;code&gt;notebooklm-podcast.json&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RSS feed to weekly podcast&lt;/td&gt;
&lt;td&gt;Every Monday at 7:00, the newest posts of a feed become one episode&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/useapi/notebooklm-api/blob/main/n8n/notebooklm-rss-podcast.json" rel="noopener noreferrer"&gt;&lt;code&gt;notebooklm-rss-podcast.json&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both files are in the &lt;a href="https://github.com/useapi/notebooklm-api/tree/main/n8n" rel="noopener noreferrer"&gt;notebooklm-api&lt;/a&gt; repository on GitHub, MIT-licensed. They were tested on self-hosted n8n 2.41.&lt;/p&gt;

&lt;h3&gt;
  
  
  How they work
&lt;/h3&gt;

&lt;p&gt;The form workflow asks for a title, the links (up to 50, one per line), the podcast format and the length. Then it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;creates a notebook with &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-notebooks" rel="noopener noreferrer"&gt;POST /notebooks&lt;/a&gt; and adds the links with &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-sources" rel="noopener noreferrer"&gt;POST /sources&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;checks the notebook every 10 seconds until Google has read every source.&lt;/li&gt;
&lt;li&gt;starts the Audio Overview with &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-artifacts" rel="noopener noreferrer"&gt;POST /artifacts&lt;/a&gt; and polls &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-jobs-jobid" rel="noopener noreferrer"&gt;GET /jobs&lt;/a&gt; every 20 seconds.&lt;/li&gt;
&lt;li&gt;downloads the &lt;code&gt;.m4a&lt;/code&gt; as binary data for the next node.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The RSS workflow does the same from a Schedule Trigger. It reads the feed, keeps the posts published in the last &lt;code&gt;lookbackDays&lt;/code&gt; days (7 by default), newest first and at most &lt;code&gt;maxPosts&lt;/code&gt; (5), and puts them in one notebook named &lt;code&gt;&amp;lt;showName&amp;gt;, &amp;lt;date&amp;gt;&lt;/code&gt;. A week with no new posts makes no episode. The schedule runs in your n8n instance's time zone.&lt;/p&gt;

&lt;p&gt;The formats are &lt;code&gt;deep_dive&lt;/code&gt;, &lt;code&gt;brief&lt;/code&gt;, &lt;code&gt;critique&lt;/code&gt; and &lt;code&gt;debate&lt;/code&gt;, and the lengths are &lt;code&gt;short&lt;/code&gt;, &lt;code&gt;default&lt;/code&gt; and &lt;code&gt;long&lt;/code&gt;. The Settings node (form) or Feed settings node (RSS) also holds &lt;code&gt;language&lt;/code&gt;, for example &lt;code&gt;es&lt;/code&gt;, &lt;code&gt;pt_BR&lt;/code&gt; or &lt;code&gt;zh_Hans&lt;/code&gt;, and &lt;code&gt;email&lt;/code&gt;, which you leave empty unless you want one specific Google account.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set it up
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Get a useapi.net &lt;a href="https://useapi.net/docs/start-here/setup-useapi" rel="noopener noreferrer"&gt;API token&lt;/a&gt; and connect your Google account with the &lt;a href="https://useapi.net/docs/start-here/setup-gemini-notebook" rel="noopener noreferrer"&gt;NotebookLM setup&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;In n8n, import the file with Workflows → Import from File.&lt;/li&gt;
&lt;li&gt;Create a Header Auth credential, for example called &lt;code&gt;useapi.net API token&lt;/code&gt;, with Name &lt;code&gt;Authorization&lt;/code&gt; and Value &lt;code&gt;Bearer &amp;lt;your API token&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select that credential on the six HTTP Request nodes: Create notebook, Add sources, Check sources, Generate Audio Overview, Check job and Download audio.&lt;/li&gt;
&lt;li&gt;For the form, click Execute workflow to test it, or publish (activate) the workflow and open its form URL. For RSS, put your feed in the Feed settings node, click Execute workflow to try it, then publish (activate) it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A short brief takes about 3 to 10 minutes. Add a Google Drive, S3, Telegram or podcast-host node after Download audio to send each episode where you need it. If you change the RSS schedule, change &lt;code&gt;lookbackDays&lt;/code&gt; to match, for example a daily run with &lt;code&gt;lookbackDays: 1&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  When something goes wrong
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;401&lt;/code&gt; on the first HTTP node means the credential is missing or the token is wrong. Check that the value starts with &lt;code&gt;Bearer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;429&lt;/code&gt; on Generate Audio Overview means the Google account is out of NotebookLM usage for now, and the run stops there. The response carries &lt;code&gt;retryAt&lt;/code&gt; when Google names the reset time. To make more episodes, connect more Google accounts through the &lt;a href="https://useapi.net/docs/start-here/setup-gemini-notebook" rel="noopener noreferrer"&gt;NotebookLM setup&lt;/a&gt; and leave &lt;code&gt;email&lt;/code&gt; empty. New notebooks then go to the least busy account, so the next run can land on one that still has usage.&lt;/li&gt;
&lt;li&gt;A failed job stops the workflow with the error Google returned.&lt;/li&gt;
&lt;li&gt;A source that ends in &lt;code&gt;error&lt;/code&gt;, for example a YouTube video without captions, is skipped and the episode uses the rest.&lt;/li&gt;
&lt;li&gt;The workflows keep polling until the sources are read and the job finishes. Stop a run that has been polling for more than about 20 minutes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What it costs
&lt;/h3&gt;

&lt;p&gt;A flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; for useapi.net, which covers every useapi.net API. There is no charge per episode. NotebookLM's usage limits come from your Google plan, and each subscription lets you connect 3 Google accounts, up to 100 in total, to make more. See &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1#run-notebooklm-at-scale" rel="noopener noreferrer"&gt;Run NotebookLM at scale&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  More ways to use the NotebookLM API
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://useapi.net/docs/articles/notebooklm-podcast-example" rel="noopener noreferrer"&gt;A real example&lt;/a&gt;: one podcast, a video overview and an infographic from the same two sources.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://useapi.net/docs/articles/gemini-notebook-bash" rel="noopener noreferrer"&gt;The full tutorial&lt;/a&gt;: every Studio output, chat with citations and Deep Research, with &lt;code&gt;curl&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/useapi/notebooklm-api" rel="noopener noreferrer"&gt;GitHub examples&lt;/a&gt;: Node.js, Python, a Colab notebook and an agent skill for Claude Code and Codex.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Frequently asked questions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Does NotebookLM have an API?&lt;/strong&gt; Google offers a NotebookLM Enterprise API to Google Cloud customers with Enterprise licenses. Of the Studio outputs, it makes Audio Overviews only. The &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1" rel="noopener noreferrer"&gt;useapi.net NotebookLM API&lt;/a&gt; drives your own Google account instead, free or paid, and covers every Studio output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need n8n Cloud?&lt;/strong&gt; No. Both workflows use only core nodes. They were tested on self-hosted n8n and need nothing Cloud-only.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start using the API
&lt;/h3&gt;

&lt;p&gt;A single &lt;strong&gt;$15/month&lt;/strong&gt; subscription covers every API on useapi.net — one token, all services. You connect up to 3 of your own provider accounts per service, and useapi.net handles the REST API, load balancing, and polling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://buy.stripe.com/8x2aEX4Bd8Vh9PMg4qeUU03" rel="noopener noreferrer"&gt;Subscribe — $15/month&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;Pricing, crypto payment, and volume options&lt;/a&gt; — full refund within the first 14 days if you have fewer than 50 successful generations.&lt;/p&gt;

</description>
      <category>notebooklm</category>
      <category>n8n</category>
      <category>automation</category>
      <category>ai</category>
    </item>
    <item>
      <title>How to Make UGC Video Ads in n8n with the Google Flow API</title>
      <dc:creator>useapi.net</dc:creator>
      <pubDate>Sun, 04 Oct 2026 00:25:41 +0000</pubDate>
      <link>https://dev.to/useapi/how-to-make-ugc-video-ads-in-n8n-with-the-google-flow-api-3b2n</link>
      <guid>https://dev.to/useapi/how-to-make-ugc-video-ads-in-n8n-with-the-google-flow-api-3b2n</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A free n8n template makes AI UGC video ads through the &lt;a href="https://useapi.net/docs/api-google-flow-v1" rel="noopener noreferrer"&gt;useapi.net Google Flow API&lt;/a&gt;: one form, up to five products, a consistent Omni 1.1 Flash presenter and voice, and 140 Flow credits for the default ad with four takes of each clip.&lt;/strong&gt; There is no code to write. You open one form URL and click through it, and every free step has a page to pick or re-roll before the clips spend any credits.&lt;/p&gt;

&lt;p&gt;UGC ads are the one-person-talking-to-a-phone videos that fill TikTok, Reels and Shorts. Making them with AI is easy to start and hard to finish, because the presenter's face drifts, the voice changes from clip to clip, and the product on the table turns into a different product. This workflow is built around those three problems. The face and the voice are saved together as one character, every product gets a four-view reference sheet or your real photo, and every clip is filmed in one scene you picked.&lt;/p&gt;

&lt;p&gt;The video model is &lt;a href="https://deepmind.google/models/model-cards/gemini-omni-flash/" rel="noopener noreferrer"&gt;Omni 1.1 Flash&lt;/a&gt;, Google's audio-native model, so the presenter speaks the lines you write, in the voice you picked, with lip sync, in one generation. If you would rather do it in code, the &lt;a href="https://useapi.net/docs/articles/google-flow-ugc-product-video" rel="noopener noreferrer"&gt;UGC product video tutorial&lt;/a&gt; builds a similar video with plain API calls in first-and-last-frame mode, which pins the set exactly but cannot carry a picked voice.&lt;/p&gt;



&lt;strong&gt;"My beauty secrets"&lt;/strong&gt;, a deadpan parody ad&lt;br&gt;&lt;small&gt;made with this n8n template, 1080p, 32 seconds&lt;/small&gt;



&lt;h3&gt;
  
  
  What you need
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;a href="https://n8n.io" rel="noopener noreferrer"&gt;n8n&lt;/a&gt; instance. The workflow uses only core n8n nodes, with no community nodes. It was tested on self-hosted n8n 2.41.&lt;/li&gt;
&lt;li&gt;A useapi.net account with an &lt;a href="https://useapi.net/docs/start-here/setup-useapi" rel="noopener noreferrer"&gt;API token&lt;/a&gt;. One &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month subscription&lt;/a&gt; covers every useapi.net API, with no per-call surcharge.&lt;/li&gt;
&lt;li&gt;A Google account &lt;a href="https://useapi.net/docs/start-here/setup-google-flow" rel="noopener noreferrer"&gt;connected to useapi.net&lt;/a&gt;, on a paid &lt;a href="https://one.google.com/ai" rel="noopener noreferrer"&gt;Google AI&lt;/a&gt; plan. Omni 1.1 Flash video needs a paid plan and spends its Flow credits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How to import the n8n UGC ad template
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Download &lt;a href="https://github.com/useapi/google-flow-api/blob/main/n8n/ugc-ad-factory.json" rel="noopener noreferrer"&gt;&lt;code&gt;ugc-ad-factory.json&lt;/code&gt;&lt;/a&gt; from the example repo, and in n8n choose &lt;strong&gt;Workflows → Import from File&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;Header Auth&lt;/strong&gt; credential whose Name is &lt;code&gt;Authorization&lt;/code&gt; and Value is &lt;code&gt;Bearer &amp;lt;your API token&amp;gt;&lt;/code&gt;, then select it on every HTTP Request node.&lt;/li&gt;
&lt;li&gt;Publish (activate) the workflow and open the URL of the &lt;strong&gt;Start form&lt;/strong&gt; node.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The form is the whole interface. Nothing in the canvas needs editing to make an ad, and the defaults produce a working ad on the first run: a friendly presenter at a bathroom vanity showing a vitamin C serum, with a short intro and a call to action at the end.&lt;/p&gt;

&lt;h3&gt;
  
  
  The pages, one by one
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Setup
&lt;/h4&gt;

&lt;p&gt;The first page asks only for the shape of the ad: the Google account email, where the presenter comes from, how many products (1 to 5), whether to add an intro and a closing clip, vertical 9:16 or horizontal 16:9, and how many takes to film of each clip (1 to 4, default 4). The next page then asks for exactly that many details, with no empty fields.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063604493787197%2Fn8n-ugc-v3-01-setup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063604493787197%2Fn8n-ugc-v3-01-setup.png" alt="The setup page of the n8n UGC ad form: account, presenter source, number of products, intro, closing, format and takes" width="800" height="685"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Details
&lt;/h4&gt;

&lt;p&gt;Here you describe the presenter, the voice, the scene and every clip. Each clip is one sentence of action plus the line in quotes, for example: &lt;em&gt;The presenter picks up the serum, holds it up so the label faces the camera, and says: "This vitamin C serum goes on first every morning."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Depending on what you chose on the setup page, this page can take photos or an ID instead of descriptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Photos of the presenter. One clear photo is enough, and a second one in three-quarter view saves a step. Google screens real faces, so a photo of a real person may be refused when the video is made.&lt;/li&gt;
&lt;li&gt;A saved character ID from an earlier run on the same Google account. It brings the face and the voice, and skips the next three pages.&lt;/li&gt;
&lt;li&gt;A photo of each product. It is used as it is, or turned into a four-view sheet if you choose that option.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063609434546186%2Fn8n-ugc-v3-02-details.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063609434546186%2Fn8n-ugc-v3-02-details.png" alt="The details page: the presenter, the voice, the scene and what is said in each clip" width="800" height="2209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Presenter and second angle
&lt;/h4&gt;

&lt;p&gt;Four presenters are generated from your description. Pick one, or re-roll four new ones with a note such as "older, shorter hair". The next page makes four three-quarter views of the same face, because a second angle helps the face hold in video. A single uploaded photo starts the workflow at the second-angle page, and two photos skip straight to the voice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063621140979732%2Fn8n-ugc-v3-03-presenters.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063621140979732%2Fn8n-ugc-v3-03-presenters.png" alt="Four generated presenter candidates to pick from or re-roll" width="800" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063742549037158%2Fn8n-ugc-v3-04-angles.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063742549037158%2Fn8n-ugc-v3-04-angles.png" alt="Four three-quarter views of the picked presenter" width="800" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Voice
&lt;/h4&gt;

&lt;p&gt;Four of Google's preset voices read your sample line, and you play them in the page. Pick one, or ask for four more, optionally with a new delivery note such as "calmer, British accent". The picked voice and the two angles are saved as one character, and that character is used in every clip, which is what keeps the voice the same across the ad.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063630745931867%2Fn8n-ugc-v3-05-voices.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063630745931867%2Fn8n-ugc-v3-05-voices.png" alt="The voice page: preset voices reading the sample line, with players" width="800" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Product images
&lt;/h4&gt;

&lt;p&gt;Each product gets four reference sheets, each showing the same product from four angles. Pick one per product, or re-roll any single product while the others keep their picks. An uploaded photo appears as it is, with nothing to choose.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063636487933975%2Fn8n-ugc-v3-06-products.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063636487933975%2Fn8n-ugc-v3-06-products.png" alt="Four four-view sheets for each product: a rat poison night cream, garden shears and a cheese grater" width="800" height="1076"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Scene
&lt;/h4&gt;

&lt;p&gt;Four candidates of the presenter with every product in one frame. Every clip is filmed in the scene you pick, so this is where you choose the set, the framing and where each product stands. This page is the last free step, and it shows what the clips will cost before you continue, for example "3 clips × 4 takes ≈ 140 credits".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063643265663086%2Fn8n-ugc-v3-07-scenes.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063643265663086%2Fn8n-ugc-v3-07-scenes.png" alt="Scene candidates with the presenter and all three products, and the credit cost of the clips" width="800" height="897"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Takes
&lt;/h4&gt;

&lt;p&gt;All the takes play in the page, one row per clip. Pick the best take of each clip, or re-roll only the clips you don't like. If Google refuses a clip, the page shows why and puts the clip's action in an editable box. In testing, a refused "lifts the shears in front of the chest" went through on the first try as "points at the shears on the table". Choose 1080p or 720p for the final video.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063654326181988%2Fn8n-ugc-v3-08-takes.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063654326181988%2Fn8n-ugc-v3-08-takes.png" alt="The takes page: every take plays in the page, pick one per clip or re-roll" width="800" height="2022"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Your ad
&lt;/h4&gt;

&lt;p&gt;The last page plays the finished ad and links the MP4. The MP4 is joined on request by the workflow's own download URL, so nothing is stored in n8n, and the clips stay in your Flow account. Your n8n URL must be reachable from the browser you use. If a join between two clips has a pause or clips a word, set how much is cut from the start or end of each clip and re-join, which is free and takes about half a minute. The page also shows the character ID, so the same presenter, with the same face and voice, can front your next ad.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063659220934767%2Fn8n-ugc-v3-09-your-ad.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063659220934767%2Fn8n-ugc-v3-09-your-ad.png" alt="The last page: the joined ad, the MP4 download, the cut points between clips and the saved character ID" width="800" height="1406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How long it takes
&lt;/h3&gt;

&lt;p&gt;The image pages are quick, and slower when captcha needs retries. The clips take 5 to 15 minutes, and the upscale and join a few more. While a step runs, the button turns into a status panel that says what is being made, how long it usually takes, and how long it has been working. Refreshing the page brings you to the next one when it is ready.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063648772792370%2Fn8n-ugc-v3-07b-working-clips.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1556063648772792370%2Fn8n-ugc-v3-07b-working-clips.png" alt="The status panel while the clips are being filmed: what is being made, how long it usually takes, and a running clock" width="780" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How much does an AI UGC ad cost?
&lt;/h3&gt;

&lt;p&gt;Everything except the video clips is free: the presenters, angles, voices, character, product sheets, scenes, the 1080p upscale and the final join. Each Omni 1.1 Flash take spends Flow credits from your Google AI plan, the same as making it in Flow yourself: 7, 10, 12 or 15 credits for a 4, 6, 8 or 10 second clip at 720p.&lt;/p&gt;

&lt;p&gt;The default ad is a 6-second intro, one 10-second product clip and a 6-second closing, which is 35 credits per round of takes and 140 credits with four takes of each clip.&lt;/p&gt;

&lt;p&gt;The same ad on the official &lt;a href="https://ai.google.dev/gemini-api/docs/pricing" rel="noopener noreferrer"&gt;Gemini API&lt;/a&gt; is billed per second of video and per image. Omni 1.1 Flash costs about $0.10 per second of 720p video there, and a Nano Banana Pro image $0.134. The table compares one finished ad with four takes of every clip and one round of images, before any re-rolls, leaving out the flat useapi.net subscription:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ad (4 takes per clip)&lt;/th&gt;
&lt;th&gt;Official Gemini API&lt;/th&gt;
&lt;th&gt;useapi.net, Flow Pro&lt;/th&gt;
&lt;th&gt;useapi.net, Flow Ultra&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Default: intro 6 s, one product 10 s, closing 6 s&lt;/td&gt;
&lt;td&gt;$11.06&lt;/td&gt;
&lt;td&gt;$2.80&lt;/td&gt;
&lt;td&gt;$1.40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parody above: intro 6 s, three products 10 s each&lt;/td&gt;
&lt;td&gt;$17.81&lt;/td&gt;
&lt;td&gt;$4.40&lt;/td&gt;
&lt;td&gt;$2.20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Largest: intro 6 s, five products 10 s each, closing 6 s&lt;/td&gt;
&lt;td&gt;$29.43&lt;/td&gt;
&lt;td&gt;$7.60&lt;/td&gt;
&lt;td&gt;$3.80&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The official column is the video seconds at $0.10 plus the images at $0.134 each (16, 24 and 32 images). The useapi.net columns are the Flow credits at about $0.02 each on Pro and $0.01 on Ultra, with images free. That is about 4 times cheaper on Pro and 8 times cheaper on Ultra, and every re-roll of an image costs nothing instead of $0.134. The per-plan figures come from the &lt;a href="https://useapi.net/docs/api-google-flow-v1#pricing" rel="noopener noreferrer"&gt;Google Flow price comparison&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Re-rolling a clip costs its takes again, and a refused clip costs nothing. The full credit table is on &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos#model-capabilities" rel="noopener noreferrer"&gt;POST /videos&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to keep the face and voice consistent across clips
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;One character holds the face and the voice. It is made from two angles of the presenter plus the voice you picked, through &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-characters" rel="noopener noreferrer"&gt;POST /characters&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Every clip is filmed in reference mode with up to four inputs: the character, the scene you picked, the product handled in that clip (if any), and the voice. In the test ads the voice stayed within the range a single speaker covers from line to line, across every clip.&lt;/li&gt;
&lt;li&gt;Each clip's action ends with the presenter putting the product back where it was, so the table looks the same at every cut.&lt;/li&gt;
&lt;li&gt;Takes absorb the rest. Reference mode lets the model reinterpret the scene a little, so framing can shift slightly between clips and the occasional take is off. Several takes per clip give you a choice, and picking costs nothing extra.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When something goes wrong
&lt;/h3&gt;

&lt;p&gt;Every API call's result is sorted into one of three kinds, and each kind is handled differently.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kind&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;th&gt;What the workflow does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Temporary&lt;/td&gt;
&lt;td&gt;captcha failures, &lt;code&gt;429&lt;/code&gt;, Google &lt;code&gt;503&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Retries automatically, up to five times 5 seconds apart, then shows the failure with a re-roll, or a stop page if the character can't be created. A clip that already went through is never submitted twice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Refused&lt;/td&gt;
&lt;td&gt;Google's content filters, such as &lt;code&gt;PUBLIC_ERROR_DANGER_FILTER&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Shows the reason and asks you to change the description or the action&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dead end&lt;/td&gt;
&lt;td&gt;a wrong token, an account that isn't connected, a plan that can't use the model&lt;/td&gt;
&lt;td&gt;Stops with a page that says what to fix&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The account, its plan and its Flow credits are checked right after the details page, and the credits again just before the clips, so a dead end stops the run before anything is spent.&lt;/p&gt;

&lt;p&gt;If upscaling a clip fails, that clip stays 720p and the last page offers to retry just the failed ones, which is free.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customize it
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Settings&lt;/strong&gt; node holds the defaults for the details page, the image model (&lt;code&gt;nano-banana-pro&lt;/code&gt;) and the number of captcha attempts per request. The clip prompt is in the &lt;strong&gt;Clip requests&lt;/strong&gt; node. Everything the workflow calls is a documented endpoint, so any step can be changed with the &lt;a href="https://useapi.net/docs/api-google-flow-v1" rel="noopener noreferrer"&gt;Google Flow API reference&lt;/a&gt; at hand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;Both were made with this workflow and are Omni 1.1 Flash output, re-encoded to a smaller size for hosting.&lt;/p&gt;

&lt;strong&gt;"My beauty secrets"&lt;/strong&gt;, a parody beauty ad&lt;br&gt;&lt;small&gt;made with this n8n template, 1080p, 32 seconds&lt;/small&gt;



&lt;strong&gt;Uploaded presenter photo and product photo&lt;/strong&gt;&lt;br&gt;&lt;small&gt;coffee, two products, 16:9, 15 s&lt;/small&gt;



&lt;h3&gt;
  
  
  Frequently asked questions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Do I need to write any code?&lt;/strong&gt; No. You import one JSON file, add one credential and open a form. The workflow can be read and changed in n8n like any other, but making an ad never needs it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use my own product photos?&lt;/strong&gt; Yes. Upload a PNG, JPEG or WebP of up to 20 MB on the details page. It is used as it is, or turned into a four-view sheet if the product gets turned around on camera.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use a real person as the presenter?&lt;/strong&gt; You can upload photos of a presenter, but Google screens identifiable people, so a real face may be refused when the clips are made. A generated presenter avoids that, and the saved character ID lets you reuse the same one in every ad on the same Google account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the voice stay the same in every clip?&lt;/strong&gt; Yes, when the character has a voice, which every character this workflow creates does. The voice you pick is saved in the character together with the face, and every clip is made from that character. Picking from four previews also means you hear the voice before any clip is made.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can it make square videos?&lt;/strong&gt; No. Omni 1.1 Flash makes vertical (9:16) and horizontal (16:9) video, and the form offers those two formats.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How many products can one ad show?&lt;/strong&gt; Up to five, each with its own clip, plus the optional intro and closing, so seven clips at most.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it work on n8n Cloud?&lt;/strong&gt; It uses only core n8n nodes, so it should, but it has only been tested on self-hosted n8n 2.41. The one requirement is that the browser can reach your n8n URL, because the last page plays the ad from the workflow's own download URL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How long does one ad take?&lt;/strong&gt; The free pages are quick, and every re-roll adds a little. The clips take 5 to 15 minutes, and the upscale and join a few more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does an ad cost?&lt;/strong&gt; The &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;useapi.net subscription&lt;/a&gt; is a flat $15 a month, and the clips spend the Flow credits of your Google AI plan, 7 to 15 per take depending on length. The default ad with four takes per clip is 140 credits. See the cost section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Visit our &lt;a href="https://discord.gg/w28uK3cnmF" rel="noopener noreferrer"&gt;Discord Server&lt;/a&gt; or &lt;a href="https://t.me/use_api" rel="noopener noreferrer"&gt;Telegram Channel&lt;/a&gt; for any support questions and concerns.&lt;/p&gt;

&lt;p&gt;Check our &lt;a href="https://github.com/useapi/google-flow-api" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; with code examples.&lt;/p&gt;

</description>
      <category>n8n</category>
      <category>omniflash</category>
      <category>ugc</category>
      <category>ai</category>
    </item>
    <item>
      <title>How to Automate NotebookLM with the Gemini Notebook API: Deep Research, Chat, Audio Overviews and a Lot More</title>
      <dc:creator>useapi.net</dc:creator>
      <pubDate>Wed, 30 Sep 2026 03:43:30 +0000</pubDate>
      <link>https://dev.to/useapi/how-to-automate-notebooklm-with-the-gemini-notebook-api-deep-research-chat-audio-overviews-and-a-5cmj</link>
      <guid>https://dev.to/useapi/how-to-automate-notebooklm-with-the-gemini-notebook-api-deep-research-chat-audio-overviews-and-a-5cmj</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1" rel="noopener noreferrer"&gt;useapi.net Gemini Notebook API&lt;/a&gt; is a REST API for Google's &lt;a href="https://notebook.google.com" rel="noopener noreferrer"&gt;Gemini Notebook&lt;/a&gt;, formerly NotebookLM, that you can call from any language that can send an HTTP request.&lt;/strong&gt; It drives your own Google account: notebooks, sources, grounded chat, notes, web research, sharing and every Studio artifact. It also runs unattended: jobs spread across your connected accounts by remaining usage and are tracked server-side, so nobody has to watch the usage limits or decide when the next batch can start (see the FAQ).&lt;/p&gt;

&lt;p&gt;Four sources and two research questions went in, and 30 minutes of API calls later the notebook held an Audio Overview, an 11-minute Video Overview, a slide deck, an infographic, a Deep Research report and every text artifact Studio makes. Everything below is real output, and every call that made it is further down the page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sources and prompts
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Web page&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://en.wikipedia.org/wiki/Apollo_11" rel="noopener noreferrer"&gt;Apollo 11 on Wikipedia&lt;/a&gt;, 27,095 words&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;YouTube video&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://www.youtube.com/watch?v=xUcYQ7slmRw" rel="noopener noreferrer"&gt;A New Look at the Apollo 11 Landing Site&lt;/a&gt;, NASA Goddard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pasted text&lt;/td&gt;
&lt;td&gt;One paragraph, "Why Apollo 11 almost did not land"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PDF upload&lt;/td&gt;
&lt;td&gt;The same Wikipedia article as a 3.8 MB PDF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chat question&lt;/td&gt;
&lt;td&gt;"What went wrong during the descent, and how did the crew handle it?", then "How much fuel was left when they landed?"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discover sources&lt;/td&gt;
&lt;td&gt;"Apollo 11 lunar module guidance computer alarms"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deep Research&lt;/td&gt;
&lt;td&gt;"Why did the Apollo 11 landing nearly abort?"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;strong&gt;Video Overview&lt;/strong&gt; — explainer, whiteboard style, 11 min 50 s&lt;br&gt;&lt;small&gt;the first 90 seconds, cut without re-encoding for our media host · [step 18](#18-a-video-overview-and-a-slide-deck)&lt;/small&gt;



&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1554374617634840656/gemini-notebook-tutorial-pro-slides-presenter-apollo11-slide1-0929.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1554374617634840656%2Fgemini-notebook-tutorial-pro-slides-presenter-apollo11-slide1-0929.png" alt="Slide 1 of the Apollo 11 Mission deck generated by the Gemini Notebook API" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;strong&gt;Slide deck&lt;/strong&gt; — presenter format, 8 slides, &lt;code&gt;pdf&lt;/code&gt; + &lt;code&gt;pptx&lt;/code&gt;&lt;br&gt;&lt;small&gt;[the whole deck as PDF](https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1554374611972530217/gemini-notebook-tutorial-pro-slides-presenter-apollo11-deck-0929.pdf) · [step 18](#18-a-video-overview-and-a-slide-deck)&lt;/small&gt;



&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1554374623431368745/gemini-notebook-tutorial-pro-slides-presenter-apollo11-slide2-0929.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1554374623431368745%2Fgemini-notebook-tutorial-pro-slides-presenter-apollo11-slide2-0929.png" alt="Slide 2 before the revision" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;strong&gt;Slide 2&lt;/strong&gt; as generated



&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1554374629219635290/gemini-notebook-tutorial-pro-slides-presenter-apollo11-slide2-revised-timeline-0929.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1554374629219635290%2Fgemini-notebook-tutorial-pro-slides-presenter-apollo11-slide2-revised-timeline-0929.png" alt="Slide 2 after the revision, redrawn as a timeline" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;strong&gt;Slide 2 revised&lt;/strong&gt; — "Make this slide a simple timeline graphic."&lt;br&gt;&lt;small&gt;51 seconds · [step 19](#19-revise-one-slide)&lt;/small&gt;



&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1554358433288032348/gemini-notebook-tutorial-pro-infographic-sketch-note-apollo11-0929.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1554358433288032348%2Fgemini-notebook-tutorial-pro-infographic-sketch-note-apollo11-0929.png" alt="Apollo 11 Mission Infographic Overview generated by the Gemini Notebook API" width="800" height="1433"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;strong&gt;Infographic&lt;/strong&gt; — portrait, sketch note, 1536 × 2752&lt;br&gt;&lt;small&gt;1 min 45 s · [step 11](#11-an-audio-overview-and-an-infographic)&lt;/small&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/gemini-notebook-bash#results" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;
&lt;strong&gt;Audio Overview&lt;/strong&gt; — brief, short, 1 min 31 s&lt;br&gt;&lt;small&gt;"Fifty Seconds of Fuel and Lunar Isolation" · 4 min 36 s to generate · [step 11](#11-an-audio-overview-and-an-infographic)&lt;/small&gt;



&lt;p&gt;And as text or JSON, ready to use in your own app:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;th&gt;What came back&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Chat answer&lt;/td&gt;
&lt;td&gt;4,237 characters with 21 numbered citations, and a follow-up in the same conversation&lt;/td&gt;
&lt;td&gt;35 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discover sources&lt;/td&gt;
&lt;td&gt;10 web pages with one-line descriptions, 3 imported&lt;/td&gt;
&lt;td&gt;16 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deep Research&lt;/td&gt;
&lt;td&gt;A 26,878-character cited report on 30 web sources, imported as a source&lt;/td&gt;
&lt;td&gt;3 min 40 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quiz&lt;/td&gt;
&lt;td&gt;6 questions with answer options, hints and rationales&lt;/td&gt;
&lt;td&gt;33 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flashcards&lt;/td&gt;
&lt;td&gt;20 cards&lt;/td&gt;
&lt;td&gt;18 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mind map&lt;/td&gt;
&lt;td&gt;A JSON tree of the whole topic&lt;/td&gt;
&lt;td&gt;92 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Briefing report&lt;/td&gt;
&lt;td&gt;27,282 characters of Markdown&lt;/td&gt;
&lt;td&gt;79 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data table&lt;/td&gt;
&lt;td&gt;12 rows of alarms and anomalies with their causes&lt;/td&gt;
&lt;td&gt;32 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Source guide&lt;/td&gt;
&lt;td&gt;Google's summary and key topics of the Wikipedia page&lt;/td&gt;
&lt;td&gt;1 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  What it cost
&lt;/h3&gt;

&lt;p&gt;useapi.net is an API, not a hosted Gemini Notebook. Every call runs on a Google account of your own, which you connect once through &lt;a href="https://useapi.net/docs/start-here/setup-gemini-notebook" rel="noopener noreferrer"&gt;Setup Gemini Notebook&lt;/a&gt;, and everything it makes lives in that account. Gemini Notebook itself is free on a free Google account, and paid Google AI plans raise its limits.&lt;/p&gt;

&lt;p&gt;You pay useapi.net a flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; for API access to every supported service, and nothing per generation. Each subscription lets you connect 3 Google accounts, up to 100 in total. With more than one connected, the API load-balances across them: omit &lt;code&gt;email&lt;/code&gt; and a new notebook goes to the least busy account, and a one-shot &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-artifacts#one-shot-requests" rel="noopener noreferrer"&gt;POST /artifacts&lt;/a&gt; runs on an account with a free job slot and enough usage left for the job. &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-jobs" rel="noopener noreferrer"&gt;GET /jobs&lt;/a&gt; shows the load on every account.&lt;/p&gt;

&lt;p&gt;Google meters it with a usage budget per account that refills every 5 hours, plus a weekly budget. Everything on this page used about 35% of a Google AI Pro account's 5-hour budget, across two windows (10% for the first script, 25% for the second, mostly the video and the slide deck), and 1.7% of its week. How many of each you can start with a full 5-hour budget, counting each job at Google's own estimate (so these are minimums):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Studio action&lt;/th&gt;
&lt;th&gt;Free&lt;/th&gt;
&lt;th&gt;Pro&lt;/th&gt;
&lt;th&gt;Ultra&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Audio Overview&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;181&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video Overview&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;183&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video Overview, short&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;229&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video Overview, cinematic&lt;/td&gt;
&lt;td&gt;not available&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Report&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;92&lt;/td&gt;
&lt;td&gt;1846&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Table&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;67&lt;/td&gt;
&lt;td&gt;1355&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quiz&lt;/td&gt;
&lt;td&gt;43&lt;/td&gt;
&lt;td&gt;175&lt;/td&gt;
&lt;td&gt;3478&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flashcards&lt;/td&gt;
&lt;td&gt;52&lt;/td&gt;
&lt;td&gt;212&lt;/td&gt;
&lt;td&gt;4285&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infographic&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;37&lt;/td&gt;
&lt;td&gt;745&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slide deck&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;146&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mind map&lt;/td&gt;
&lt;td&gt;66&lt;/td&gt;
&lt;td&gt;263&lt;/td&gt;
&lt;td&gt;5217&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chat question&lt;/td&gt;
&lt;td&gt;62&lt;/td&gt;
&lt;td&gt;243&lt;/td&gt;
&lt;td&gt;4897&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-accounts-email" rel="noopener noreferrer"&gt;GET /accounts/&lt;code&gt;email&lt;/code&gt;&lt;/a&gt; shows each account's live usage, reset times and every action's current estimate.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it was built
&lt;/h3&gt;

&lt;p&gt;Two scripts ran back to back: the first (steps 1 to 14) built and researched the notebook and generated the audio, infographic and quiz, the second (steps 15 to 19) made everything else on the same notebook. Both are at the end of the page. Each step shows its result, and its &lt;code&gt;curl&lt;/code&gt; request with the response it got is one click away.&lt;/p&gt;

&lt;p&gt;You need a useapi.net &lt;a href="https://useapi.net/docs/start-here/setup-useapi" rel="noopener noreferrer"&gt;API token&lt;/a&gt; and a Google account connected through &lt;a href="https://useapi.net/docs/start-here/setup-gemini-notebook" rel="noopener noreferrer"&gt;Setup Gemini Notebook&lt;/a&gt;. Every call is also in the &lt;a href="https://www.postman.com/useapinet/useapi-net/collection/29112081-40696e39-d128-417e-984b-fe1b97e7bb00" rel="noopener noreferrer"&gt;Postman collection&lt;/a&gt; if you'd rather click than script. The steps use these variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;USEAPI_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"user:12345-..."&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;EMAIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"user@example.com"&lt;/span&gt;
&lt;span class="nv"&gt;API&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://api.useapi.net/v1/gemini-notebook
enc&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; jq &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; v &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'$v|@uri'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ids the API returns name the account they belong to and contain &lt;code&gt;:&lt;/code&gt; and &lt;code&gt;@&lt;/code&gt;, so they are URL-encoded (&lt;code&gt;enc&lt;/code&gt;) whenever they go into a URL path. Studio generation and research run as jobs: the default &lt;code&gt;mode: sync&lt;/code&gt; waits up to 90 seconds and returns the finished result, or &lt;code&gt;202&lt;/code&gt; with the running job, and &lt;code&gt;mode: async&lt;/code&gt; returns &lt;code&gt;201&lt;/code&gt; with a &lt;code&gt;jobid&lt;/code&gt; at once. Poll &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-jobs-jobid" rel="noopener noreferrer"&gt;GET /jobs/&lt;code&gt;jobid&lt;/code&gt;&lt;/a&gt; or pass &lt;code&gt;replyUrl&lt;/code&gt; for a webhook.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Create a notebook
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-notebooks" rel="noopener noreferrer"&gt;POST /notebooks&lt;/a&gt; on the connected account. Omit &lt;code&gt;email&lt;/code&gt; and the API picks the least busy of your accounts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/notebooks"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; email &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$EMAIL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{email: $email, title: "Apollo 11"}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee &lt;/span&gt;notebook.json
&lt;span class="nv"&gt;NOTEBOOK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .notebook notebook.json&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returned, in full (&lt;a href="https://useapi.net/assets/articles/gemini-notebook-bash/step-01-notebook.json" rel="noopener noreferrer"&gt;step-01-notebook.json&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"notebook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-user@example.com-notebook:62600bab-4082-4ee6-8fc3-955cee0c69cf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Apollo 11"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  2. Add a web page, a YouTube video and pasted text
&lt;/h4&gt;

&lt;p&gt;One &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-sources" rel="noopener noreferrer"&gt;POST /sources&lt;/a&gt; call takes up to 50 &lt;code&gt;urls&lt;/code&gt; (YouTube links become video sources) plus pasted &lt;code&gt;text&lt;/code&gt;. A file in the account's Google Drive goes in the same call as &lt;code&gt;drive: [{fileId, mimeType, name}]&lt;/code&gt;, and &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-sources-sync" rel="noopener noreferrer"&gt;POST /sources/sync&lt;/a&gt; re-imports it after it changes.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Upload a file
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-sources-upload" rel="noopener noreferrer"&gt;POST /sources/upload&lt;/a&gt; takes the file as the raw request body, with its MIME type as &lt;code&gt;Content-Type&lt;/code&gt;: PDF, Word, PowerPoint, EPUB, Markdown, text, CSV, audio, video or an image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/sources/upload?notebook=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;enc &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NOTEBOOK&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;name=01-apollo11-wikipedia.pdf"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/pdf"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-binary&lt;/span&gt; @01-apollo11-wikipedia.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returned, in full (&lt;a href="https://useapi.net/assets/articles/gemini-notebook-bash/step-03-upload.json" rel="noopener noreferrer"&gt;step-03-upload.json&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"notebook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-user@example.com-notebook:62600bab-4082-4ee6-8fc3-955cee0c69cf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-user@example.com-source:62600bab-4082-4ee6-8fc3-955cee0c69cf:6e04a6ea-cd2d-44cb-8be5-66f48be21a0d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"01-apollo11-wikipedia.pdf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"preparing"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  4. Wait until every source is ready
&lt;/h4&gt;

&lt;p&gt;Google processes each source before it can be used. The 3.8 MB PDF took about 45 seconds, the others were ready at once.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. See what a source is about
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-sources-source" rel="noopener noreferrer"&gt;GET /sources/&lt;code&gt;source&lt;/code&gt;&lt;/a&gt; returns Google's summary and key topics of one source, and with &lt;code&gt;?content=true&lt;/code&gt; the full text Google indexed from it. For the Wikipedia page the topics were Apollo spaceflight, Lunar landing, Space Race, Mission personnel and Space exploration.&lt;/p&gt;

&lt;h4&gt;
  
  
  6. Ask a question
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-chat" rel="noopener noreferrer"&gt;POST /chat&lt;/a&gt; answers from the sources with numbered citations, each naming its source and quoting the passage. This answer took 35 seconds and carried 21 citations. Send the same &lt;code&gt;conversation&lt;/code&gt; with the next question to keep the context (step 15).&lt;/p&gt;

&lt;h4&gt;
  
  
  7. Keep the answer as a note
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-notes" rel="noopener noreferrer"&gt;POST /notes&lt;/a&gt; saves text in the notebook. Notes can be listed, edited and deleted, and step 16 turns this one into a source.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/notes"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; nb &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NOTEBOOK&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; a &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .answer chat.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{notebook: $nb, title: "What went wrong during the descent", content: $a}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee &lt;/span&gt;note.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returned, in full (&lt;a href="https://useapi.net/assets/articles/gemini-notebook-bash/step-07-note.json" rel="noopener noreferrer"&gt;step-07-note.json&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"notebook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-user@example.com-notebook:62600bab-4082-4ee6-8fc3-955cee0c69cf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"note"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-user@example.com-note:62600bab-4082-4ee6-8fc3-955cee0c69cf:3ae0d70e-29eb-4f70-804e-0fe6c936f35f"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"What went wrong during the descent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"During the lunar descent of Apollo 11's Lunar Module *Eagle*, a cascade of unexpected technical anomalies and environmental hazards threatened the landing, requiring rapid problem-solving from both the crew and Mission Control [1-6].&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;---&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;### **1. Overshooting the Planned Landing Target**&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;* **What went wrong:** As descent began, Neil Armstrong and Buzz Aldrin noticed they were passing lunar landmarks two to three seconds early, meaning *Eagle* was traveling too fast and would land miles downrange of their intended target [3, 7]. Flight controllers suspected this was caused by lunar gravitational anomalies (mascons), extra air pressure in the docking tunnel, or unmodeled forces during earlier maneuvers [3, 7].&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;* **How it was handled:** The crew monitored their position closely, maintained composure, and prepared to adapt to landing further west than planned [2, 3, 5, 7].&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;---&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;### **2. Computer Program Alarms (1201 and 1202)**&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;* **What went wrong:** Five minutes into the descent burn, at about 6,000 feet above the surface, the Lunar Module Guidance Computer (LGC) raised unexpected **1201 and 1202 program alarms** [1, 4, 6]. These indicated &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;executive overflows&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;—the computer was receiving more data than it could process in real-time and had to postpone lower-priority tasks [1, 4]. The root cause was later identified as a radar hardware mismatch that fed spurious data from the rendezvous radar into the computer while the landing radar was also active [8-10].&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;* **How it was handled:** &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  * **Mission Control:** Computer engineer **Jack Garman** recognized that the alarms were safe as long as they remained intermittent [1, 4]. Guidance Officer **Steve Bales** agreed, and CAPCOM **Charles Duke** relayed the &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;GO&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; call to the crew [1, 4].&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  * **Onboard Software:** Software engineered under **Margaret Hamilton** at MIT was designed to drop lower-priority tasks and prioritize critical guidance calculations, preventing a system crash or an automatic abort [11, 12].&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;---&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;### **3. Hazardous Landing Terrain (West Crater)**&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;* **What went wrong:** When Armstrong looked out his window, he saw that the automated guidance system was targeting a boulder-strewn area surrounding a 300-foot-wide crater (West crater) [2, 5, 6]. Touching down there would have risked flipping or damaging the lander [2, 5].&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;* **How it was handled:** Armstrong took **semi-automatic manual control** of *Eagle* to fly past the boulder field and find clear ground [2, 5, 6, 13, 14]. While Armstrong focused entirely on flying the spacecraft, **Buzz Aldrin called out altitude and navigation data** continuously to keep him informed [2, 5].&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;---&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;### **4. Dwindling Fuel and Blinding Lunar Dust**&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;* **What went wrong:** Extending the flight to find a clear landing site consumed critical propellant [13, 14]. At 100 feet above the surface, the lander had only about **90 seconds of fuel remaining** [13, 14]. Additionally, the engine exhaust kicked up a blinding cloud of fine lunar dust that obscured the surface, making it difficult to judge motion and speed [14, 15].&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;* **How it was handled:** Armstrong picked out large rocks projecting above the dust cloud to visually gauge *Eagle*'s horizontal speed [14, 15]. He cleared a smaller crater and brought the lander down smoothly with roughly **25 to 50 seconds of fuel remaining** before a forced abort would have become necessary [13, 14, 16, 17].&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;---&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;### **5. Engine Shutdown and Touchdown**&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;* **What went wrong:** When a 67-inch probe hanging from *Eagle*'s footpads touched the Moon, Aldrin called &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Contact light!&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; [10, 15, 18]. Engine shutdown was supposed to occur immediately to avoid gas pressure build-up under the craft, but in the intensity of the moment, Armstrong delayed shutting down the engine for about three seconds [15, 18].&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;* **How it was handled:** *Eagle* settled safely on the Moon without damage [15, 18]. The crew immediately ran through post-landing checklists to secure the engine, after which Armstrong announced: *&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Houston, Tranquility Base here. The Eagle has landed&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;* [10, 15, 19-21].&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;💡 Would you like to explore what happened during the moonwalk itself, or look into the close calls the crew faced during their liftoff and ascent from the lunar surface?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"note"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"created"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-29T04:57:19.000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"updated"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-29T04:57:19.000Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  8. Find more sources on the web
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-research" rel="noopener noreferrer"&gt;POST /research&lt;/a&gt; with &lt;code&gt;type: "fast"&lt;/code&gt; is Gemini Notebook's Discover sources. It returned 10 web pages in 16 seconds. Nothing enters the notebook until &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-research-import" rel="noopener noreferrer"&gt;POST /research/import&lt;/a&gt;, and three were picked. Two came back: Google could not fetch the third page (a Stack Exchange question), so it is left out of the answer and listed in the notebook with status &lt;code&gt;error&lt;/code&gt;. An import waits until Google has fetched every page, about a minute and a half here. If Google takes longer, the API answers &lt;code&gt;504&lt;/code&gt; after about two minutes and the import usually still completes, so check the notebook before you retry. Never retry blindly, since that adds every source twice.&lt;/p&gt;

&lt;h4&gt;
  
  
  9. Start a Deep Research run
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;type: "deep"&lt;/code&gt; runs Deep Research: Google reads dozens of web pages and writes a cited report. It takes minutes, so it starts async here and is collected in step 12, after the Studio jobs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/research"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; nb &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NOTEBOOK&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{notebook: $nb, type: "deep", query: "Why did the Apollo 11 landing nearly abort?", mode: "async"}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee &lt;/span&gt;deep.json
&lt;span class="nv"&gt;DEEP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .jobid deep.json&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returned, in full (&lt;a href="https://useapi.net/assets/articles/gemini-notebook-bash/step-09-deep-research-submit.json" rel="noopener noreferrer"&gt;step-09-deep-research-submit.json&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jobid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"job:e2af6631-3d2b-4630-87b1-e115620e0c4e-user:12345-user@example.com-bot:gemini_notebook"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"research"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"processing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"notebook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-user@example.com-notebook:62600bab-4082-4ee6-8fc3-955cee0c69cf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-29T04:59:08.701Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"notebook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-user@example.com-notebook:62600bab-4082-4ee6-8fc3-955cee0c69cf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deep"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Why did the Apollo 11 landing nearly abort?"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  10. A quiz
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-artifacts" rel="noopener noreferrer"&gt;POST /artifacts&lt;/a&gt; with &lt;code&gt;type: "quiz"&lt;/code&gt;. It finished in 33 seconds, within the 90-second sync wait, so the call returned the finished quiz: 6 questions in &lt;code&gt;result.content.quiz&lt;/code&gt;, each with answer options, a hint and a rationale per option. Quizzes, flashcards and mind maps are JSON, ready to render in your own app.&lt;/p&gt;

&lt;h4&gt;
  
  
  11. An Audio Overview and an infographic
&lt;/h4&gt;

&lt;p&gt;Audio and video take minutes, so both went in async and were polled. The infographic finished in 1 minute 45 seconds, the Audio Overview in 4 minutes 36 seconds. Each finished job lists its files, and every file link goes through &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-artifacts-download" rel="noopener noreferrer"&gt;GET /artifacts/download&lt;/a&gt; with your token (&lt;code&gt;m4a&lt;/code&gt;, &lt;code&gt;mp4&lt;/code&gt;, &lt;code&gt;pdf&lt;/code&gt;, &lt;code&gt;pptx&lt;/code&gt;, &lt;code&gt;png&lt;/code&gt;). Both are shown in Results.&lt;/p&gt;

&lt;h4&gt;
  
  
  12. Collect the Deep Research report
&lt;/h4&gt;

&lt;p&gt;The Deep Research run from step 9 finished in 3 minutes 40 seconds, while the Studio jobs ran: "Anatomy of a Lunar Descent: Systems Architecture, Hardware Anomaly, and Human Decision-Making in the Apollo 11 Landing Near-Abort", 26,878 characters of Markdown with &lt;code&gt;[cite: n]&lt;/code&gt; markers, on 30 sources, 24 of them cited. Imported as a source (3,146 words), it grounds every later answer and artifact. &lt;code&gt;urls: []&lt;/code&gt; with &lt;code&gt;report: true&lt;/code&gt; imports the report alone, and leaving &lt;code&gt;urls&lt;/code&gt; out imports it with every cited source, as the app's Import button does.&lt;/p&gt;

&lt;h4&gt;
  
  
  13. Share the notebook
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-sharing" rel="noopener noreferrer"&gt;POST /sharing&lt;/a&gt; with a public link lets anyone with it view the notebook, and &lt;code&gt;allowCopies: false&lt;/code&gt; stops them duplicating it. &lt;code&gt;people: [{email, role}]&lt;/code&gt; invites someone as &lt;code&gt;viewer&lt;/code&gt; or &lt;code&gt;editor&lt;/code&gt; (Google emails them), &lt;code&gt;role: "remove"&lt;/code&gt; takes the access away, and &lt;code&gt;link: "restricted"&lt;/code&gt; makes the notebook private again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/sharing"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; nb &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NOTEBOOK&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{notebook: $nb, link: "public", allowCopies: false}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returned, in full (&lt;a href="https://useapi.net/assets/articles/gemini-notebook-bash/step-13-sharing.json" rel="noopener noreferrer"&gt;step-13-sharing.json&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"notebook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-user@example.com-notebook:62600bab-4082-4ee6-8fc3-955cee0c69cf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"people"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"owner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"link"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allowCopies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  14. What the first script used
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-accounts-email" rel="noopener noreferrer"&gt;GET /accounts/&lt;code&gt;email&lt;/code&gt;&lt;/a&gt; reads the account's usage. Steps 1 to 13 took the 5-hour window from 9.6% to 19.5% and its week from 7.0% to 7.5%, in 9 minutes 20 seconds end to end.&lt;/p&gt;

&lt;h4&gt;
  
  
  15. Ask a follow-up question
&lt;/h4&gt;

&lt;p&gt;The second script starts here, on the same notebook. The &lt;code&gt;conversation&lt;/code&gt; from step 6 makes the answer build on the earlier turns: &lt;em&gt;"When the Lunar Module Eagle touched down, it had 216 pounds (98 kg) of usable fuel remaining"&lt;/em&gt;, with 5 citations.&lt;/p&gt;

&lt;h4&gt;
  
  
  16. Turn the note into a source
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-notes-source" rel="noopener noreferrer"&gt;POST /notes/source&lt;/a&gt; turns the note from step 7 into a Markdown source that later answers can cite.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/notes/source"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; n &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; .note note.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{note: $n}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returned, in full (&lt;a href="https://useapi.net/assets/articles/gemini-notebook-bash/step-16-note-to-source.json" rel="noopener noreferrer"&gt;step-16-note-to-source.json&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"notebook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-user@example.com-notebook:62600bab-4082-4ee6-8fc3-955cee0c69cf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-user@example.com-source:62600bab-4082-4ee6-8fc3-955cee0c69cf:f9aa14ef-446a-445a-8d94-b45b1b9a5045"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"What went wrong during the descent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"markdown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ready"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"words"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;656&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"created"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-29T05:49:29.000Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  17. Flashcards, a mind map, a report and a data table
&lt;/h4&gt;

&lt;p&gt;Four sync calls, one after another: the flashcards in 18 seconds, the data table in 32, the report in 79 and the mind map in 92. The mind map outlived the 90-second sync wait, so it answered &lt;code&gt;202&lt;/code&gt; and was polled to the end. Flashcards come back as &lt;code&gt;result.content.flashcards&lt;/code&gt; (20 cards of front &lt;code&gt;f&lt;/code&gt; and back &lt;code&gt;b&lt;/code&gt;), the mind map as a JSON tree in &lt;code&gt;result.content&lt;/code&gt;, the briefing report as 27,282 characters of Markdown in &lt;code&gt;result.text&lt;/code&gt;, and the data table as &lt;code&gt;result.table&lt;/code&gt;, the header row first. The table's first rows, with the cells shortened and the Source column left out here:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Alarm or event&lt;/th&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;What the crew or Mission Control did&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Five minutes into the descent burn / MET 102:38:00–102:38:22 / PDI + 316 seconds&lt;/td&gt;
&lt;td&gt;1202 program alarm&lt;/td&gt;
&lt;td&gt;Computer overload (Executive overflow: no core sets available). High-frequency counter increment requests …&lt;/td&gt;
&lt;td&gt;Buzz Aldrin checked the alarm code using Verb 90 Noun 50 (and Verb 05 Noun 09 at PDI + 322 seconds). Computer …&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MET 102:36:55&lt;/td&gt;
&lt;td&gt;Slow spacecraft rotation rate during pitch-over/spin maneuver&lt;/td&gt;
&lt;td&gt;Autopilot rate switch was set at 5 deg/sec.&lt;/td&gt;
&lt;td&gt;Neil Armstrong switched the autopilot rate switch from 5 deg/sec to 25 deg/sec.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;As descent began / Not in source&lt;/td&gt;
&lt;td&gt;Overshooting the Planned Landing Target / Downrange Position Offset (Trajectory shifted 3,000 ft downrange …&lt;/td&gt;
&lt;td&gt;Residual pressure in the docking tunnel during separation, lunar gravitational anomalies (mascons), and …&lt;/td&gt;
&lt;td&gt;The crew monitored their position closely, maintained composure, and prepared to adapt to landing further …&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  18. A Video Overview and a slide deck
&lt;/h4&gt;

&lt;p&gt;Both async. The slide deck finished in 5 minutes 10 seconds: 8 slides, with &lt;code&gt;pdf&lt;/code&gt; and &lt;code&gt;pptx&lt;/code&gt; files and one image per slide in &lt;code&gt;result.slides&lt;/code&gt;. The Video Overview took 14 minutes and runs 11 minutes 50 seconds, a 720p &lt;code&gt;mp4&lt;/code&gt; of 59 MB. Both are shown in Results.&lt;/p&gt;

&lt;h4&gt;
  
  
  19. Revise one slide
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-artifacts-revise" rel="noopener noreferrer"&gt;POST /artifacts/revise&lt;/a&gt; redrew slide 2 from a prompt in 51 seconds. The revision is a new artifact with its own &lt;code&gt;artifact&lt;/code&gt; id, its job's result is the whole deck again with the new slide 2, and the original deck stays in the notebook. Before and after are shown in Results.&lt;/p&gt;

&lt;p&gt;The second script used about 25% of the 5-hour window and 1.2% of the week. The Video Overview and the slide deck are the expensive ones, at Google's estimate of about 11% and 14% each.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shortcuts
&lt;/h3&gt;

&lt;p&gt;For a single artifact you do not need to manage a notebook. Send the sources straight to &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-artifacts#one-shot-requests" rel="noopener noreferrer"&gt;POST /artifacts&lt;/a&gt;: the API creates a notebook on one of your accounts with a free job slot whose usage window allows the job, waits for the sources, generates, and can delete the notebook afterwards for text-only types. If it answers &lt;code&gt;202&lt;/code&gt; (the job outlived the 90-second wait), poll its &lt;code&gt;jobid&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/artifacts"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"type": "quiz", "urls": ["https://en.wikipedia.org/wiki/Apollo_11"], "deleteNotebook": true}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | jq &lt;span class="s1"&gt;'{status, questions: (.result.content.quiz | length)}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be told when a job finishes instead of polling, pass &lt;code&gt;replyUrl&lt;/code&gt; (and optionally &lt;code&gt;replyRef&lt;/code&gt;) with &lt;code&gt;mode: async&lt;/code&gt;, on Studio jobs and research alike. The API sends one POST with the same job record &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-jobs-jobid" rel="noopener noreferrer"&gt;GET /jobs/&lt;code&gt;jobid&lt;/code&gt;&lt;/a&gt; returns. &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/delete-gemini-notebook-jobs-jobid" rel="noopener noreferrer"&gt;DELETE /jobs/&lt;code&gt;jobid&lt;/code&gt;&lt;/a&gt; stops a research run you no longer need.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API&lt;/span&gt;&lt;span class="s2"&gt;/research"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; nb &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NOTEBOOK&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{notebook: $nb, type: "deep", query: "How did the Apollo guidance computer recover from overloads?", mode: "async", replyUrl: "https://example.com/hooks/notebook", replyRef: "order-42"}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  More of the API
&lt;/h3&gt;

&lt;p&gt;The rest of the API, on an Apollo 11 notebook like the one above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-notebooks-guide" rel="noopener noreferrer"&gt;GET /notebooks/guide&lt;/a&gt; returned Google's summary of the whole notebook, three suggested reports such as "Explain the technical challenges faced during the Eagle's lunar descent.", and three suggested chat questions.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-chat-settings" rel="noopener noreferrer"&gt;POST /chat/settings&lt;/a&gt; with the persona "You are a NASA flight controller. Answer in two sentences." made the next answers short and in that voice. &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-chat" rel="noopener noreferrer"&gt;GET /chat&lt;/a&gt; then returned the conversation's four turns, oldest first, and &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/delete-gemini-notebook-chat" rel="noopener noreferrer"&gt;DELETE /chat&lt;/a&gt; cleared it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-notes" rel="noopener noreferrer"&gt;POST /notes&lt;/a&gt; with &lt;code&gt;conversation&lt;/code&gt; saved that whole conversation as one note, "Chat History", question and answer by turn.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-notes-mindmap" rel="noopener noreferrer"&gt;POST /notes/mindmap&lt;/a&gt; made a mind map note, "Apollo 11 Mission", with six branches from "Background &amp;amp; Goals" to "Legacy &amp;amp; Artifacts".&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-labels" rel="noopener noreferrer"&gt;POST /labels&lt;/a&gt; with &lt;code&gt;auto: "all"&lt;/code&gt; grouped both sources under a "Space Exploration" label. Labels of your own take a name and an emoji, and &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-labels-label" rel="noopener noreferrer"&gt;POST /labels/&lt;code&gt;label&lt;/code&gt;&lt;/a&gt; renames them and moves sources in and out.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-notebooks-copy" rel="noopener noreferrer"&gt;POST /notebooks/copy&lt;/a&gt; copied the notebook with its two sources and two Studio artifacts.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-accounts" rel="noopener noreferrer"&gt;POST /accounts&lt;/a&gt; with &lt;code&gt;outputLanguage: "es"&lt;/code&gt; switched the account's Studio output to Spanish, and back.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-research" rel="noopener noreferrer"&gt;POST /research&lt;/a&gt; with &lt;code&gt;source: "drive"&lt;/code&gt; searches the account's Google Drive instead of the web. It found a Word &lt;code&gt;.docx&lt;/code&gt; and a Google Doc about Apollo 11, and &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-research-import" rel="noopener noreferrer"&gt;POST /research/import&lt;/a&gt; added them as Drive sources. After the Doc was edited in Drive, &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-sources-source" rel="noopener noreferrer"&gt;GET /sources/&lt;code&gt;source&lt;/code&gt;&lt;/a&gt; reported it &lt;code&gt;inSync: false&lt;/code&gt;, and a few seconds later the notebook held the new text. &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-sources-sync" rel="noopener noreferrer"&gt;POST /sources/sync&lt;/a&gt; re-imports a changed Drive file on request.&lt;/li&gt;
&lt;li&gt;A preset report takes extra &lt;code&gt;instructions&lt;/code&gt;: a briefing "for a high-school class, in under 300 words" came back as 1,946 characters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What the NotebookLM API can do
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Create a notebook&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-notebooks" rel="noopener noreferrer"&gt;POST /notebooks&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Creates an empty notebook on one of your connected accounts.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Add sources&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-sources" rel="noopener noreferrer"&gt;POST /sources&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Web pages and YouTube videos (&lt;code&gt;urls&lt;/code&gt;, up to 50 per call), pasted &lt;code&gt;text&lt;/code&gt; and Google Drive files (&lt;code&gt;drive&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Upload a file&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-sources-upload" rel="noopener noreferrer"&gt;POST /sources/upload&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;The file is the raw request body: PDF, Word, PowerPoint, EPUB, Markdown, text, CSV, audio, video or an image.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read a source&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-sources-source" rel="noopener noreferrer"&gt;GET /sources/&lt;code&gt;source&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Google's summary and key topics of one source, and with &lt;code&gt;content=true&lt;/code&gt; the text Google indexed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ask&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-chat" rel="noopener noreferrer"&gt;POST /chat&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;An answer from the sources with numbered citations. Pass &lt;code&gt;conversation&lt;/code&gt; for a follow-up.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keep notes&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-notes" rel="noopener noreferrer"&gt;POST /notes&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Notes in the notebook. A note can become a source.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Research&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-research" rel="noopener noreferrer"&gt;POST /research&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fast&lt;/code&gt; finds sources on the web in seconds, &lt;code&gt;deep&lt;/code&gt; runs Deep Research and writes a cited report.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Import research&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-research-import" rel="noopener noreferrer"&gt;POST /research/import&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Adds the sources a research run found, and its report, to the notebook.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generate&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-artifacts" rel="noopener noreferrer"&gt;POST /artifacts&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;audio&lt;/code&gt;, &lt;code&gt;video&lt;/code&gt;, &lt;code&gt;report&lt;/code&gt;, &lt;code&gt;interactive_report&lt;/code&gt;, &lt;code&gt;table&lt;/code&gt;, &lt;code&gt;quiz&lt;/code&gt;, &lt;code&gt;flashcards&lt;/code&gt;, &lt;code&gt;mindmap&lt;/code&gt;, &lt;code&gt;infographic&lt;/code&gt; or &lt;code&gt;slides&lt;/code&gt;, each with its own options.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Revise a slide&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-artifacts-revise" rel="noopener noreferrer"&gt;POST /artifacts/revise&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Redraws one slide of a finished deck from a prompt.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Follow a job&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-jobs-jobid" rel="noopener noreferrer"&gt;GET /jobs/&lt;code&gt;jobid&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;The status and, once finished, the result.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Download&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-artifacts-download" rel="noopener noreferrer"&gt;GET /artifacts/download&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;The artifact's file (&lt;code&gt;m4a&lt;/code&gt;, &lt;code&gt;mp4&lt;/code&gt;, &lt;code&gt;pdf&lt;/code&gt;, &lt;code&gt;pptx&lt;/code&gt;, &lt;code&gt;png&lt;/code&gt;), streamed with your API token.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Share&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-sharing" rel="noopener noreferrer"&gt;POST /sharing&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Invite people as viewers or editors, turn the public link on or off, and limit viewers to chat only.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Copy a notebook&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-notebooks-copy" rel="noopener noreferrer"&gt;POST /notebooks/copy&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;A copy with every source and Studio artifact, on the same account.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Notebook guide&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-notebooks-guide" rel="noopener noreferrer"&gt;GET /notebooks/guide&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Google's summary of the whole notebook, suggested reports and suggested chat questions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chat history and settings&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-chat" rel="noopener noreferrer"&gt;GET /chat&lt;/a&gt;, &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/delete-gemini-notebook-chat" rel="noopener noreferrer"&gt;DELETE /chat&lt;/a&gt;, &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-chat-settings" rel="noopener noreferrer"&gt;POST /chat/settings&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;A conversation's turns, delete the history, and set the chat's goal, persona and answer length.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Source labels&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-labels" rel="noopener noreferrer"&gt;POST /labels&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Google labels the sources by topic, or you make and edit your own labels.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mind map note&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-notes-mindmap" rel="noopener noreferrer"&gt;POST /notes/mindmap&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;A mind map made in one call and kept as a note.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output language&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-accounts" rel="noopener noreferrer"&gt;POST /accounts&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;The language Google writes Studio artifacts in, for the whole account.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-artifacts#options-by-type" rel="noopener noreferrer"&gt;POST /artifacts&lt;/a&gt; page lists every Studio type's options.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run both scripts yourself
&lt;/h3&gt;

&lt;p&gt;Both scripts save every response under a timestamped folder. The first builds the notebook, the second takes the notebook, conversation and note ids the first one printed.&lt;/p&gt;

&lt;p&gt;Both scripts are also in the &lt;a href="https://github.com/useapi/gemini-notebook-api" rel="noopener noreferrer"&gt;gemini-notebook-api GitHub repo&lt;/a&gt;, with Node.js and Python examples that turn URLs into an Audio Overview podcast and save a Deep Research report as Markdown.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frequently asked questions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Is Gemini Notebook the same as NotebookLM?&lt;/strong&gt; Yes. Gemini Notebook is Google's current name for NotebookLM, and the &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1" rel="noopener noreferrer"&gt;useapi.net Gemini Notebook API&lt;/a&gt; works as a NotebookLM API: notebooks, sources, chat, Deep Research and every Studio artifact over REST.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I generate a NotebookLM Audio Overview (podcast) through an API?&lt;/strong&gt; Yes. &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-artifacts" rel="noopener noreferrer"&gt;POST /artifacts&lt;/a&gt; with &lt;code&gt;type: "audio"&lt;/code&gt; generates an Audio Overview (&lt;code&gt;deep_dive&lt;/code&gt;, &lt;code&gt;brief&lt;/code&gt;, &lt;code&gt;critique&lt;/code&gt; or &lt;code&gt;debate&lt;/code&gt;) and returns an &lt;code&gt;m4a&lt;/code&gt; file. The short brief in this walkthrough took about 4 and a half minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does the API reach my Gemini Notebook?&lt;/strong&gt; The &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1" rel="noopener noreferrer"&gt;useapi.net Gemini Notebook API&lt;/a&gt; drives your own Google account over REST, with a single useapi.net API token. You connect the account once through &lt;a href="https://useapi.net/docs/start-here/setup-gemini-notebook" rel="noopener noreferrer"&gt;Setup Gemini Notebook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it work on a free Google account?&lt;/strong&gt; Yes. Every call on this page also runs on a free account, Deep Research included. Paid Google AI plans raise the usage budget and unlock Cinematic video: Google AI Pro gives an account about four times Free's budget, and Google AI Ultra about twenty times Pro's (see What it cost).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which source types can I add?&lt;/strong&gt; Web pages and YouTube videos by URL, pasted text, files in the account's Google Drive (Google Docs included), and uploaded PDF, Word, PowerPoint, EPUB, Markdown, text, CSV, audio, video and image files. See &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-sources" rel="noopener noreferrer"&gt;POST /sources&lt;/a&gt; and &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-sources-upload" rel="noopener noreferrer"&gt;POST /sources/upload&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why did my YouTube video end with status error?&lt;/strong&gt; Google reads a YouTube video from its captions. A video with no captions at all, as with some official music videos, fails without a reason. Upload the audio or video file with &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-sources-upload" rel="noopener noreferrer"&gt;POST /sources/upload&lt;/a&gt; instead, and Google transcribes it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the difference between fast and deep research?&lt;/strong&gt; &lt;code&gt;fast&lt;/code&gt; (Discover sources) returns about ten relevant web pages with one-line descriptions in seconds. &lt;code&gt;deep&lt;/code&gt; (Deep Research) reads dozens of pages for a few minutes and writes a cited report. Its result lists the pages it found and marks the ones the report cites. Both only suggest: nothing enters the notebook until &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-research-import" rel="noopener noreferrer"&gt;POST /research/import&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How long does a generation take?&lt;/strong&gt; Flashcards, a quiz and a data table take well under a minute, a mind map, a report or an infographic one to two minutes, an Audio Overview three to five minutes, a slide deck about five to seven, and Video Overviews ten minutes or more. See &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/post-gemini-notebook-artifacts#what-you-get-back" rel="noopener noreferrer"&gt;POST /artifacts&lt;/a&gt; for each type.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I have to watch the jobs and usage limits myself?&lt;/strong&gt; No. Connect several Google accounts and the API spreads the work: each new job goes to an account that is healthy, has a free job slot and still has usage left for that type. Jobs are tracked on our side, so you poll &lt;a href="https://useapi.net/docs/api-gemini-notebook-v1/get-gemini-notebook-jobs-jobid" rel="noopener noreferrer"&gt;GET /jobs/&lt;code&gt;jobid&lt;/code&gt;&lt;/a&gt; or pass &lt;code&gt;replyUrl&lt;/code&gt; and get the finished job posted to your webhook. When every account is out of usage, the &lt;code&gt;429&lt;/code&gt; carries &lt;code&gt;retryAt&lt;/code&gt; whenever Google names the reset time, so your code decides how to handle the load: wait until then, route the next batch to another account, or slow down. No one has to check in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens when an account runs out of its usage window?&lt;/strong&gt; Google refuses the generation. The call answers &lt;code&gt;429&lt;/code&gt;, or the job fails with &lt;code&gt;error.code: "quota"&lt;/code&gt; when it started async, with the reset time when Google names it. Connect more accounts: one-shot requests skip accounts whose last-known usage blocks the job, and new notebooks go to the least busy account.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Visit our &lt;a href="https://discord.gg/w28uK3cnmF" rel="noopener noreferrer"&gt;Discord Server&lt;/a&gt; or &lt;a href="https://t.me/use_api" rel="noopener noreferrer"&gt;Telegram Channel&lt;/a&gt; for any support questions and concerns.&lt;/p&gt;

&lt;p&gt;Check our &lt;a href="https://github.com/useapi/gemini-notebook-api" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; with code examples.&lt;/p&gt;

</description>
      <category>notebooklm</category>
      <category>gemini</category>
      <category>ai</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Generate Nano Banana 2 &amp; Nano Banana Pro Images via the Google Flow API</title>
      <dc:creator>useapi.net</dc:creator>
      <pubDate>Sun, 27 Sep 2026 17:01:07 +0000</pubDate>
      <link>https://dev.to/useapi/how-to-generate-nano-banana-2-nano-banana-pro-images-via-the-google-flow-api-1cn2</link>
      <guid>https://dev.to/useapi/how-to-generate-nano-banana-2-nano-banana-pro-images-via-the-google-flow-api-1cn2</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;One synchronous &lt;code&gt;POST&lt;/code&gt; to the &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;useapi.net&lt;/a&gt; Google Flow API returns up to four &lt;a href="https://deepmind.google/models/gemini-image/flash/" rel="noopener noreferrer"&gt;Nano Banana 2&lt;/a&gt;, &lt;a href="https://deepmind.google/models/gemini-image/pro/" rel="noopener noreferrer"&gt;Nano Banana Pro&lt;/a&gt; or &lt;a href="https://deepmind.google/models/gemini-image/flash-lite/" rel="noopener noreferrer"&gt;Nano Banana 2 Lite&lt;/a&gt; images, generated on your own &lt;a href="https://flow.google.com" rel="noopener noreferrer"&gt;Google Flow&lt;/a&gt; account.&lt;/strong&gt; There's no Google Cloud project, no Gemini API key and no per-image metering. Image generation is included on any &lt;a href="https://one.google.com/ai" rel="noopener noreferrer"&gt;Google AI&lt;/a&gt; plan, even a free one, where the official Gemini API bills $0.034–$0.134 per image.&lt;/p&gt;

&lt;p&gt;This guide covers the models you get, the price difference, the single-call image workflow with copy-paste &lt;code&gt;curl&lt;/code&gt;, and a runnable Node.js script that batch-generates from a list of prompts. Want to see how the three models differ on one prompt? See the &lt;a href="https://useapi.net/docs/articles/google-flow-nano-banana-compare" rel="noopener noreferrer"&gt;Nano Banana model comparison&lt;/a&gt;. Need video instead? See the sibling &lt;a href="https://useapi.net/docs/articles/google-flow-bash" rel="noopener noreferrer"&gt;Veo 3.1 tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supported models
&lt;/h3&gt;

&lt;p&gt;Pick a model per request with the &lt;code&gt;model&lt;/code&gt; field (default &lt;code&gt;nano-banana-2-lite&lt;/code&gt;). All three models work on any Google AI subscription — including a free account.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model id&lt;/th&gt;
&lt;th&gt;Marketing name&lt;/th&gt;
&lt;th&gt;References (I2I)&lt;/th&gt;
&lt;th&gt;Aspect ratios&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;nano-banana-2-lite&lt;/code&gt; &lt;em&gt;(default)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;Nano Banana 2 Lite / Gemini 3.1 Flash-Lite Image&lt;/td&gt;
&lt;td&gt;max 10&lt;/td&gt;
&lt;td&gt;16:9, 4:3, 1:1, 3:4, 9:16, auto&lt;sup&gt;†&lt;/sup&gt;
&lt;/td&gt;
&lt;td&gt;Google Flow's default image model since July 2026 — stays at 16:9 in image-to-image mode unless you pass a ratio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nano-banana-2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nano Banana 2 / Gemini 3.1 Flash Image&lt;/td&gt;
&lt;td&gt;max 10&lt;/td&gt;
&lt;td&gt;16:9, 4:3, 1:1, 3:4, 9:16, auto&lt;sup&gt;†&lt;/sup&gt;
&lt;/td&gt;
&lt;td&gt;Defaults to &lt;code&gt;auto&lt;/code&gt; in image-to-image mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nano-banana-pro&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nano Banana Pro / Gemini 3 Pro Image&lt;/td&gt;
&lt;td&gt;max 10&lt;/td&gt;
&lt;td&gt;16:9, 4:3, 1:1, 3:4, 9:16, auto&lt;sup&gt;†&lt;/sup&gt;
&lt;/td&gt;
&lt;td&gt;Highest-quality image model — defaults to &lt;code&gt;auto&lt;/code&gt; in image-to-image mode&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;sup&gt;†&lt;/sup&gt; &lt;code&gt;auto&lt;/code&gt; is valid only in image-to-image mode (at least one &lt;code&gt;reference_*&lt;/code&gt; or &lt;code&gt;character_*&lt;/code&gt; supplied) — the backend derives the ratio from the first reference image. With several references the orientation is not guaranteed, so pass an explicit ratio when every image must come back in the same shape.&lt;/p&gt;

&lt;p&gt;All three accept &lt;code&gt;count&lt;/code&gt; (1–4) and &lt;code&gt;seed&lt;/code&gt; for reproducibility. If you omit &lt;code&gt;model&lt;/code&gt;, the API uses &lt;code&gt;nano-banana-2-lite&lt;/code&gt;, with or without references. Two deprecated aliases are still accepted: &lt;code&gt;nano-banana&lt;/code&gt; maps to &lt;code&gt;nano-banana-2&lt;/code&gt;, and &lt;code&gt;imagen-4&lt;/code&gt; maps to &lt;code&gt;nano-banana-2-lite&lt;/code&gt; (Google removed Imagen from Flow in July 2026). Details and per-model capabilities are in the &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-images" rel="noopener noreferrer"&gt;POST /images&lt;/a&gt; reference.&lt;/p&gt;

&lt;h4&gt;
  
  
  Upscaling to 2K/4K
&lt;/h4&gt;

&lt;p&gt;Images generated with any of the three models can be upscaled with &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-images-upscale" rel="noopener noreferrer"&gt;POST /images/upscale&lt;/a&gt;: pass the image's &lt;code&gt;mediaGenerationId&lt;/code&gt; and a &lt;code&gt;resolution&lt;/code&gt; of &lt;code&gt;2k&lt;/code&gt; (default) or &lt;code&gt;4k&lt;/code&gt;. The response is base64 in &lt;code&gt;encodedImage&lt;/code&gt;. &lt;code&gt;2k&lt;/code&gt; works on any plan. &lt;code&gt;4k&lt;/code&gt; needs a paid Google plan, and on a free account it fails with &lt;code&gt;403&lt;/code&gt; and a &lt;code&gt;captcha_quality: PUBLIC_ERROR_UNUSUAL_ACTIVITY&lt;/code&gt; error that looks like a captcha problem but is not one, so don't retry it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Image generation is included. You keep your normal &lt;a href="https://one.google.com/ai" rel="noopener noreferrer"&gt;Google AI&lt;/a&gt; account — even a free one works for images (a paid plan is only needed for video and &lt;code&gt;4k&lt;/code&gt; upscales) — plus a flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; to useapi.net for API access to every service. No per-image metering, no per-call surcharge.&lt;/p&gt;

&lt;p&gt;Third-party &lt;a href="https://useapi.net/docs/api-google-flow-v1" rel="noopener noreferrer"&gt;Google Flow API&lt;/a&gt; by &lt;a href="https://useapi.net/" rel="noopener noreferrer"&gt;useapi.net&lt;/a&gt; vs. the official &lt;a href="https://ai.google.dev/gemini-api/docs/pricing" rel="noopener noreferrer"&gt;Gemini API&lt;/a&gt; — drive your own Google Flow subscription instead of metered, per-call API billing:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Official Gemini API&lt;/th&gt;
&lt;th&gt;useapi.net (Flow Pro)&lt;/th&gt;
&lt;th&gt;useapi.net (Flow Ultra)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Veo 3.1 Fast — 8s clip&lt;/td&gt;
&lt;td&gt;$0.80&lt;/td&gt;
&lt;td&gt;~$0.40&lt;/td&gt;
&lt;td&gt;~$0.10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Veo 3.1 Quality — 8s clip&lt;/td&gt;
&lt;td&gt;$3.20&lt;/td&gt;
&lt;td&gt;~$2.00&lt;/td&gt;
&lt;td&gt;~$1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Veo 3.1 Lite — 8s clip&lt;/td&gt;
&lt;td&gt;$0.40&lt;/td&gt;
&lt;td&gt;~$0.20&lt;/td&gt;
&lt;td&gt;~$0.05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Veo 3.1 Lite, lower priority&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;$0 &lt;em&gt;(Ultra $199)&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Omni 1.1 Flash — 8s clip&lt;/td&gt;
&lt;td&gt;— &lt;em&gt;(Flow only)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;~$0.24&lt;/td&gt;
&lt;td&gt;~$0.12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Omni 1.1 Flash — 8s clip at 360p&lt;/td&gt;
&lt;td&gt;— &lt;em&gt;(Flow only)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;~$0.12&lt;/td&gt;
&lt;td&gt;~$0.06&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nano Banana Pro — per image&lt;/td&gt;
&lt;td&gt;$0.134&lt;/td&gt;
&lt;td&gt;included&lt;/td&gt;
&lt;td&gt;included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nano Banana 2 — per image&lt;/td&gt;
&lt;td&gt;$0.067&lt;/td&gt;
&lt;td&gt;included&lt;/td&gt;
&lt;td&gt;included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nano Banana 2 Lite — per image&lt;/td&gt;
&lt;td&gt;$0.034&lt;/td&gt;
&lt;td&gt;included&lt;/td&gt;
&lt;td&gt;included&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Expected daily output — Ultra ($199/mo) plan. Daily averages observed on top real accounts. These are expected, not guaranteed: Google governs the underlying Flow allowances and they vary with demand.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Free workload (no Flow credits spent)&lt;/th&gt;
&lt;th&gt;Avg generations / day*&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Veo 3.1 Lite — lower priority video&lt;/td&gt;
&lt;td&gt;~1,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Images — Nano Banana 2 Lite, Nano Banana 2, Nano Banana Pro&lt;/td&gt;
&lt;td&gt;up to ~500&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;small&gt;*Averages from the busiest real accounts — not guarantees. They are set by Google's own allowances and fluctuate with demand. Applies only to the free lower-priority video queue and image generation. Credit-metered models (Veo 3.1 Fast / Quality and Omni 1.1 Flash) are not shown here — their volume is bounded by your plan's monthly Flow credits (see the &lt;a href="https://useapi.net/docs/api-google-flow-v1" rel="noopener noreferrer"&gt;credit table&lt;/a&gt;), not a free allowance.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;&lt;small&gt;Veo is billed per second on the Gemini API (an 8-second 720p clip shown) and images are priced per image. Through useapi.net you spend your own Flow plan credits and pay a flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; — image generation is included on any Google AI plan, and there is no Google Cloud project, API key, or per-call metering.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Full plan and credit details are on the &lt;a href="https://useapi.net/docs/api-google-flow-v1" rel="noopener noreferrer"&gt;Google Flow overview&lt;/a&gt;. See the &lt;a href="https://useapi.net/docs/start-here/setup-google-flow" rel="noopener noreferrer"&gt;setup guide&lt;/a&gt; to connect your account.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to generate a Nano Banana image with curl
&lt;/h3&gt;

&lt;p&gt;You need a useapi.net &lt;a href="https://useapi.net/docs/start-here/setup-useapi" rel="noopener noreferrer"&gt;API token&lt;/a&gt; and a connected &lt;a href="https://useapi.net/docs/start-here/setup-google-flow" rel="noopener noreferrer"&gt;Google Flow account&lt;/a&gt;. Image generation is synchronous — one &lt;code&gt;POST&lt;/code&gt; blocks until the images are ready (typically 10–20 seconds) and returns them in the response, so there's no &lt;code&gt;jobid&lt;/code&gt; to poll. Step two is just saving the result, from the signed URL or, when that is missing, the inline base64 image.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Submit the prompt — &lt;code&gt;POST https://api.useapi.net/v1/google-flow/images&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.useapi.net/v1/google-flow/images"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "prompt": "Cat dressed like a pirate fencing with a real pirate, pirate looks absolutely terrified, this is happening on a deck of the Disney cruise ship",
    "model": "nano-banana-pro",
    "aspectRatio": "16:9",
    "count": 4,
    "seed": 123456
  }'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; response.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The call returns &lt;code&gt;200 OK&lt;/code&gt; with a &lt;code&gt;jobId&lt;/code&gt; and a &lt;code&gt;media&lt;/code&gt; array — one entry per image (&lt;code&gt;count&lt;/code&gt; is 1–4, default 4). Each image's signed download URL is at &lt;code&gt;media[].image.generatedImage.fifeUrl&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jobId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"j1731859345678i-u12345-email:jo***@gmail.com-bot:google-flow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"media"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"generatedImage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"seed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;123456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"mediaGenerationId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-email:6a6f...-image:..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cat dressed like a pirate fencing with a real pirate, pirate looks absolutely terrified, this is happening on a deck of the Disney cruise ship"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"fifeUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://flow-content.google/image/..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"aspectRatio"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"IMAGE_ASPECT_RATIO_LANDSCAPE"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Download the image from &lt;code&gt;fifeUrl&lt;/code&gt; (the signed URL is valid for a limited time, so download promptly). Once in a while &lt;code&gt;fifeUrl&lt;/code&gt; is absent and the image comes back inline as base64 in &lt;code&gt;encodedImage&lt;/code&gt; instead, so fall back to decoding that:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.media[0].image.generatedImage.fifeUrl // empty'&lt;/span&gt; response.json&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; image_1.jpg &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.media[0].image.generatedImage.encodedImage'&lt;/span&gt; response.json | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; image_1.jpg
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each generated image's &lt;code&gt;mediaGenerationId&lt;/code&gt; can be reused as a reference in a later request — see Image references &amp;amp; characters below.&lt;/p&gt;

&lt;p&gt;Want a webhook as well? Pass a &lt;code&gt;replyUrl&lt;/code&gt; in the request body and the API also posts job status updates to that URL. The call itself still waits for the images. The payload matches the &lt;a href="https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid" rel="noopener noreferrer"&gt;GET /jobs/&lt;code&gt;jobId&lt;/code&gt;&lt;/a&gt; response, where a completed image lives at &lt;code&gt;response.media[].image.generatedImage.fifeUrl&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Image references &amp;amp; characters
&lt;/h3&gt;

&lt;p&gt;To steer a generation with an existing picture, upload it first with &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-assets-email" rel="noopener noreferrer"&gt;POST /assets/&lt;code&gt;email&lt;/code&gt;&lt;/a&gt; (raw bytes, an image &lt;code&gt;Content-Type&lt;/code&gt;, PNG/JPEG/WebP up to 20 MB). The upload response nests the reference id at &lt;code&gt;mediaGenerationId.mediaGenerationId&lt;/code&gt; — that nested string is what you pass back as &lt;code&gt;reference_1&lt;/code&gt; (each of the three models accepts up to 10 references):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Upload a reference image&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.useapi.net/v1/google-flow/assets/john%40gmail.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: image/jpeg"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-binary&lt;/span&gt; @reference.jpeg

&lt;span class="c"&gt;# Response — the reference id is nested one level deep:&lt;/span&gt;
&lt;span class="c"&gt;# {&lt;/span&gt;
&lt;span class="c"&gt;#   "mediaGenerationId": {&lt;/span&gt;
&lt;span class="c"&gt;#     "mediaGenerationId": "user:12345-email:6a6f...-image:ff9aa5cc-..."&lt;/span&gt;
&lt;span class="c"&gt;#   },&lt;/span&gt;
&lt;span class="c"&gt;#   "width": 1024, "height": 1024, "email": "jo***@gmail.com"&lt;/span&gt;
&lt;span class="c"&gt;# }&lt;/span&gt;

&lt;span class="c"&gt;# 2. Generate using that reference&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.useapi.net/v1/google-flow/images"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "model": "nano-banana-pro",
    "prompt": "Make this photograph look modern",
    "reference_1": "user:12345-email:6a6f...-image:ff9aa5cc-..."
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For consistent identity across many images, bundle 1–2 reference images into a reusable character with &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-characters" rel="noopener noreferrer"&gt;POST /characters&lt;/a&gt;, then pass its &lt;code&gt;character&lt;/code&gt; id as &lt;code&gt;character_1&lt;/code&gt;…&lt;code&gt;character_7&lt;/code&gt;. Characters mix freely with &lt;code&gt;reference_*&lt;/code&gt; and share the same per-model image-ref budget. You can also drop &lt;code&gt;@reference_1&lt;/code&gt; / &lt;code&gt;@character_1&lt;/code&gt; markers inline in the &lt;code&gt;prompt&lt;/code&gt; for positional grounding — each inline marker must have a matching body param.&lt;/p&gt;

&lt;h3&gt;
  
  
  Batch-generate with a script
&lt;/h3&gt;

&lt;p&gt;Finding the right image takes many attempts, and running them by hand is tedious. The Node.js script reads a list of prompts from &lt;a href="https://github.com/useapi/google-flow-api/blob/main/images/prompts.json" rel="noopener noreferrer"&gt;&lt;code&gt;prompts.json&lt;/code&gt;&lt;/a&gt;, uploads any reference images, submits each request, and downloads every returned image — so you can queue a batch and come back to the winners. Because &lt;code&gt;POST /images&lt;/code&gt; is synchronous, the script writes each result as soon as the call returns.&lt;/p&gt;

&lt;p&gt;You need &lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; v21 or newer. Put &lt;code&gt;prompts.json&lt;/code&gt; and &lt;a href="https://github.com/useapi/google-flow-api/blob/main/images/google-flow-images.mjs" rel="noopener noreferrer"&gt;&lt;code&gt;google-flow-images.mjs&lt;/code&gt;&lt;/a&gt; in the same folder and run &lt;code&gt;node ./google-flow-images.mjs API_TOKEN EMAIL&lt;/code&gt;, where &lt;code&gt;API_TOKEN&lt;/code&gt; is your useapi.net &lt;a href="https://useapi.net/docs/start-here/setup-useapi" rel="noopener noreferrer"&gt;API token&lt;/a&gt; and &lt;code&gt;EMAIL&lt;/code&gt; is your connected &lt;a href="https://useapi.net/docs/start-here/setup-google-flow" rel="noopener noreferrer"&gt;Google Flow account&lt;/a&gt; email. The script looks the account up by email automatically and checks its &lt;code&gt;health&lt;/code&gt; field before submitting.&lt;/p&gt;

&lt;p&gt;Prefer to clone and run it locally? The complete &lt;code&gt;google-flow-images.mjs&lt;/code&gt; and &lt;code&gt;prompts.json&lt;/code&gt; are on GitHub in &lt;a href="https://github.com/useapi/google-flow-api/tree/main/images" rel="noopener noreferrer"&gt;&lt;code&gt;useapi/google-flow-api&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"By default the nano-banana-2-lite model generates 4 image variations at 16:9."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nano-banana-pro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"aspectRatio"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1:1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"seed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;123456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nano Banana Pro (Gemini 3 Pro Image), two square variations. For all parameters see https://useapi.net/docs/api-google-flow-v1/post-google-flow-images"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nano-banana-2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"aspectRatio"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"auto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"reference_1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./reference_image.jpeg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Image-to-image: pass a local reference file as reference_1 (uploaded automatically). auto aspect ratio derives from the first reference. All three models accept up to 10 references."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nano-banana-2-lite"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"aspectRatio"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"9:16"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nano Banana 2 Lite portrait. Other models (nano-banana-2, nano-banana-pro) are selectable via the model field — see the POST /images docs."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;Real images generated through this same Google Flow API with Nano Banana Pro and Nano Banana 2 Lite — taken straight from our blog and model comparison.&lt;/p&gt;

&lt;p&gt;Nano Banana Pro — text-to-image (&lt;a href="https://useapi.net/blog/251120" rel="noopener noreferrer"&gt;source&lt;/a&gt;): &lt;em&gt;"Cat dressed like a pirate fencing with a real pirate… on a Disney cruise ship."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1441264638044930109%2Fnano-banana-pro-text-to-image.jfif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1441264638044930109%2Fnano-banana-pro-text-to-image.jfif" alt="Nano Banana Pro text-to-image result" width="768" height="1376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nano Banana Pro — 5 reference images (&lt;a href="https://useapi.net/blog/251201" rel="noopener noreferrer"&gt;source&lt;/a&gt;): five individual portraits composited into one "K-Pop group victory celebration" group shot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1444890082044543077%2Fresult.jfif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1444890082044543077%2Fresult.jfif" alt="Nano Banana Pro multi-reference group shot" width="1365" height="768"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nano Banana 2 Lite, the default model (&lt;a href="https://useapi.net/docs/articles/google-flow-nano-banana-compare#examples" rel="noopener noreferrer"&gt;source&lt;/a&gt;): the beekeeper prompt from our three-model comparison, rendered at 9:16 by the fastest of the three.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1522358033676632074%2Fnano-banana-2-lite.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fmedia.discordapp.net%2Fattachments%2F1239264794394234985%2F1522358033676632074%2Fnano-banana-2-lite.jpeg" alt="Nano Banana 2 Lite beekeeper result via the Google Flow API" width="768" height="1376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Frequently asked questions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Is there a Nano Banana 2 API?&lt;/strong&gt; Yes — two ways. Google offers Nano Banana 2 (Gemini 3.1 Flash Image) on the official &lt;a href="https://ai.google.dev/gemini-api/docs/pricing" rel="noopener noreferrer"&gt;Gemini API&lt;/a&gt;, which meters per image on a Google Cloud project. Or use useapi.net's &lt;a href="https://useapi.net/docs/api-google-flow-v1" rel="noopener noreferrer"&gt;Google Flow API&lt;/a&gt;, which exposes it as &lt;code&gt;nano-banana-2&lt;/code&gt; and drives your own Google Flow account through a standard REST endpoint — no Cloud project, and image generation works on any Google AI plan including the free tier. See Pricing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is there a Nano Banana Pro API?&lt;/strong&gt; Yes. Nano Banana Pro is Gemini 3 Pro Image, available on Google's official &lt;a href="https://ai.google.dev/gemini-api/docs/pricing#gemini-3-pro-image" rel="noopener noreferrer"&gt;Gemini API&lt;/a&gt;, which meters per image. useapi.net exposes the same model as &lt;code&gt;nano-banana-pro&lt;/code&gt; on the &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-images" rel="noopener noreferrer"&gt;POST /images&lt;/a&gt; endpoint, driving your Flow account instead of metering per image — see Pricing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which model does the API use by default?&lt;/strong&gt; &lt;code&gt;nano-banana-2-lite&lt;/code&gt; (Gemini 3.1 Flash-Lite Image), with or without references. Switch per request by setting &lt;code&gt;model&lt;/code&gt; to &lt;code&gt;nano-banana-2&lt;/code&gt; (Gemini 3.1 Flash Image) or &lt;code&gt;nano-banana-pro&lt;/code&gt; (Gemini 3 Pro Image, the highest quality). All three accept up to 10 reference images and can be upscaled to 2K/4K. &lt;a href="https://useapi.net/docs/articles/google-flow-nano-banana-compare" rel="noopener noreferrer"&gt;Nano Banana 2 Lite vs 2 vs Pro&lt;/a&gt; shows all three on one prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is Imagen 4 still available in Google Flow?&lt;/strong&gt; No. Google removed Imagen from Google Flow in July 2026. The &lt;code&gt;imagen-4&lt;/code&gt; model id is still accepted so existing code keeps working, but those requests now generate with &lt;code&gt;nano-banana-2-lite&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How much does it cost?&lt;/strong&gt; Image generation works with any Google AI subscription or a free account, plus a flat monthly &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;subscription&lt;/a&gt; to useapi.net for API access to all services. The official &lt;a href="https://ai.google.dev/gemini-api/docs/pricing#gemini-3-pro-image" rel="noopener noreferrer"&gt;Gemini API&lt;/a&gt; meters per image, while useapi.net includes generation in the flat subscription — see Pricing above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do I need a captcha or a Google Cloud project?&lt;/strong&gt; No Google Cloud project. Image generation requires reCAPTCHA, but you do not solve it yourself — the useapi.net worker solves it automatically, and your first Google Flow account comes with 300 free captcha credits as a one-time grant (powered by CapSolver). After that you configure your own provider keys via &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-accounts-captcha-providers" rel="noopener noreferrer"&gt;POST /accounts/captcha-providers&lt;/a&gt;. The script in this guide sends no &lt;code&gt;captchaToken&lt;/code&gt; and relies on this automatic solving.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Visit our &lt;a href="https://discord.gg/w28uK3cnmF" rel="noopener noreferrer"&gt;Discord Server&lt;/a&gt; or &lt;a href="https://t.me/use_api" rel="noopener noreferrer"&gt;Telegram Channel&lt;/a&gt; for any support questions and concerns.&lt;/p&gt;

&lt;p&gt;Check our &lt;a href="https://github.com/useapi/google-flow-api" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; with code examples.&lt;/p&gt;

</description>
      <category>nanobanana</category>
      <category>googleflow</category>
      <category>ai</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Generate Text-to-Speech Audio with the MiniMax (Hailuo) API</title>
      <dc:creator>useapi.net</dc:creator>
      <pubDate>Fri, 25 Sep 2026 22:28:13 +0000</pubDate>
      <link>https://dev.to/useapi/how-to-generate-text-to-speech-audio-with-the-minimax-hailuo-api-4bo1</link>
      <guid>https://dev.to/useapi/how-to-generate-text-to-speech-audio-with-the-minimax-hailuo-api-4bo1</guid>
      <description>&lt;h3&gt;
  
  
  Three ways to get audio
&lt;/h3&gt;

&lt;p&gt;Pick by how long the text is and whether you want to wait.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Text limit&lt;/th&gt;
&lt;th&gt;You get&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Short and simple&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-speech-create-mp3" rel="noopener noreferrer"&gt;POST speech/create-mp3&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;3,000 characters&lt;/td&gt;
&lt;td&gt;The finished MP3 URL in one call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anything longer&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-speech-create" rel="noopener noreferrer"&gt;POST speech/create&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;5,000, or 10,000 on &lt;code&gt;turbo&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;An &lt;code&gt;audioId&lt;/code&gt; straight away, plus a &lt;code&gt;replyUrl&lt;/code&gt; callback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Start playing sooner&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-speech-create" rel="noopener noreferrer"&gt;POST speech/create&lt;/a&gt; with &lt;code&gt;"stream": true&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;5,000, or 10,000 on &lt;code&gt;turbo&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;The audio streamed back as it renders, so playback can start before it is finished&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;create-mp3&lt;/code&gt; holds the connection open for the whole generation, which is why it is capped below what the models accept — 3,000 characters is about 22 seconds of waiting. For anything longer, use &lt;code&gt;create&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your first call
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "380426458095854",
    "text": "The last train leaves at midnight, and I still have not packed."
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#your-first-call" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That is &lt;code&gt;speech-2.8-hd&lt;/code&gt;, the default, with no styling at all. Everything below is that same line with one thing changed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Picking a voice
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-minimax-v1/get-minimax-speech-voices" rel="noopener noreferrer"&gt;GET speech/voices&lt;/a&gt; lists what the account can use. It returns 600+ voices across 40 languages, and MiniMax keeps adding:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;English, Arabic, Cantonese, Chinese (Mandarin), Dutch, French, German, Indonesian, Italian, Japanese, Korean, Portuguese, Russian, Spanish, Turkish, Ukrainian, Vietnamese, Thai, Polish, Romanian, Greek, Czech, Finnish, Hindi, Bulgarian, Danish, Hebrew, Malay, Persian, Slovak, Swedish, Croatian, Filipino, Hungarian, Norwegian, Slovenian, Catalan, Nynorsk, Tamil, Afrikaans&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Each voice carries tags for language, accent, gender and age, and &lt;code&gt;tag_list&lt;/code&gt; filters on them. Matching is exact and case-sensitive, and a tag it does not recognise is ignored rather than rejected — so &lt;code&gt;Female,Middle-Aged&lt;/code&gt; returns the same 310 voices as &lt;code&gt;Female&lt;/code&gt; alone rather than none. A typo widens the result instead of narrowing it, so check the count when you add a filter. &lt;a href="https://useapi.net/docs/api-minimax-v1/get-minimax-speech-config" rel="noopener noreferrer"&gt;GET speech/config&lt;/a&gt; returns the current vocabulary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.useapi.net/v1/minimax/speech/voices?is_system=true&amp;amp;tag_list=English"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer …"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The voice does more to the result than any other parameter. Same text, same model, a British female voice instead of the US male above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "236835177529411",
    "model": "speech-2.8-hd",
    "text": "The last train leaves at midnight, and I still have not packed."
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#picking-a-voice" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Steering the delivery
&lt;/h3&gt;

&lt;p&gt;Everything from here uses a cloned voice called &lt;strong&gt;Scarlett&lt;/strong&gt;, built from a one-minute sample — see Cloning a voice. The controls work identically on the built-in voices. Each sample has the exact call that produced it folded up above it.&lt;/p&gt;

&lt;p&gt;Three kinds of markup go directly inside &lt;code&gt;text&lt;/code&gt;, and they combine. Only emotion tags are free, because they are stripped before billing. Sounds and pauses are billed in full, markup and all.&lt;/p&gt;

&lt;h4&gt;
  
  
  Emotion
&lt;/h4&gt;

&lt;p&gt;Wrap a span in &lt;code&gt;{emotion}…{/emotion}&lt;/code&gt;. Eight are available — &lt;code&gt;happy&lt;/code&gt;, &lt;code&gt;sad&lt;/code&gt;, &lt;code&gt;angry&lt;/code&gt;, &lt;code&gt;fearful&lt;/code&gt;, &lt;code&gt;disgusted&lt;/code&gt;, &lt;code&gt;surprised&lt;/code&gt;, &lt;code&gt;neutral&lt;/code&gt;, &lt;code&gt;fluent&lt;/code&gt; — and a single request may carry up to 15 spans.&lt;/p&gt;

&lt;p&gt;The five below are the ones that separate most cleanly. &lt;code&gt;surprised&lt;/code&gt; and &lt;code&gt;happy&lt;/code&gt; tend to converge, as do &lt;code&gt;neutral&lt;/code&gt; and &lt;code&gt;sad&lt;/code&gt;, so pick across the range rather than adjacent to it. The line is the same six words every time — only the delivery decides whether it is an accusation, dread, revulsion, delight or grief.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{angry}&lt;/code&gt; — accusation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "user:12345-minimax:1234…-voice:433688037470324",
    "model": "speech-2.8-hd",
    "text": "{angry}Look at what you have done.{/angry}"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#emotion" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{fearful}&lt;/code&gt; — dread:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "user:12345-minimax:1234…-voice:433688037470324",
    "model": "speech-2.8-hd",
    "text": "{fearful}Look at what you have done.{/fearful}"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#emotion" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{disgusted}&lt;/code&gt; — revulsion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "user:12345-minimax:1234…-voice:433688037470324",
    "model": "speech-2.8-hd",
    "text": "{disgusted}Look at what you have done.{/disgusted}"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#emotion" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{happy}&lt;/code&gt; — delight:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "user:12345-minimax:1234…-voice:433688037470324",
    "model": "speech-2.8-hd",
    "text": "{happy}Look at what you have done.{/happy}"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#emotion" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{sad}&lt;/code&gt; — grief:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "user:12345-minimax:1234…-voice:433688037470324",
    "model": "speech-2.8-hd",
    "text": "{sad}Look at what you have done.{/sad}"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#emotion" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How far a voice can swing is set by the voice, not the tag. A clone inherits the range of whatever you fed it, so a one-minute sample of even-toned speech will not shout. The built-in voices tagged as expressive have more headroom — the same five emotions on &lt;code&gt;Radiant Girl&lt;/code&gt; (&lt;code&gt;236835177529409&lt;/code&gt;), for comparison: &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838177051250688/e-radiant-angry.mp3" rel="noopener noreferrer"&gt;angry&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838184945057893/e-radiant-fearful.mp3" rel="noopener noreferrer"&gt;fearful&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838180633182339/e-radiant-disgusted.mp3" rel="noopener noreferrer"&gt;disgusted&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838188237594804/e-radiant-happy.mp3" rel="noopener noreferrer"&gt;happy&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838191362478181/e-radiant-sad.mp3" rel="noopener noreferrer"&gt;sad&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Sounds
&lt;/h4&gt;

&lt;p&gt;Nineteen non-speech sounds render in place when written in parentheses: &lt;code&gt;laughs&lt;/code&gt;, &lt;code&gt;chuckle&lt;/code&gt;, &lt;code&gt;coughs&lt;/code&gt;, &lt;code&gt;clear-throat&lt;/code&gt;, &lt;code&gt;groans&lt;/code&gt;, &lt;code&gt;breath&lt;/code&gt;, &lt;code&gt;pant&lt;/code&gt;, &lt;code&gt;inhale&lt;/code&gt;, &lt;code&gt;exhale&lt;/code&gt;, &lt;code&gt;gasps&lt;/code&gt;, &lt;code&gt;sniffs&lt;/code&gt;, &lt;code&gt;sighs&lt;/code&gt;, &lt;code&gt;snorts&lt;/code&gt;, &lt;code&gt;burps&lt;/code&gt;, &lt;code&gt;lip-smacking&lt;/code&gt;, &lt;code&gt;humming&lt;/code&gt;, &lt;code&gt;hissing&lt;/code&gt;, &lt;code&gt;emm&lt;/code&gt;, &lt;code&gt;sneezes&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "user:12345-minimax:1234…-voice:433688037470324",
    "model": "speech-2.8-hd",
    "text": "I told you this would happen (sighs). Every single time (laughs)."
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#sounds" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Pauses
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;#seconds#&amp;gt;&lt;/code&gt; inserts a silence, anywhere from &lt;code&gt;0.01&lt;/code&gt; to &lt;code&gt;99.99&lt;/code&gt; seconds. This is the one that most improves long narration — models tend to run sentences together, and a beat between them fixes it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "user:12345-minimax:1234…-voice:433688037470324",
    "model": "speech-2.8-hd",
    "text": "I told you this would happen. &amp;lt;#1.5#&amp;gt; Every single time."
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#pauses" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Speed and pitch
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;speed&lt;/code&gt; runs &lt;code&gt;0.5&lt;/code&gt; to &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;pitch&lt;/code&gt; runs &lt;code&gt;-12&lt;/code&gt; to &lt;code&gt;12&lt;/code&gt;, both independent of the markup above. Back to the longer line so the difference is easier to hear.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"speed": 0.7&lt;/code&gt; — 7.6 seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "user:12345-minimax:1234…-voice:433688037470324",
    "model": "speech-2.8-hd",
    "text": "The last train leaves at midnight, and I still have not packed.",
    "speed": 0.7
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#speed-and-pitch" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"speed": 1.5&lt;/code&gt; — 3.2 seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "user:12345-minimax:1234…-voice:433688037470324",
    "model": "speech-2.8-hd",
    "text": "The last train leaves at midnight, and I still have not packed.",
    "speed": 1.5
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#speed-and-pitch" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"pitch": -6&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "user:12345-minimax:1234…-voice:433688037470324",
    "model": "speech-2.8-hd",
    "text": "The last train leaves at midnight, and I still have not packed.",
    "pitch": -6
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#speed-and-pitch" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"pitch": 6&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "user:12345-minimax:1234…-voice:433688037470324",
    "model": "speech-2.8-hd",
    "text": "The last train leaves at midnight, and I still have not packed.",
    "pitch": 6
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#speed-and-pitch" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are also voice effects — &lt;code&gt;deepen_lighten&lt;/code&gt;, &lt;code&gt;stronger_softer&lt;/code&gt; and &lt;code&gt;nasal_crisp&lt;/code&gt; take &lt;code&gt;-100&lt;/code&gt; to &lt;code&gt;100&lt;/code&gt;, and &lt;code&gt;spacious_echo&lt;/code&gt;, &lt;code&gt;lofi_telephone&lt;/code&gt;, &lt;code&gt;robotic&lt;/code&gt; and &lt;code&gt;auditorium_echo&lt;/code&gt; are switches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choosing a model
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Max characters&lt;/th&gt;
&lt;th&gt;Credits per character&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;speech-2.8-hd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Current, and the default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;speech-2.8-turbo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;0.6&lt;/td&gt;
&lt;td&gt;Current&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;speech-2.6-hd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Previous generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;speech-2.6-turbo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;0.6&lt;/td&gt;
&lt;td&gt;Previous generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;speech-2.5-hd-preview&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Superseded by 2.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;speech-2.5-turbo-preview&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;0.6&lt;/td&gt;
&lt;td&gt;Superseded by 2.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;speech-02-hd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Legacy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;speech-02-turbo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;0.6&lt;/td&gt;
&lt;td&gt;Legacy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;speech-01-hd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Legacy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;speech-01-turbo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;0.6&lt;/td&gt;
&lt;td&gt;Legacy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Use &lt;code&gt;speech-2.8-hd&lt;/code&gt; unless you have a reason not to. The older models stay selectable because they are still live at MiniMax, and because regenerating audio to match something made earlier needs the model that made it — not because they are worth picking for new work.&lt;/p&gt;

&lt;p&gt;Within a generation, &lt;code&gt;hd&lt;/code&gt; and &lt;code&gt;turbo&lt;/code&gt; are the same model tuned differently. &lt;code&gt;turbo&lt;/code&gt; costs 40% less per character and accepts twice the text in a single call. It is not measurably faster — on identical 990-character text the two came out level — so pick &lt;code&gt;turbo&lt;/code&gt; for the cheaper rate and the higher ceiling, and &lt;code&gt;hd&lt;/code&gt; when voice quality matters most.&lt;/p&gt;

&lt;p&gt;Sending more than a model accepts returns &lt;code&gt;400&lt;/code&gt; before anything is generated, so an oversized request never costs credits. The message names the model and its limit — &lt;code&gt;Parameter text length (5001) exceeds 5000 characters for model speech-2.8-hd&lt;/code&gt; — except at the absolute 10,000 ceiling, which is checked first and reports the limit without the model.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;hd&lt;/code&gt; and &lt;code&gt;turbo&lt;/code&gt; are the same family tuned differently. Turbo on the same line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "user:12345-minimax:1234…-voice:433688037470324",
    "model": "speech-2.8-turbo",
    "text": "The last train leaves at midnight, and I still have not packed."
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#choosing-a-model" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For narration where nobody is waiting, &lt;code&gt;speech-2.8-turbo&lt;/code&gt; is usually the better trade — it takes twice the text per call and costs 0.6 credits a character against &lt;code&gt;hd&lt;/code&gt;'s 1, which MiniMax mirrors as $60 against $100 per million on their own API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Word timings for captions
&lt;/h3&gt;

&lt;p&gt;A finished generation carries a &lt;code&gt;subtitles&lt;/code&gt; array with millisecond boundaries per phrase.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"subtitles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The last train leaves at midnight"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"time_begin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"time_end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2245.2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;time_begin&lt;/code&gt; and &lt;code&gt;time_end&lt;/code&gt;. The &lt;code&gt;text_begin&lt;/code&gt; and &lt;code&gt;text_end&lt;/code&gt; fields come back from MiniMax but do not reliably index into the text, so treat them as opaque.&lt;/p&gt;

&lt;p&gt;One limitation worth planning around: timings only reach you through &lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-speech-create-mp3" rel="noopener noreferrer"&gt;POST speech/create-mp3&lt;/a&gt; or the streaming &lt;code&gt;done&lt;/code&gt; event. MiniMax does not store them, so polling &lt;a href="https://useapi.net/docs/api-minimax-v1/get-minimax-speech_audio_id" rel="noopener noreferrer"&gt;GET speech/&lt;code&gt;audioId&lt;/code&gt;&lt;/a&gt; or waiting on a &lt;code&gt;replyUrl&lt;/code&gt; callback gives you &lt;code&gt;has_srt&lt;/code&gt; but not the timings themselves. If you need captions for more than 3,000 characters, use &lt;code&gt;stream&lt;/code&gt; and keep the &lt;code&gt;done&lt;/code&gt; payload.&lt;/p&gt;

&lt;h3&gt;
  
  
  Long text without waiting
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-speech-create" rel="noopener noreferrer"&gt;POST speech/create&lt;/a&gt; answers in about four seconds with an &lt;code&gt;audioId&lt;/code&gt;, whatever the length, and keeps generating in the background.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.useapi.net/v1/minimax/speech/create"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer …"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "380426458095854",
    "model": "speech-2.8-turbo",
    "text": "…up to 10,000 characters…",
    "replyUrl": "https://your.app/webhook"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"audioId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-minimax:1234…-audio:178737039436895391"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"statusLabel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"statusFinal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then either wait for the POST to &lt;code&gt;replyUrl&lt;/code&gt;, or poll &lt;a href="https://useapi.net/docs/api-minimax-v1/get-minimax-speech_audio_id" rel="noopener noreferrer"&gt;GET speech/&lt;code&gt;audioId&lt;/code&gt;&lt;/a&gt; until &lt;code&gt;statusFinal&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;. A 10,000-character request takes around 78 seconds and yields 12 to 16 minutes of speech, so poll every few seconds rather than tightly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Streaming
&lt;/h3&gt;

&lt;p&gt;Set &lt;code&gt;stream&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; and the response is &lt;code&gt;text/event-stream&lt;/code&gt; instead of JSON, with the id in an &lt;code&gt;X-Audio-Id&lt;/code&gt; header. First audio lands about four seconds in rather than at the end.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;audio&lt;/code&gt; events carry two different things, and &lt;code&gt;format&lt;/code&gt; tells them apart. &lt;code&gt;format: "mp3"&lt;/code&gt; events are chunks — append them in arrival order and the result is a plain MP3. A short line sends one, a 10,000-character generation sends around 40 over a minute or two. &lt;code&gt;format: "wav"&lt;/code&gt; with &lt;code&gt;complete: true&lt;/code&gt; is the same speech again as a whole WAV file, delivered after the chunks. Do not append that one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;audio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mp3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;atob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charCodeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A streamed generation is tracked like any other, so if the connection drops the recording still completes and the &lt;code&gt;audioId&lt;/code&gt; still resolves. Full worked example on the &lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-speech-create#streaming" rel="noopener noreferrer"&gt;endpoint page&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloning a voice
&lt;/h3&gt;

&lt;p&gt;Every sample from Steering the delivery onward uses a cloned voice. This is how it was made.&lt;/p&gt;

&lt;p&gt;Two calls. &lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-speech-upload-sample" rel="noopener noreferrer"&gt;POST speech/upload-sample&lt;/a&gt; takes the raw bytes of an MP3 or WAV and returns a &lt;code&gt;fileId&lt;/code&gt;, then &lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-speech-clone-voice" rel="noopener noreferrer"&gt;POST speech/clone-voice&lt;/a&gt; turns that into a voice you pass as &lt;code&gt;voice_id&lt;/code&gt; anywhere above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.useapi.net/v1/minimax/speech/upload-sample"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer …"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: audio/mpeg"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-binary&lt;/span&gt; &lt;span class="s2"&gt;"@sample.mp3"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"fileID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-minimax:1234…-file:54768197611603968682433"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feed that straight into the clone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.useapi.net/v1/minimax/speech/clone-voice"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer …"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_name": "Scarlett",
    "language_tag": "English",
    "files": "user:12345-minimax:1234…-file:54768197611603968682433"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"voice_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:12345-minimax:1234…-voice:433688037470324"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"voice_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Scarlett"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"voice_status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the source sample that was uploaded — one minute of ordinary speech, nothing special:&lt;/p&gt;

&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#cloning-a-voice" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And this is the clone reading a line it has never seen, 35 seconds after that upload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/speech/create-mp3'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:1234-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "voice_id": "user:12345-minimax:1234…-voice:433688037470324",
    "model": "speech-2.8-hd",
    "text": "The last train leaves at midnight, and I still have not packed."
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/minimax-speech-bash#cloning-a-voice" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The returned &lt;code&gt;voice_id&lt;/code&gt; goes anywhere &lt;code&gt;voice_id&lt;/code&gt; is accepted, exactly like a built-in one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-speech-upload-sample" rel="noopener noreferrer"&gt;POST speech/upload-sample&lt;/a&gt; takes &lt;code&gt;?account=&lt;/code&gt; in the query string, like the read endpoints — there is no identifier to infer it from, since the body is raw bytes. The &lt;code&gt;fileID&lt;/code&gt; it returns then pins the voice to that account, which is why &lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-speech-clone-voice" rel="noopener noreferrer"&gt;POST speech/clone-voice&lt;/a&gt; takes no &lt;code&gt;account&lt;/code&gt; of its own and reads it from &lt;code&gt;files&lt;/code&gt;. &lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-speech-delete-voice" rel="noopener noreferrer"&gt;POST speech/delete-voice&lt;/a&gt; works the same way, taking only a &lt;code&gt;voice_id&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Slots
&lt;/h4&gt;

&lt;p&gt;Cloned voices occupy a slot, and how many you get depends on the MiniMax plan. Check before you spend 35 seconds discovering there is no room:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.useapi.net/v1/minimax/speech/equity"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer …"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"voice_clone_preview_free_quota"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"inf"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Free one with &lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-speech-delete-voice" rel="noopener noreferrer"&gt;POST speech/delete-voice&lt;/a&gt;. Note &lt;code&gt;used&lt;/code&gt; is allowed to exceed &lt;code&gt;total&lt;/code&gt; — treat these as advisory and let the clone call itself be the authority.&lt;/p&gt;

&lt;p&gt;Only clone voices you have permission to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Managing what you have generated
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-minimax-v1/get-minimax-speech" rel="noopener noreferrer"&gt;GET speech&lt;/a&gt; lists every recording on the account, newest first, including any made on minimax.io directly. Each row carries the &lt;code&gt;audio_url&lt;/code&gt;, the voice name, and &lt;code&gt;has_srt&lt;/code&gt; / &lt;code&gt;has_wav&lt;/code&gt; telling you whether timings and a WAV rendition exist.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.useapi.net/v1/minimax/speech/?page_size=10"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer …"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://useapi.net/docs/api-minimax-v1/get-minimax-speech_audio_id" rel="noopener noreferrer"&gt;GET speech/&lt;code&gt;audioId&lt;/code&gt;&lt;/a&gt; returns one recording in full — the voice it used, the model, &lt;code&gt;cost_credit&lt;/code&gt;, and the speed, pitch and effects it was generated with. It is also what you poll after an async create.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-minimax-v1/del-minimax-speech-audio_id" rel="noopener noreferrer"&gt;DELETE speech/&lt;code&gt;audioId&lt;/code&gt;&lt;/a&gt; removes one permanently. A generation still in flight cannot be deleted, because there is nothing stored yet — cancel that with &lt;a href="https://useapi.net/docs/api-minimax-v1/del-minimax-scheduler-videoId" rel="noopener noreferrer"&gt;DELETE scheduler/&lt;code&gt;id&lt;/code&gt;&lt;/a&gt; instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it costs
&lt;/h3&gt;

&lt;p&gt;Speech bills per character against the MiniMax Audio balance — the same pool music draws on. One credit per character on an &lt;code&gt;hd&lt;/code&gt; model, 0.6 on a &lt;code&gt;turbo&lt;/code&gt; one.&lt;/p&gt;

&lt;p&gt;That works out to $33 a million characters on the $99 Pro plan, against $100 on MiniMax's own pay-as-you-go API — the comparison at the top of this page has all three options side by side.&lt;/p&gt;

&lt;p&gt;A few things worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cost_credit&lt;/code&gt; appears only on &lt;a href="https://useapi.net/docs/api-minimax-v1/get-minimax-speech_audio_id" rel="noopener noreferrer"&gt;GET speech/&lt;code&gt;audioId&lt;/code&gt;&lt;/a&gt;, not on the list or on the &lt;code&gt;create-mp3&lt;/code&gt; response — that one returns &lt;code&gt;usage_characters&lt;/code&gt;, the raw count before the model's ratio.&lt;/li&gt;
&lt;li&gt;Emotion tags are free. Sound and pause markup is billed as written: 79 characters including &lt;code&gt;(sighs)&lt;/code&gt; and &lt;code&gt;(laughs)&lt;/code&gt; billed as 79.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;turbo&lt;/code&gt; is charged at 0.6 credits a character, and the discount is real credits rather than a list price. &lt;a href="https://useapi.net/docs/api-minimax-v1/get-minimax-speech_audio_id" rel="noopener noreferrer"&gt;GET speech/&lt;code&gt;audioId&lt;/code&gt;&lt;/a&gt; reports what was charged as &lt;code&gt;cost_credit&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Speech needs a MiniMax audio subscription. Without one the call returns &lt;code&gt;412&lt;/code&gt; however much video credit the account holds, though a new account gets a small allowance first.&lt;/li&gt;
&lt;li&gt;Only a few generations run concurrently per account. Past that a request returns &lt;code&gt;429&lt;/code&gt; and the ones already running are unaffected, so retry when one finishes. The ceiling looks plan-dependent — a free account allows three.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;Every recording on this page is a real generation, and the call that produced it is folded up directly above it. The first two use built-in voices. Everything from Steering the delivery onward uses the cloned Scarlett voice on &lt;code&gt;speech-2.8-hd&lt;/code&gt; unless noted, apart from the long-text example, which is back on a built-in voice.&lt;/p&gt;

&lt;p&gt;Clone source and result: &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838216142159952/s00-clone-source.mp3" rel="noopener noreferrer"&gt;the one-minute sample&lt;/a&gt; that was uploaded, and &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540834084123582524/s01-baseline.mp3" rel="noopener noreferrer"&gt;the clone&lt;/a&gt; reading a line it had never seen.&lt;/p&gt;

&lt;p&gt;Emotion, the same six words each time — &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838194386309160/e-scarlett-angry.mp3" rel="noopener noreferrer"&gt;angry&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838201055514634/e-scarlett-fearful.mp3" rel="noopener noreferrer"&gt;fearful&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838197528100895/e-scarlett-disgusted.mp3" rel="noopener noreferrer"&gt;disgusted&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838205291626546/e-scarlett-happy.mp3" rel="noopener noreferrer"&gt;happy&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838209158651974/e-scarlett-sad.mp3" rel="noopener noreferrer"&gt;sad&lt;/a&gt;. The same five on the built-in &lt;code&gt;Radiant Girl&lt;/code&gt;, which has more range: &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838177051250688/e-radiant-angry.mp3" rel="noopener noreferrer"&gt;angry&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838184945057893/e-radiant-fearful.mp3" rel="noopener noreferrer"&gt;fearful&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838180633182339/e-radiant-disgusted.mp3" rel="noopener noreferrer"&gt;disgusted&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838188237594804/e-radiant-happy.mp3" rel="noopener noreferrer"&gt;happy&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540838191362478181/e-radiant-sad.mp3" rel="noopener noreferrer"&gt;sad&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Everything else: &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540834105426579598/s07-sounds.mp3" rel="noopener noreferrer"&gt;sounds&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540834108949790840/s08-pauses.mp3" rel="noopener noreferrer"&gt;pauses&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540834112380735498/s09-speed-slow.mp3" rel="noopener noreferrer"&gt;slow&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540834115694100510/s10-speed-fast.mp3" rel="noopener noreferrer"&gt;fast&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540834119007870996/s11-pitch-low.mp3" rel="noopener noreferrer"&gt;low pitch&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540834122623098930/s12-pitch-high.mp3" rel="noopener noreferrer"&gt;high pitch&lt;/a&gt;, &lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1540834126364676096/s13-turbo.mp3" rel="noopener noreferrer"&gt;turbo&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where to go next
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-speech-create" rel="noopener noreferrer"&gt;POST speech/create&lt;/a&gt; — every parameter, response and error&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://useapi.net/docs/api-minimax-v1/get-minimax-speech-voices" rel="noopener noreferrer"&gt;GET speech/voices&lt;/a&gt; — the voice catalogue&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://useapi.net/docs/api-minimax-v1/get-minimax-speech-config" rel="noopener noreferrer"&gt;GET speech/config&lt;/a&gt; — emotion and tag vocabularies, for building your own picker&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/useapi/minimax-api" rel="noopener noreferrer"&gt;&lt;code&gt;minimax-api&lt;/code&gt; GitHub repo&lt;/a&gt; — a runnable batch script that reads a list of lines, generates each one, and downloads the MP3s, with a &lt;code&gt;--voices&lt;/code&gt; mode for finding a &lt;code&gt;voice_id&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>texttospeech</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Sora 2 API Alternatives Compared, With Code: Seedance 2.5, Omni Flash, MiniMax H3, Kling v3</title>
      <dc:creator>useapi.net</dc:creator>
      <pubDate>Mon, 21 Sep 2026 03:48:43 +0000</pubDate>
      <link>https://dev.to/useapi/sora-2-api-alternatives-compared-with-code-seedance-25-omni-flash-minimax-h3-kling-v3-4cek</link>
      <guid>https://dev.to/useapi/sora-2-api-alternatives-compared-with-code-seedance-25-omni-flash-minimax-h3-kling-v3-4cek</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;OpenAI removes &lt;code&gt;sora-2&lt;/code&gt;, &lt;code&gt;sora-2-pro&lt;/code&gt; and the whole Videos API on September 24, 2026, and its deprecation table names no replacement — so the migration is to another vendor, and through the &lt;a href="https://useapi.net/" rel="noopener noreferrer"&gt;useapi.net&lt;/a&gt; APIs the same six-second shot costs between $0.08 and $1.80 depending on which one you pick.&lt;/p&gt;

&lt;p&gt;The most expensive of the four costs 22 times the cheapest — $1.80 against $0.08 — from the same brief, the same character and the same framing. At any real volume that gap, not the output quality, is what decides the choice.&lt;/p&gt;

&lt;p&gt;So the comparison is not just a table, the same scene was shot five times with one character: a neon-sign maker retires a SORA 2 sign, then presents each replacement in turn. Every clip was generated by the model whose name is on the sign, so what you are watching is each model describing itself, at its own price:&lt;/p&gt;



&lt;strong&gt;The result&lt;/strong&gt; — 31 seconds, five models, one character&lt;br&gt;&lt;small&gt;$3.68 in total, all five clips · [watch on YouTube](https://www.youtube.com/watch?v=W5vXcM2cCJs)&lt;/small&gt;



&lt;h3&gt;
  
  
  What is actually being removed
&lt;/h3&gt;

&lt;p&gt;On March 24, 2026 OpenAI notified developers that the Videos API and every Sora 2 alias and snapshot — &lt;code&gt;sora-2&lt;/code&gt;, &lt;code&gt;sora-2-pro&lt;/code&gt;, &lt;code&gt;sora-2-2025-10-06&lt;/code&gt;, &lt;code&gt;sora-2-2025-12-08&lt;/code&gt;, &lt;code&gt;sora-2-pro-2025-10-06&lt;/code&gt; — would be removed on September 24, 2026. The Sora consumer app had already closed on April 26, 2026. After the removal date the endpoints stop answering, and OpenAI says it will permanently delete the data associated with your use of Sora once any final export window closes — so anything you still need has to come down before then.&lt;/p&gt;

&lt;p&gt;The detail that decides the migration is the shape of the &lt;a href="https://developers.openai.com/api/docs/deprecations" rel="noopener noreferrer"&gt;deprecations table&lt;/a&gt; itself. Most rows name a recommended replacement. The Sora 2 and Videos API rows leave that column empty, because OpenAI has no other video model to move you to. There is no in-house upgrade path — the only question is which vendor you go to instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  The four replacements
&lt;/h3&gt;

&lt;p&gt;Each of these generates video from a start frame with synchronised speech, which is the capability most Sora 2 pipelines were using. Prices are for a six-second clip at each model's nearest tier to 720p, on the best per-credit rate of each route.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Vendor&lt;/th&gt;
&lt;th&gt;Route&lt;/th&gt;
&lt;th&gt;Six seconds&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Omni 1.1 Flash&lt;/td&gt;
&lt;td&gt;Google&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-google-flow-v1" rel="noopener noreferrer"&gt;Google Flow API&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$0.08&lt;/td&gt;
&lt;td&gt;generates at 360p or 720p, free upscale to 1080p&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kling v3&lt;/td&gt;
&lt;td&gt;Kuaishou&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-kling-v1" rel="noopener noreferrer"&gt;Kling API&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$0.44&lt;/td&gt;
&lt;td&gt;up to 4K, derives aspect from the frame&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MiniMax H3&lt;/td&gt;
&lt;td&gt;MiniMax&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-pixverse-v2" rel="noopener noreferrer"&gt;PixVerse API&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$0.72&lt;/td&gt;
&lt;td&gt;768p or 1440p, no 720p tier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Seedance 2.5&lt;/td&gt;
&lt;td&gt;ByteDance&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-pixverse-v2" rel="noopener noreferrer"&gt;PixVerse API&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$1.80&lt;/td&gt;
&lt;td&gt;reference audio and video, via create-fusion&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;MiniMax H3 is also the only one of the four whose weights are public, which matters if you are thinking about self-hosting. The FAQ covers what the licence actually allows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Every route here is flat-fee. You bring your own vendor account and add a flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; to useapi.net for API access, with no per-generation surcharge from us — the credits above are the vendor's own, spent on your own plan.&lt;/p&gt;

&lt;p&gt;The figures use the best per-credit rate on each route, on monthly billing: PixVerse Premium at $0.00400 per credit, Google AI Ultra $199 at roughly $0.008 per Flow credit, and Kling Ultra monthly at $0.00615. These are the lowest per-credit rates, not the cheapest plans — Premium is $60 a month and Ultra $199 is Google's top tier. Yearly billing is cheaper again on all three. Full per-model, per-plan tables are on the &lt;a href="https://useapi.net/docs/api-pixverse-v2" rel="noopener noreferrer"&gt;PixVerse overview&lt;/a&gt;, the &lt;a href="https://useapi.net/docs/api-google-flow-v1" rel="noopener noreferrer"&gt;Google Flow overview&lt;/a&gt; and the &lt;a href="https://useapi.net/docs/api-kling-v1" rel="noopener noreferrer"&gt;Kling overview&lt;/a&gt;, and the numbers move when vendors change their promotions, so treat them as current-as-of-publication rather than contractual.&lt;/p&gt;

&lt;p&gt;Route matters as much as plan. MiniMax H3 also runs on our own &lt;a href="https://useapi.net/docs/api-minimax-v1" rel="noopener noreferrer"&gt;MiniMax API&lt;/a&gt; at 7 credits per second, about $0.32 for the same six seconds against $0.72 on PixVerse. Both PixVerse clips here were kept on one account for convenience, not because it was the cheapest way to buy them. The &lt;a href="https://useapi.net/model-matrix" rel="noopener noreferrer"&gt;model matrix&lt;/a&gt; lists every API that carries a given model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting the video back
&lt;/h3&gt;

&lt;p&gt;Every create call below is asynchronous — it returns an id, not a file. All of them authenticate the same way, with your useapi.net token as &lt;code&gt;Authorization: Bearer user:1234-…&lt;/code&gt; (see &lt;a href="https://useapi.net/docs/start-here/setup-useapi" rel="noopener noreferrer"&gt;Setup&lt;/a&gt;), and that one token reaches all four vendors.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Route&lt;/th&gt;
&lt;th&gt;Poll&lt;/th&gt;
&lt;th&gt;Finished when&lt;/th&gt;
&lt;th&gt;The file&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PixVerse&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-pixverse-v2/get-pixverse-videos-video_id" rel="noopener noreferrer"&gt;GET /videos/{video_id}&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;video_status_final: true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;url&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Flow&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid" rel="noopener noreferrer"&gt;GET /jobs/{jobId}&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;status: "completed"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fifeUrl&lt;/code&gt; on the returned media&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kling&lt;/td&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-kling-v1/get-kling-tasks-task_id" rel="noopener noreferrer"&gt;GET /tasks/{task_id}&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;status_final: true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;works[0].resource.resource&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Any create call also accepts &lt;code&gt;replyUrl&lt;/code&gt;, which calls you back when the job finishes instead of making you poll.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: one character, reused everywhere
&lt;/h3&gt;

&lt;p&gt;Everything starts from a single generated portrait. Images are free on Google Flow — Nano Banana Pro is billed at $0.134 an image on the official Gemini API and included here — so this stage costs nothing however many times you run it. It is passed as &lt;code&gt;reference_1&lt;/code&gt; to every later image request, which is what keeps the same face, the same room and the same bench across five clips made by four different vendors. Nothing else carries identity between them.&lt;/p&gt;

&lt;p&gt;The character is invented rather than photographed. In our runs Google's moderation was markedly stricter with real, identifiable people, and a generated reference sidesteps that entirely.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1551387405334872244/sora2-alt-00-character-reference-nano-banana-pro.jpg" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1551387405334872244%2Fsora2-alt-00-character-reference-nano-banana-pro.jpg" alt="The generated character used across all five clips: a neon-sign maker behind a steel workbench, reused as the reference for the Seedance 2.5, Omni 1.1 Flash, MiniMax H3 and Kling v3 start frames" width="768" height="1376"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;strong&gt;The character&lt;/strong&gt; — Nano Banana Pro&lt;br&gt;&lt;small&gt;0 credits&lt;/small&gt;



&lt;h3&gt;
  
  
  Step 2: a start frame per model
&lt;/h3&gt;

&lt;p&gt;One image request per clip, each passing the character as &lt;code&gt;reference_1&lt;/code&gt; and changing only the sign's text and colour. Holding the wording identical — &lt;em&gt;"Same man, same room, same framing as the reference image … change only the sign"&lt;/em&gt; — is what keeps the framing stable enough that the five clips cut together.&lt;/p&gt;

&lt;p&gt;Text on a generated sign is the fragile part. Twelve characters (&lt;code&gt;SEEDANCE 2.5&lt;/code&gt;) rendered cleanly here, but that is close to where image models start mangling glyphs, so check every frame before spending a credit on video. Pick the variant where the whole sign sits inside the frame, not one that runs off the edge — once the clip animates, anything near the border clips out of shot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1551387303027540120/sora2-alt-02-start-frame-seedance-2-5-nano-banana-pro.jpg" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1551387303027540120%2Fsora2-alt-02-start-frame-seedance-2-5-nano-banana-pro.jpg" alt="Seedance 2.5 start frame: the sign maker behind a pink SEEDANCE 2.5 neon sign, the ByteDance Sora 2 replacement" width="720" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;
Seedance 2.5



&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1551387308366889003/sora2-alt-03-start-frame-omni-1-1-flash-nano-banana-pro.jpg" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1551387308366889003%2Fsora2-alt-03-start-frame-omni-1-1-flash-nano-banana-pro.jpg" alt="Omni 1.1 Flash start frame: the sign maker behind an amber OMNI FLASH neon sign, the Google Sora 2 replacement" width="768" height="1376"&gt;&lt;/a&gt;&lt;/p&gt;
Omni 1.1 Flash



&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1551387314071019590/sora2-alt-04-start-frame-minimax-h3-nano-banana-pro.jpg" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1551387314071019590%2Fsora2-alt-04-start-frame-minimax-h3-nano-banana-pro.jpg" alt="MiniMax H3 start frame: the sign maker behind a cyan MINIMAX H3 neon sign, the MiniMax Sora 2 replacement" width="768" height="1366"&gt;&lt;/a&gt;&lt;/p&gt;
MiniMax H3



&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1551387320165339277/sora2-alt-05-start-frame-kling-v3-nano-banana-pro.jpg" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1551387320165339277%2Fsora2-alt-05-start-frame-kling-v3-nano-banana-pro.jpg" alt="Kling v3 start frame: the sign maker behind a green KLING V3 neon sign, the Kuaishou Sora 2 replacement" width="768" height="1376"&gt;&lt;/a&gt;&lt;/p&gt;
Kling v3



&lt;p&gt;The start frames live in Google Flow, and the video calls below are on three different vendors. Omni 1.1 Flash takes the Flow &lt;code&gt;mediaGenerationId&lt;/code&gt; directly. For the others, download the frame with &lt;a href="https://useapi.net/docs/api-google-flow-v1/get-google-flow-assets-mediagenerationid" rel="noopener noreferrer"&gt;GET /assets/{mediaGenerationId}&lt;/a&gt;, then upload the file to &lt;a href="https://useapi.net/docs/api-pixverse-v2/post-pixverse-files" rel="noopener noreferrer"&gt;POST /files&lt;/a&gt; for PixVerse and use the returned &lt;code&gt;path&lt;/code&gt;, or to &lt;a href="https://useapi.net/docs/api-kling-v1/post-kling-assets" rel="noopener noreferrer"&gt;POST /assets&lt;/a&gt; for Kling and use the returned URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: the farewell clip, on Sora 2 itself
&lt;/h3&gt;

&lt;p&gt;The opening clip was generated on Sora 2 while it still answers, through &lt;a href="https://useapi.net/docs/api-pixverse-v2" rel="noopener noreferrer"&gt;PixVerse&lt;/a&gt; rather than OpenAI directly. The sign maker boxes the sign and ships it off. Sora 2 only accepts 4, 8 or 12 seconds — there is no six-second option — so this one is eight, trimmed back to six in the reel.&lt;/p&gt;



&lt;strong&gt;Sora 2&lt;/strong&gt; — 720p&lt;br&gt;&lt;small&gt;$0.64 for eight seconds&lt;/small&gt;



&lt;h3&gt;
  
  
  Step 4: one clip per replacement
&lt;/h3&gt;

&lt;p&gt;The same prompt shape drives all four, with only the model name and the closing line changed. Each names itself, gives a flat endorsement, then an honest catch.&lt;/p&gt;



&lt;strong&gt;Seedance 2.5&lt;/strong&gt;&lt;br&gt;&lt;small&gt;$1.80&lt;/small&gt;





&lt;strong&gt;Omni 1.1 Flash&lt;/strong&gt;&lt;br&gt;&lt;small&gt;$0.08&lt;/small&gt;





&lt;strong&gt;MiniMax H3&lt;/strong&gt;&lt;br&gt;&lt;small&gt;$0.72&lt;/small&gt;





&lt;strong&gt;Kling v3&lt;/strong&gt;&lt;br&gt;&lt;small&gt;$0.44&lt;/small&gt;



&lt;h3&gt;
  
  
  What changes when you move off Sora 2
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Duration grids differ, and a hard-coded value will not port. Sora 2 took 4, 8 or 12 seconds. Omni 1.1 Flash takes 4, 6, 8 or 10, MiniMax H3 5 to 15, Kling v3 3 to 15, and Seedance 2.5 anything from 4 to 30.&lt;/li&gt;
&lt;li&gt;Resolution tiers are not uniform either. Omni 1.1 Flash generates at 360p or 720p, MiniMax H3 skips 720p entirely and jumps 768p to 1440p, Seedance 2.5 reaches 1080p and Kling v3 goes to 4K. Mixing them means conforming everything to the lowest common size, so pick that size before you shoot.&lt;/li&gt;
&lt;li&gt;Quality varies more than the resolution numbers suggest. At the same nominal size the H3 clip came back at 1.3 Mbps against Seedance's 6.5 Mbps, and it is visibly the softest of the set.&lt;/li&gt;
&lt;li&gt;Voice is the one capability that does not port cleanly. Seedance 2.5 is the only one of the four that accepts an uploaded audio clip as a reference, and only through &lt;a href="https://useapi.net/docs/api-pixverse-v2/post-pixverse-videos-create-fusion" rel="noopener noreferrer"&gt;create-fusion&lt;/a&gt;. Omni 1.1 Flash offers Google's preset voices through &lt;code&gt;referenceAudio_1&lt;/code&gt;, and Kling can carry a voice on a character &lt;a href="https://useapi.net/docs/api-kling-v1/post-kling-elements" rel="noopener noreferrer"&gt;element&lt;/a&gt;. Each clip here uses its model's own native voice, which is why they differ.&lt;/li&gt;
&lt;li&gt;Prompts mostly carry over, with one habit worth adopting: give each physical action its own sentence and describe expressions positively. Trailing clauses and negations get dropped, unevenly, by all four.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What it cost
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Credits&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Character portrait, 9:16&lt;/td&gt;
&lt;td&gt;Nano Banana Pro&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Four start frames, 9:16&lt;/td&gt;
&lt;td&gt;Nano Banana Pro&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clip 1, Sora 2, 8s 720p, trimmed to 6s&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sora-2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;160&lt;/td&gt;
&lt;td&gt;$0.64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clip 2, Seedance 2.5, 6s 720p&lt;/td&gt;
&lt;td&gt;&lt;code&gt;seedance-2.5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;450&lt;/td&gt;
&lt;td&gt;$1.80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clip 3, Omni 1.1 Flash, 6s 720p&lt;/td&gt;
&lt;td&gt;&lt;code&gt;omni-flash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;$0.08&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clip 4, MiniMax H3, 6s 768p&lt;/td&gt;
&lt;td&gt;&lt;code&gt;minimax-h3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;180&lt;/td&gt;
&lt;td&gt;$0.72&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clip 5, Kling v3, 6s 1080p&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kling-v3-0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;72&lt;/td&gt;
&lt;td&gt;$0.44&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$3.68&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Images cost nothing on Google Flow, so iterate on the character and the signs as long as you like before spending anything on video. All five clips together came to $3.68, and the cheapest of them is the $0.08 one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run it yourself
&lt;/h3&gt;

&lt;p&gt;Every call on this page chains into two scripts. &lt;a href="https://github.com/useapi/sora-2-alternatives" rel="noopener noreferrer"&gt;&lt;code&gt;useapi/sora-2-alternatives&lt;/code&gt;&lt;/a&gt; holds them along with every prompt above in &lt;a href="https://github.com/useapi/sora-2-alternatives/prompts.json" rel="noopener noreferrer"&gt;&lt;code&gt;prompts.json&lt;/code&gt;&lt;/a&gt;: &lt;code&gt;frames/&lt;/code&gt; generates the character and a start frame per model, and &lt;code&gt;clips/&lt;/code&gt; sends each frame to the model named on its sign, then prints the credit cost the API returned.&lt;/p&gt;

&lt;p&gt;The frame stage is free, so you can iterate on the character and the signs as long as you like before spending anything. One command does the cheap end of the comparison on its own:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node clips.mjs &amp;lt;API_TOKEN&amp;gt; omni
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Frequently asked questions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;When exactly does the Sora 2 API stop working?&lt;/strong&gt; September 24, 2026. OpenAI announced it on March 24, 2026, covering the Videos API and every &lt;code&gt;sora-2&lt;/code&gt; alias and snapshot. After that date the endpoints stop answering and OpenAI permanently deletes the associated data once any final export window closes, so download anything you still need first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What does OpenAI recommend migrating to?&lt;/strong&gt; Nothing. The &lt;a href="https://developers.openai.com/api/docs/deprecations" rel="noopener noreferrer"&gt;deprecations table&lt;/a&gt; leaves the recommended-replacement column empty for both rows, because OpenAI has no other video model in the API. Migration means another vendor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which alternative is closest to Sora 2 in capability?&lt;/strong&gt; For the common case — a start frame plus synchronised speech — all four here do it. Seedance 2.5 is the most capable, taking up to 30 reference images plus 10 reference videos and 10 reference audios — 50 in total, through &lt;a href="https://useapi.net/docs/api-pixverse-v2/post-pixverse-videos-create-fusion" rel="noopener noreferrer"&gt;create-fusion&lt;/a&gt; — and it is also the most expensive at $1.80 per six seconds. Omni 1.1 Flash does the same core job for $0.08 with a 720p ceiling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is MiniMax H3 really open source?&lt;/strong&gt; Its weights are public — MiniMax published them in early August 2026, 33B parameters, on &lt;a href="https://huggingface.co/MiniMaxAI/MiniMax-H3" rel="noopener noreferrer"&gt;Hugging Face&lt;/a&gt;. It is open-&lt;em&gt;weight&lt;/em&gt; under a custom community licence whose territory clause requires an application form for the USA, EU, UK and South Korea, so "open source" is a loose description of it. The full repository runs to hundreds of gigabytes, though the smallest usable checkpoint is far smaller.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do I pay useapi.net per generation?&lt;/strong&gt; No. You bring your own vendor account and pay a flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; for API access. The credits in the table are the vendor's own, spent against your plan. See Pricing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Visit our &lt;a href="https://discord.gg/w28uK3cnmF" rel="noopener noreferrer"&gt;Discord Server&lt;/a&gt; or &lt;a href="https://t.me/use_api" rel="noopener noreferrer"&gt;Telegram Channel&lt;/a&gt; for any support questions and concerns.&lt;/p&gt;

&lt;p&gt;Check our &lt;a href="https://github.com/useapi/sora-2-alternatives" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; with code examples.&lt;/p&gt;

</description>
      <category>sora</category>
      <category>seedance</category>
      <category>ai</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Make a UGC Product Video with the Google Flow API</title>
      <dc:creator>useapi.net</dc:creator>
      <pubDate>Sat, 05 Sep 2026 04:53:54 +0000</pubDate>
      <link>https://dev.to/useapi/how-to-make-a-ugc-product-video-with-the-google-flow-api-4nef</link>
      <guid>https://dev.to/useapi/how-to-make-a-ugc-product-video-with-the-google-flow-api-4nef</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A UGC product video can be built end to end through the &lt;a href="https://useapi.net/docs/api-google-flow-v1" rel="noopener noreferrer"&gt;useapi.net Google Flow API&lt;/a&gt; for 45 Flow credits, with nothing processed locally.&lt;/strong&gt; One invented presenter shows three invented products to the camera.&lt;/p&gt;

&lt;p&gt;UGC is the user-generated-content style that fills social feeds and ad libraries: one person talking to a phone camera, to sell a product, to entertain, or just for fun.&lt;/p&gt;

&lt;p&gt;This is the full A-to-Z guide to producing that kind of video at a professional level: the products, the presenter, her lines and the final cut all under your control, in six steps of API calls you can copy as they are.&lt;/p&gt;

&lt;p&gt;Here is the result, three 10-second Omni 1.1 Flash clips upscaled to 1080p, every frame and every sound produced through the &lt;a href="https://useapi.net/docs/api-google-flow-v1" rel="noopener noreferrer"&gt;Google Flow API&lt;/a&gt;. The same upscale call goes to 4K when you need professional quality, see Step 5:&lt;/p&gt;



&lt;strong&gt;The result&lt;/strong&gt; — 29 seconds, 1080p, three products, three clips&lt;br&gt;&lt;small&gt;45 credits in total&lt;/small&gt;



&lt;p&gt;If you would rather watch than read, here is the whole guide in 75 seconds:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/wbUROtDIfGA" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The 75-second walkthrough&lt;/strong&gt; · &lt;a href="https://www.youtube.com/watch?v=wbUROtDIfGA" rel="noopener noreferrer"&gt;watch on YouTube&lt;/a&gt; · narration and music from the &lt;a href="https://useapi.net/docs/api-minimax-v1" rel="noopener noreferrer"&gt;MiniMax API&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Omni 1.1 Flash video needs a paid &lt;a href="https://one.google.com/ai" rel="noopener noreferrer"&gt;Google AI&lt;/a&gt; plan plus a flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; to useapi.net for API access, with no per-call surcharge. Every image, portrait, character and the concatenate below cost nothing. The three 10-second clips cost 15 Flow credits each, 45 in total, which is 45 cents on the Google AI Ultra $99 plan. Full per-tier credit costs are on the &lt;a href="https://useapi.net/docs/api-google-flow-v1" rel="noopener noreferrer"&gt;Google Flow overview&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  About the ids in the requests
&lt;/h3&gt;

&lt;p&gt;Every request below refers to earlier results by their &lt;code&gt;mediaGenerationId&lt;/code&gt;. The ids are long, so they are shortened here to &lt;code&gt;user:1234-email:…-image:b0bdf3e8-…&lt;/code&gt;, and a line under each request says which earlier result each one is. An image id comes back from &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-images" rel="noopener noreferrer"&gt;POST /images&lt;/a&gt; under &lt;code&gt;media[0].image.generatedImage.mediaGenerationId&lt;/code&gt;, a character id in the &lt;code&gt;character&lt;/code&gt; field of &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-characters" rel="noopener noreferrer"&gt;POST /characters&lt;/a&gt;, a video id under &lt;code&gt;media[0].mediaGenerationId&lt;/code&gt; of the finished &lt;a href="https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid" rel="noopener noreferrer"&gt;job&lt;/a&gt;, and an upscaled clip's id is its source's id with &lt;code&gt;_upsampled&lt;/code&gt; on the end.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: a sheet for each product
&lt;/h3&gt;

&lt;p&gt;A product sheet is one image that shows the item from four sides, so the model has the whole object and not one lucky angle. &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-images" rel="noopener noreferrer"&gt;POST /images&lt;/a&gt;, square, one request per product. The prompt spells out the camera for every panel, because "front, side, back" on its own gave two identical panels for the mug and no true side for the keyboard. A flat object like the keyboard needs a top-down panel, a cube-shaped one does not. No hands, no captions, no logos, so nothing but the product can leak into the clips.&lt;/p&gt;

&lt;p&gt;The same works for a real product. Upload photos of it with &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-assets-email" rel="noopener noreferrer"&gt;POST /assets&lt;/a&gt; and pass their ids as &lt;code&gt;reference_1&lt;/code&gt; to &lt;code&gt;reference_4&lt;/code&gt; on this request, and the model turns them into a clean four-panel sheet. The same trick makes a sheet for a package, a logo or a set.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1545251455705809068/01-ugc-products-sheet-smart-mug-nano-banana-2-lite.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1545251455705809068%2F01-ugc-products-sheet-smart-mug-nano-banana-2-lite.png" alt="Product sheet of the smart mug, four views in a 2 by 2 grid" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;strong&gt;The mug&lt;/strong&gt; — Nano Banana 2 Lite, id &lt;code&gt;b0bdf3e8&lt;/code&gt;&lt;br&gt;&lt;small&gt;0 credits&lt;/small&gt;



&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1545251460005105675/02-ugc-products-sheet-desk-robot-nano-banana-2-lite.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1545251460005105675%2F02-ugc-products-sheet-desk-robot-nano-banana-2-lite.png" alt="Product sheet of the desk robot, four views in a 2 by 2 grid" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;strong&gt;The desk robot&lt;/strong&gt; — Nano Banana 2 Lite, id &lt;code&gt;7aaed056&lt;/code&gt;&lt;br&gt;&lt;small&gt;0 credits&lt;/small&gt;



&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1545251464509923378/03-ugc-products-sheet-three-key-keyboard-nano-banana-2-lite.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1545251464509923378%2F03-ugc-products-sheet-three-key-keyboard-nano-banana-2-lite.png" alt="Product sheet of the three-key keyboard, four views in a 2 by 2 grid" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;strong&gt;The keyboard&lt;/strong&gt; — Nano Banana 2 Lite, id &lt;code&gt;4f861c23&lt;/code&gt;&lt;br&gt;&lt;small&gt;0 credits&lt;/small&gt;



&lt;p&gt;Images cost nothing, so ask for &lt;code&gt;count&lt;/code&gt; of 2 to 4 and keep the best sheet. The keyboard took a few rounds before its prompt described a real macro pad with a top-down panel, the cube worked first time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: the presenter
&lt;/h3&gt;

&lt;p&gt;Three calls. A front portrait from a description. A three-quarter portrait generated from the first one with &lt;code&gt;reference_1&lt;/code&gt;, so the two agree on the face. Then &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-characters" rel="noopener noreferrer"&gt;POST /characters&lt;/a&gt; with both portraits, which returns a character reference. From then on she is &lt;code&gt;@character_1&lt;/code&gt; in any prompt, and Google pins her through its own entity system instead of through a description.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1545251470063050894/04-ugc-products-presenter-front-nano-banana-2-lite.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1545251470063050894%2F04-ugc-products-presenter-front-nano-banana-2-lite.png" alt="Front portrait of the presenter" width="800" height="1071"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;strong&gt;Front&lt;/strong&gt; — Nano Banana 2 Lite, id &lt;code&gt;a236ef66&lt;/code&gt;&lt;br&gt;&lt;small&gt;0 credits&lt;/small&gt;



&lt;p&gt;Rendered a few looks, picked this one. If a detail needs changing afterwards, the chain say, re-render her with her own portrait as &lt;code&gt;reference_1&lt;/code&gt; and a prompt that names only the change, and the face stays put.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;reference_1&lt;/code&gt; is the front portrait, &lt;code&gt;a236ef66&lt;/code&gt;. This prompt still mentions freckles, a sweater and earrings left over from an earlier presenter, and it did no harm: with a reference image in the request, the reference wins over the words.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1545251474735505459/05-ugc-products-presenter-three-quarter-nano-banana-2-lite.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1545251474735505459%2F05-ugc-products-presenter-three-quarter-nano-banana-2-lite.png" alt="Three-quarter portrait of the presenter, generated from the front portrait" width="800" height="1071"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;strong&gt;Three-quarter&lt;/strong&gt; — id &lt;code&gt;d891301c&lt;/code&gt;&lt;br&gt;&lt;small&gt;0 credits&lt;/small&gt;



&lt;p&gt;&lt;code&gt;imageReference_1&lt;/code&gt; is the front portrait &lt;code&gt;a236ef66&lt;/code&gt;, &lt;code&gt;imageReference_2&lt;/code&gt; the three-quarter &lt;code&gt;d891301c&lt;/code&gt;. The response's &lt;code&gt;character&lt;/code&gt; field is her id, &lt;code&gt;53ca1036&lt;/code&gt; below. The &lt;code&gt;voice&lt;/code&gt; is one of Google's system presets and rides along with the character, but it cannot reach the clip mode used in Step 4, see What to expect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: the still, the whole scene in one frame
&lt;/h3&gt;

&lt;p&gt;One request puts everything together. The character goes in as &lt;code&gt;character_1&lt;/code&gt;, the three sheets as &lt;code&gt;reference_1&lt;/code&gt; to &lt;code&gt;reference_3&lt;/code&gt;, and the prompt places them by tag, left to right on the table in front of her. This frame becomes both ends of every clip, so it is the one place where the tags do their work.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;character_1&lt;/code&gt; is the character from Step 2, &lt;code&gt;53ca1036&lt;/code&gt;. &lt;code&gt;reference_1&lt;/code&gt; to &lt;code&gt;reference_3&lt;/code&gt; are the three sheets from Step 1: the mug &lt;code&gt;b0bdf3e8&lt;/code&gt;, the desk robot &lt;code&gt;7aaed056&lt;/code&gt;, the keyboard &lt;code&gt;4f861c23&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://demo.useapi.net/discord-cdn-proxy/?https://cdn.discordapp.com/attachments/1239264794394234985/1545251479877714009/06-ugc-products-still-presenter-and-three-products-nano-banana-2-lite.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo.useapi.net%2Fdiscord-cdn-proxy%2F%3Fhttps%3A%2F%2Fcdn.discordapp.com%2Fattachments%2F1239264794394234985%2F1545251479877714009%2F06-ugc-products-still-presenter-and-three-products-nano-banana-2-lite.png" alt="The presenter at the table with the mug, the desk robot and the keyboard laid out in front of her" width="768" height="1376"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;strong&gt;The still&lt;/strong&gt; — her face from the character, each product from its sheet, id &lt;code&gt;034cddc8&lt;/code&gt;&lt;br&gt;&lt;small&gt;0 credits&lt;/small&gt;



&lt;p&gt;The mug has its glow, the robot its face and antenna, the keyboard its three colours and its port, and she is the woman from the portraits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: one clip per product, all from the still
&lt;/h3&gt;

&lt;p&gt;Omni's first-plus-last-frame mode with the still in both slots, one request per product, the same &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos" rel="noopener noreferrer"&gt;POST /videos&lt;/a&gt; each time. This mode takes nothing but the two images, no sheets, no character, no voice reference. That is fine, because the still already holds all of it. Every item she picks up came out matching its sheet from the still alone.&lt;/p&gt;

&lt;p&gt;The prompt does three jobs. It pins both ends to the frame, with a quiet beat on each side. It gives her the line and the voice. And it times the choreography: she starts talking as she lifts the item, the item is back on its spot by the eight-second mark, and the last two seconds are a still, silent hold. Without that last part she ran late and her arm snapped into the end frame.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;startImage&lt;/code&gt; and &lt;code&gt;endImage&lt;/code&gt; are both the still from Step 3, &lt;code&gt;034cddc8&lt;/code&gt;. The same two ids go into all three clips.&lt;/p&gt;



&lt;strong&gt;Clip 1, the mug&lt;/strong&gt; — 10 seconds, id &lt;code&gt;55808825&lt;/code&gt;, shown after the 1080p upscale of Step 5&lt;br&gt;&lt;small&gt;15 credits&lt;/small&gt;





&lt;strong&gt;Clip 2, the desk robot&lt;/strong&gt; — 10 seconds, id &lt;code&gt;c4d0e6b1&lt;/code&gt;, shown after the 1080p upscale of Step 5&lt;br&gt;&lt;small&gt;15 credits&lt;/small&gt;





&lt;strong&gt;Clip 3, the keyboard&lt;/strong&gt; — 10 seconds, id &lt;code&gt;3cc8ea2f&lt;/code&gt;, shown after the 1080p upscale of Step 5&lt;br&gt;&lt;small&gt;15 credits&lt;/small&gt;



&lt;p&gt;Same woman, same table, same light, and each clip opens and closes on the still, so any of them can follow any other. The lines are around 20 words, which is what 10 seconds holds at this pace with room for the beat at the end.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: upscale to 1080p
&lt;/h3&gt;

&lt;p&gt;Omni 1.1 Flash renders at 720p. &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-upscale" rel="noopener noreferrer"&gt;POST /videos/upscale&lt;/a&gt; takes a clip to 1080p for free on any paid plan, in about 40 seconds, and answers in the same call with the upscaled clip's id and URL. One request per clip, no &lt;code&gt;email&lt;/code&gt;, the account comes from the id.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mediaGenerationId&lt;/code&gt; is the mug clip from Step 4, &lt;code&gt;55808825&lt;/code&gt;. The same call with &lt;code&gt;c4d0e6b1&lt;/code&gt; and &lt;code&gt;3cc8ea2f&lt;/code&gt; upscales the robot and the keyboard. Each response carries the new clip under &lt;code&gt;media[0].mediaGenerationId&lt;/code&gt;, which is the source id with &lt;code&gt;_upsampled&lt;/code&gt; on the end, so the three upscaled ids are &lt;code&gt;55808825-…_upsampled&lt;/code&gt;, &lt;code&gt;c4d0e6b1-…_upsampled&lt;/code&gt; and &lt;code&gt;3cc8ea2f-…_upsampled&lt;/code&gt;. The clips shown in Step 4 are these upscaled versions. 4K is also available, for 50 credits and only on a Google AI Ultra plan.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: join them
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-concatenate" rel="noopener noreferrer"&gt;POST /videos/concatenate&lt;/a&gt; takes the three upscaled ids in order and returns the joined file as base64, at the clips' resolution. The trims decide whether the joins feel like one take. Each clip opens with a short hold on the still and closes with a settle back onto it, and untrimmed those stack into a freeze at every cut. But she finishes each line with her hands already resting, so a trim measured from the picture alone cuts into the last words. Cut after the last sound plus a beat, never earlier. On these clips that meant leaving clip 1 whole, since its laugh runs to the last frame, taking just over half a second off the end of clip 2, and a few frames off the start of clips 2 and 3.&lt;/p&gt;

&lt;p&gt;The three ids are the upscaled clips from Step 5 in order: the mug, the desk robot, the keyboard.&lt;/p&gt;



&lt;strong&gt;Joined&lt;/strong&gt; — 28.8 seconds, 1080p&lt;br&gt;&lt;small&gt;0 credits&lt;/small&gt;



&lt;p&gt;She finishes a line with her hands on the table, the cut lands, and she reaches for the next item. The joined file was re-encoded to a smaller size for hosting, the three clips are as the API returned them.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to expect
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Generate, do not edit. The &lt;a href="https://useapi.net/blog/260902" rel="noopener noreferrer"&gt;UGC talking head&lt;/a&gt; post extended a clip with video-to-video edits, and that still works when the lines are short. Here it did not. An edit keeps its source's speech on the source's own timeline, so with a 10-second line filling the seed, a new line got braided into the old one instead of replacing it, and the products left on the table drifted between takes. Generating each clip from the still gave complete lines, intact products and cleaner joins, for fewer credits.&lt;/li&gt;
&lt;li&gt;The still carries the tags. The first-plus-last-frame mode accepts only the two images. Do the tagging in the still, with the character and the sheets, and the clips inherit it.&lt;/li&gt;
&lt;li&gt;Time the choreography. A 10-second clip with a full line needs the put-down called out by the clock, "by the eight-second mark", and a still, silent hold at the end. Left to itself the model ran the line long and jumped into the end frame.&lt;/li&gt;
&lt;li&gt;Describe the voice the same way in every prompt. Nothing carries a voice between separate generations, and a character can hold a voice preset but cannot reach this mode. With one identical description the three clips came back close enough to pass as one take.&lt;/li&gt;
&lt;li&gt;Sheets need per-panel cameras. Name what each of the four panels shows. Give flat objects a top-down panel. Keep hands, captions and logos out, because whatever is on the sheet can end up in the clip.&lt;/li&gt;
&lt;li&gt;Trim to the sound, not the picture. She goes still before she stops talking. A cut placed at the first still frame took the end of a line with it.&lt;/li&gt;
&lt;li&gt;The presenter is invented. Google's moderation is stricter with real, identifiable people. Start from a generated character.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What it cost
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Credits&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Three product sheets, 1:1&lt;/td&gt;
&lt;td&gt;Nano Banana 2 Lite&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Two presenter portraits, 3:4&lt;/td&gt;
&lt;td&gt;Nano Banana 2 Lite&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The character&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The still, 9:16&lt;/td&gt;
&lt;td&gt;Nano Banana 2 Lite, character + 3 references&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clip 1, the mug, 10s&lt;/td&gt;
&lt;td&gt;I2V, first + last frame&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clip 2, the desk robot, 10s&lt;/td&gt;
&lt;td&gt;I2V, first + last frame&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clip 3, the keyboard, 10s&lt;/td&gt;
&lt;td&gt;I2V, first + last frame&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Upscale, three clips to 1080p&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Concatenate&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;45&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A 10-second Omni clip costs 15 credits at 720p, so the whole video is 45 cents on the Google AI Ultra $99 plan. Images, characters, the 1080p upscale and the concatenate cost nothing, so iterate freely on the sheets, the presenter and the still before spending a credit on video. 4K is the one upgrade that costs, 50 credits a clip on Ultra.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run it yourself
&lt;/h3&gt;

&lt;p&gt;Every step above is one API call, and the six of them chain into a script. The complete Node.js pipeline, a Python port, and the &lt;a href="https://github.com/useapi/google-flow-api/blob/main/ugc-product-video/prompts.json" rel="noopener noreferrer"&gt;&lt;code&gt;prompts.json&lt;/code&gt;&lt;/a&gt; holding every prompt on this page live in &lt;a href="https://github.com/useapi/google-flow-api/tree/main/ugc-product-video" rel="noopener noreferrer"&gt;&lt;code&gt;useapi/google-flow-api/ugc-product-video&lt;/code&gt;&lt;/a&gt;. Clone it, put your own products and lines in &lt;code&gt;prompts.json&lt;/code&gt;, and one command builds the whole video.&lt;/p&gt;

&lt;p&gt;It checkpoints after every step, so an interrupted run resumes instead of paying for the clips again, and you can redo a single step — a better still, a different presenter — without regenerating what came before it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frequently asked questions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Can I use my own product photos instead of generated sheets?&lt;/strong&gt; Yes. Upload them with &lt;a href="https://useapi.net/docs/api-google-flow-v1/post-google-flow-assets-email" rel="noopener noreferrer"&gt;POST /assets&lt;/a&gt; and pass the returned ids as &lt;code&gt;reference_1&lt;/code&gt; to &lt;code&gt;reference_3&lt;/code&gt; on the still, exactly as the generated sheets are passed here. The four-panel sheet is a way to give the model every side of an object, and a real product benefits from the same treatment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why not edit one clip into the next, like the &lt;a href="https://useapi.net/blog/260902" rel="noopener noreferrer"&gt;talking-head post&lt;/a&gt;?&lt;/strong&gt; Because a video-to-video edit keeps its source's speech on the source's timeline. With short lines that replacement works. With a 10-second line filling the clip, the new line got braided into the old one and the products on the table drifted. Generating every clip from the same still avoids both, and costs 15 credits instead of 20. See What to expect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why do all three clips start and end on the same frame?&lt;/strong&gt; So they can be joined in any order with no visible cut. The first-plus-last-frame mode pins both ends of each clip to the still, and the concatenate trims the short holds around each join. The mechanism is explained in the &lt;a href="https://useapi.net/blog/260902" rel="noopener noreferrer"&gt;UGC talking head&lt;/a&gt; post.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does the voice stay the same across the clips?&lt;/strong&gt; Nothing carries a voice between separate first-plus-last generations, since that mode takes no audio reference, and a character's voice preset cannot reach it either. Describing the voice identically in every prompt kept these three close enough to pass as one take. If you need a guaranteed voice, the reference-to-video mode accepts &lt;code&gt;referenceAudio_1&lt;/code&gt;, at the cost of the pinned frames.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How much does it cost?&lt;/strong&gt; You keep your paid Google AI plan and add the flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;useapi.net subscription&lt;/a&gt;. The whole video is 45 Flow credits, 45 cents on the Ultra $99 plan, and every image, portrait, character and the concatenate are free. See Pricing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Visit our &lt;a href="https://discord.gg/w28uK3cnmF" rel="noopener noreferrer"&gt;Discord Server&lt;/a&gt; or &lt;a href="https://t.me/use_api" rel="noopener noreferrer"&gt;Telegram Channel&lt;/a&gt; for any support questions and concerns.&lt;/p&gt;

&lt;p&gt;Check our &lt;a href="https://github.com/useapi/google-flow-api" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; with code examples.&lt;/p&gt;

</description>
      <category>googleflow</category>
      <category>ugc</category>
      <category>ai</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Generate Multi-Reference &amp; Multi-Shot Video with Kling Omni via the Kling API</title>
      <dc:creator>useapi.net</dc:creator>
      <pubDate>Mon, 24 Aug 2026 00:18:24 +0000</pubDate>
      <link>https://dev.to/useapi/how-to-generate-multi-reference-multi-shot-video-with-kling-omni-via-the-kling-api-1091</link>
      <guid>https://dev.to/useapi/how-to-generate-multi-reference-multi-shot-video-with-kling-omni-via-the-kling-api-1091</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Kling Omni is the one Kling endpoint that lets you blend several image references into a single shot and storyboard a multi-shot sequence — each scene with its own prompt and duration — in one API job, all from code against your own Kling account.&lt;/strong&gt; &lt;a href="https://app.klingai.com" rel="noopener noreferrer"&gt;Kling AI&lt;/a&gt; is the generative video service from Chinese short-video giant &lt;a href="https://www.kuaishou.com/en" rel="noopener noreferrer"&gt;Kuaishou Technology&lt;/a&gt;, and &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;useapi.net&lt;/a&gt; fronts it with a third-party &lt;a href="https://useapi.net/docs/api-kling-v1" rel="noopener noreferrer"&gt;Kling API&lt;/a&gt; that runs your own Kling account over a standard REST endpoint — no enterprise contract, no per-call billing from us. This guide covers Omni specifically. For plain text-to-video and start/end-frame image-to-video, see the &lt;a href="https://useapi.net/docs/articles/kling-bash" rel="noopener noreferrer"&gt;core Kling tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Omni does
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://useapi.net/docs/api-kling-v1/post-kling-videos-omni" rel="noopener noreferrer"&gt;POST /videos/omni&lt;/a&gt; is a single endpoint that selects a workflow from the inputs you pass. Three of those are what set Omni apart from the plain text-to-video and frames endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-image reference — pass up to 7 reference images (&lt;code&gt;image_1&lt;/code&gt;…&lt;code&gt;image_7&lt;/code&gt;) and weave each into the prompt with &lt;code&gt;@image_1&lt;/code&gt;, &lt;code&gt;@image_2&lt;/code&gt;, … syntax, so one shot can combine a character, a prop, and a background.&lt;/li&gt;
&lt;li&gt;Video Elements — reusable saved character/object references created once with &lt;a href="https://useapi.net/docs/api-kling-v1/post-kling-elements" rel="noopener noreferrer"&gt;POST /elements&lt;/a&gt;, then dropped into any later generation as &lt;code&gt;@element_1&lt;/code&gt; (or &lt;code&gt;@object_1&lt;/code&gt;). Images and elements share the same pool of 7 slots, so the combined total can't exceed 7.&lt;/li&gt;
&lt;li&gt;Multi-shot (v3 only) — split one video into 2–6 sequential shots, each with its own &lt;code&gt;shot_N_prompt&lt;/code&gt; and &lt;code&gt;shot_N_duration&lt;/code&gt;, for storytelling with scene cuts in a single job.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Omni also handles a frames workflow (&lt;code&gt;frame_start&lt;/code&gt;/&lt;code&gt;frame_end&lt;/code&gt;) and a video-reference/transform workflow (&lt;code&gt;video_1&lt;/code&gt;), but those overlap with the core endpoints — this guide focuses on the multi-reference, Video Elements, and multi-shot paths.&lt;/p&gt;

&lt;p&gt;Two model versions exist, picked with &lt;code&gt;omni_version&lt;/code&gt;: &lt;code&gt;v3&lt;/code&gt; (the default) and &lt;code&gt;o1&lt;/code&gt;. Multi-shot and VIDEO-type elements are v3 only — &lt;code&gt;o1&lt;/code&gt; supports IMAGE elements and single-clip durations of 3–10s, while &lt;code&gt;v3&lt;/code&gt; runs 3–15s. Pick quality with &lt;code&gt;mode&lt;/code&gt;: &lt;code&gt;std&lt;/code&gt; (720p), &lt;code&gt;pro&lt;/code&gt; (1080p), or &lt;code&gt;4k&lt;/code&gt; (v3 only). Durations of 7s and up, counts of 2–4, and 4K need a VIP Kling plan.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;You keep your normal &lt;a href="https://kling.ai/app/membership/membership-plan" rel="noopener noreferrer"&gt;Kling&lt;/a&gt; website subscription and add a single flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; to useapi.net that covers API access to every supported service, with no per-generation surcharge from us — see the &lt;a href="https://useapi.net/docs/articles/kling-bash#pricing" rel="noopener noreferrer"&gt;core Kling tutorial's pricing section&lt;/a&gt; and the &lt;a href="https://useapi.net/docs/api-kling-v1" rel="noopener noreferrer"&gt;Kling API overview&lt;/a&gt; live cost calculator.&lt;/p&gt;

&lt;p&gt;This is the consumer-account route. Kuaishou's &lt;a href="https://klingai.com/global/dev/pricing" rel="noopener noreferrer"&gt;official Kling API&lt;/a&gt; bills per generation at developer rates on a separate developer account, while useapi.net automates the consumer account you already pay for at the &lt;a href="https://kling.ai/app/membership/membership-plan" rel="noopener noreferrer"&gt;website subscription&lt;/a&gt; price.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate a multi-reference video in two API calls
&lt;/h3&gt;

&lt;p&gt;You need a useapi.net &lt;a href="https://useapi.net/docs/start-here/setup-useapi" rel="noopener noreferrer"&gt;API token&lt;/a&gt; and a connected &lt;a href="https://useapi.net/docs/start-here/setup-kling" rel="noopener noreferrer"&gt;Kling account&lt;/a&gt; — export the token so the &lt;code&gt;curl&lt;/code&gt; examples below run as-is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;USEAPI_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"user:1234-..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generation is asynchronous — the create call returns a task object immediately, then you poll until the video is ready.&lt;/p&gt;

&lt;p&gt;First, upload each reference image with &lt;a href="https://useapi.net/docs/api-kling-v1/post-kling-assets" rel="noopener noreferrer"&gt;POST /assets&lt;/a&gt; (raw bytes, an image &lt;code&gt;Content-Type&lt;/code&gt;, max 10 MB, 300px minimum). It returns a Kling-hosted &lt;code&gt;url&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.useapi.net/v1/kling/assets/?email=user@example.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: image/jpeg"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-binary&lt;/span&gt; @character.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://s21-kling.klingai.com/....jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"fileName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"abc123def456789.jpg"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1. Submit the job&lt;/strong&gt; — &lt;code&gt;POST https://api.useapi.net/v1/kling/videos/omni&lt;/code&gt;. Pass each uploaded URL as &lt;code&gt;image_1&lt;/code&gt;, &lt;code&gt;image_2&lt;/code&gt;, … and reference them by name in the prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.useapi.net/v1/kling/videos/omni"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "prompt": "A woman @image_1 walking through the garden @image_2, holding the lantern @image_3, camera pushing in slowly",
    "omni_version": "v3",
    "mode": "pro",
    "aspect_ratio": "16:9",
    "duration": "5",
    "image_1": "https://s21-kling.klingai.com/.../character.jpg",
    "image_2": "https://s21-kling.klingai.com/.../garden.jpg",
    "image_3": "https://s21-kling.klingai.com/.../lantern.jpg"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response returns immediately with a task object of type &lt;code&gt;m2v_omni_video&lt;/code&gt;. The task id you poll on is &lt;code&gt;task.id&lt;/code&gt; (a number):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"task"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;123456789&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"m2v_omni_video"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"submitted"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status_final"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"works"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"submitted"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status_final"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;email&lt;/code&gt; field is required in the body only when you have more than one Kling account configured. A &lt;code&gt;500&lt;/code&gt; from Kling almost always means a content-moderation rejection rather than a server fault — read the &lt;code&gt;error&lt;/code&gt; text (the &lt;code&gt;message&lt;/code&gt; field is generic and often misleading) to tell them apart. &lt;code&gt;prompt&lt;/code&gt; maxes out at 1700 characters and references each input by its &lt;code&gt;@&lt;/code&gt;-name (&lt;code&gt;@image_1&lt;/code&gt;, &lt;code&gt;@element_1&lt;/code&gt;, &lt;code&gt;@video_1&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Poll for the result&lt;/strong&gt; — &lt;code&gt;GET https://api.useapi.net/v1/kling/tasks/{task_id}&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.useapi.net/v1/kling/tasks/123456789?email=user@example.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The task is done when &lt;code&gt;status_final&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;. Success is &lt;code&gt;status_name: "succeed"&lt;/code&gt; (&lt;code&gt;status: 99&lt;/code&gt;); the MP4 is in &lt;code&gt;works[0].resource.resource&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"succeed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status_final"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"works"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"workId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;123456789&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"status_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"succeed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://s21-kling.klingai.com/....mp4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;720&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1280&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5041&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The MP4 at &lt;code&gt;works[0].resource.resource&lt;/code&gt; is watermarked. To get the clean, non-watermarked master, take the &lt;code&gt;workId&lt;/code&gt; from the &lt;code&gt;works&lt;/code&gt; array and call &lt;a href="https://useapi.net/docs/api-kling-v1/get-kling-assets-download" rel="noopener noreferrer"&gt;GET /assets/download&lt;/a&gt; — it returns a &lt;code&gt;cdnUrl&lt;/code&gt; to the file (a single &lt;code&gt;workId&lt;/code&gt; plus a single &lt;code&gt;fileTypes&lt;/code&gt; value yields a direct MP4 link, otherwise a &lt;code&gt;.zip&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.useapi.net/v1/kling/assets/download?email=user@example.com&amp;amp;workIds=123456789&amp;amp;fileTypes=MP4"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the poll, a &lt;code&gt;404&lt;/code&gt; means the task was deleted, failed at moderation, or your Kling account ran out of credits — check your balance at &lt;a href="https://useapi.net/docs/api-kling-v1/get-kling-accounts-email" rel="noopener noreferrer"&gt;GET /accounts/&lt;code&gt;email&lt;/code&gt;&lt;/a&gt;. Prefer not to poll? Pass a &lt;code&gt;replyUrl&lt;/code&gt; in the create body to receive a webhook callback when the task completes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-shot sequences (v3)
&lt;/h3&gt;

&lt;p&gt;Instead of one &lt;code&gt;prompt&lt;/code&gt; and one &lt;code&gt;duration&lt;/code&gt;, v3 Omni lets you storyboard a single video as 2–6 sequential shots, each with its own &lt;code&gt;shot_N_prompt&lt;/code&gt; and matching &lt;code&gt;shot_N_duration&lt;/code&gt;. The total of all durations must land between 3 and 15 seconds, shots must be sequential with no gaps (&lt;code&gt;shot_1&lt;/code&gt; + &lt;code&gt;shot_2&lt;/code&gt;, never &lt;code&gt;shot_1&lt;/code&gt; + &lt;code&gt;shot_3&lt;/code&gt;), and the multi-shot parameters cannot be combined with &lt;code&gt;prompt&lt;/code&gt; or &lt;code&gt;duration&lt;/code&gt;. Each shot prompt can carry the same &lt;code&gt;@image_N&lt;/code&gt; / &lt;code&gt;@element_N&lt;/code&gt; references as a single-shot job, so a recurring character holds across cuts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.useapi.net/v1/kling/videos/omni"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "omni_version": "v3",
    "mode": "pro",
    "aspect_ratio": "16:9",
    "image_1": "https://s21-kling.klingai.com/.../kitchen.jpg",
    "shot_1_prompt": "Cinematic medium shot, a chef standing behind a stainless steel stove @image_1, focused intently on the pan",
    "shot_1_duration": "3",
    "shot_2_prompt": "Continuous scene at the same stove @image_1. The chef flips the food high into the air, then turns sharply to the camera",
    "shot_2_duration": "3"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response, polling, and clean download are identical to the single-shot flow above — the create call returns the same &lt;code&gt;task.id&lt;/code&gt;, and the finished sequence comes back as one MP4 in &lt;code&gt;works[0]&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Video Elements
&lt;/h3&gt;

&lt;p&gt;A Video Element is a reusable character or object reference you create once and drop into any later Omni job by ID — so the same face, costume, or prop stays consistent across separate generations without re-uploading and re-describing it each time. Create one with &lt;a href="https://useapi.net/docs/api-kling-v1/post-kling-elements" rel="noopener noreferrer"&gt;POST /elements&lt;/a&gt;. There are two types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IMAGE elements — built from a &lt;code&gt;coverImage&lt;/code&gt; URL (optionally with extra angle views, or AI-generated multi-angle views via &lt;code&gt;generateViews&lt;/code&gt;). Usable in both &lt;code&gt;o1&lt;/code&gt; and &lt;code&gt;v3&lt;/code&gt; Omni.&lt;/li&gt;
&lt;li&gt;VIDEO elements — built from a &lt;code&gt;video&lt;/code&gt; URL (mp4, minimum 3 seconds, auto-trimmed to 8s), which captures motion and can carry a voice. VIDEO elements work only in v3 Omni.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Upload the cover image (or clip) with &lt;a href="https://useapi.net/docs/api-kling-v1/post-kling-assets" rel="noopener noreferrer"&gt;POST /assets&lt;/a&gt; first, then register the element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.useapi.net/v1/kling/elements"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "name": "FashionLady",
    "coverImage": "https://s21-kling.klingai.com/.../character.jpg",
    "tag": "character"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returns a generated element &lt;code&gt;id&lt;/code&gt; (a 5-character random suffix is appended to your &lt;code&gt;name&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"elements"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"u_123456789012345"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FashionLady ABC12"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Elegant woman in red dress"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;tag&lt;/code&gt; is one of &lt;code&gt;character&lt;/code&gt;, &lt;code&gt;animal&lt;/code&gt;, &lt;code&gt;prop&lt;/code&gt;, &lt;code&gt;costume&lt;/code&gt;, &lt;code&gt;scene&lt;/code&gt;, &lt;code&gt;effect&lt;/code&gt;, or &lt;code&gt;others&lt;/code&gt; (from &lt;a href="https://useapi.net/docs/api-kling-v1/get-kling-elements-tags" rel="noopener noreferrer"&gt;GET /elements/tags&lt;/a&gt;) — leave it out to have Kling auto-detect it. List your saved elements anytime with &lt;a href="https://useapi.net/docs/api-kling-v1/get-kling-elements" rel="noopener noreferrer"&gt;GET /elements&lt;/a&gt;. Then reference the element by ID in any Omni prompt, alone or alongside images (remember the combined 7-slot limit):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.useapi.net/v1/kling/videos/omni"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$USEAPI_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "prompt": "Character @element_1 walking through a sunlit garden, smiling",
    "omni_version": "v3",
    "mode": "std",
    "duration": "5",
    "element_1": "u_123456789012345"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;character&lt;/code&gt;-tagged element can also carry a &lt;code&gt;voice&lt;/code&gt; — an official voice name/ID from &lt;a href="https://useapi.net/docs/api-kling-v1/get-kling-elements-voices" rel="noopener noreferrer"&gt;GET /elements/voices&lt;/a&gt;, or a 5–60s mp4 to clone one from. For a VIDEO element, voice is extracted automatically from the source clip when it has 5–60 seconds of audio.&lt;/p&gt;

&lt;h3&gt;
  
  
  Batch script
&lt;/h3&gt;

&lt;p&gt;Finding the right shot takes many attempts, and running them by hand is tedious. The Node.js script reads a list of prompts from &lt;a href="https://github.com/useapi/kling-api/prompts.json" rel="noopener noreferrer"&gt;&lt;code&gt;prompts.json&lt;/code&gt;&lt;/a&gt;, submits each one to the Omni endpoint — single-shot (&lt;code&gt;prompt&lt;/code&gt; + image/element refs) or multi-shot (&lt;code&gt;shots&lt;/code&gt;) — then polls every task until it is final and downloads the finished MP4, preferring the clean, non-watermarked master via &lt;a href="https://useapi.net/docs/api-kling-v1/get-kling-assets-download" rel="noopener noreferrer"&gt;GET /assets/download&lt;/a&gt; and falling back to the watermarked &lt;code&gt;works[0].resource.resource&lt;/code&gt; if needed. So you can queue a batch and come back to the winners.&lt;/p&gt;

&lt;p&gt;You need &lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; v21 or newer. Put &lt;code&gt;prompts.json&lt;/code&gt; and &lt;a href="https://github.com/useapi/kling-api/kling-omni.mjs" rel="noopener noreferrer"&gt;&lt;code&gt;kling-omni.mjs&lt;/code&gt;&lt;/a&gt; in the same folder and run &lt;code&gt;node ./kling-omni.mjs API_TOKEN EMAIL&lt;/code&gt;, where &lt;code&gt;API_TOKEN&lt;/code&gt; is your useapi.net &lt;a href="https://useapi.net/docs/start-here/setup-useapi" rel="noopener noreferrer"&gt;API token&lt;/a&gt; and &lt;code&gt;EMAIL&lt;/code&gt; is your connected &lt;a href="https://useapi.net/docs/start-here/setup-kling" rel="noopener noreferrer"&gt;Kling account&lt;/a&gt; email. The script looks the account up by email automatically. Pass image URLs (already uploaded via &lt;a href="https://useapi.net/docs/api-kling-v1/post-kling-assets" rel="noopener noreferrer"&gt;POST /assets&lt;/a&gt;) as &lt;code&gt;image_1&lt;/code&gt;…&lt;code&gt;image_7&lt;/code&gt;, and saved &lt;a href="https://useapi.net/docs/api-kling-v1/post-kling-elements" rel="noopener noreferrer"&gt;element&lt;/a&gt; IDs as &lt;code&gt;element_1&lt;/code&gt;…&lt;code&gt;element_7&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;The clips below are real Kling Omni generations produced through this Kling API, straight from our blog walkthroughs.&lt;/p&gt;

&lt;h6&gt;
  
  
  Multi-shot v3 — text-only 2-shot sequence via &lt;code&gt;POST /videos/omni&lt;/code&gt; (&lt;code&gt;omni_version: v3&lt;/code&gt;)
&lt;/h6&gt;



&lt;p&gt;— from &lt;a href="https://useapi.net/blog/260216" rel="noopener noreferrer"&gt;Kling v3: Multi-Shot Storytelling&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Video Elements v3 — two VIDEO elements + a background image, 720p ~11s via &lt;code&gt;POST /videos/omni&lt;/code&gt; (&lt;code&gt;omni_version: v3&lt;/code&gt;, &lt;code&gt;mode: std&lt;/code&gt;)
&lt;/h6&gt;



&lt;p&gt;— from &lt;a href="https://useapi.net/blog/260209" rel="noopener noreferrer"&gt;Kling v3: 4K Resolution and Video Elements&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Frequently asked questions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What is Kling Omni?&lt;/strong&gt; Omni is a single Kling video endpoint, &lt;a href="https://useapi.net/docs/api-kling-v1/post-kling-videos-omni" rel="noopener noreferrer"&gt;POST /videos/omni&lt;/a&gt;, that picks a workflow from your inputs: blend up to 7 image references (&lt;code&gt;@image_1&lt;/code&gt;…&lt;code&gt;@image_7&lt;/code&gt;), reuse saved Video Elements (&lt;code&gt;@element_1&lt;/code&gt;…), storyboard a v3 multi-shot sequence, run a start/end-frame transition, or guide generation from a reference video. See What Omni does above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I pass multiple image references to Kling?&lt;/strong&gt; Upload each image with &lt;a href="https://useapi.net/docs/api-kling-v1/post-kling-assets" rel="noopener noreferrer"&gt;POST /assets&lt;/a&gt;, pass the returned URLs as &lt;code&gt;image_1&lt;/code&gt;, &lt;code&gt;image_2&lt;/code&gt;, … (up to 7), and reference them in the prompt with &lt;code&gt;@image_1&lt;/code&gt;, &lt;code&gt;@image_2&lt;/code&gt;, etc. Images and saved elements share the same pool of 7 slots, so the combined total can't exceed 7. See Generate a multi-reference video in two API calls above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What are Video Elements and how do I reuse a character?&lt;/strong&gt; A Video Element is a reusable character/object reference created once with &lt;a href="https://useapi.net/docs/api-kling-v1/post-kling-elements" rel="noopener noreferrer"&gt;POST /elements&lt;/a&gt; — IMAGE elements from a &lt;code&gt;coverImage&lt;/code&gt;, or VIDEO elements from an mp4 clip (v3 only). It returns an &lt;code&gt;id&lt;/code&gt; like &lt;code&gt;u_123…&lt;/code&gt;, which you then drop into any Omni prompt as &lt;code&gt;@element_1&lt;/code&gt;. See Video Elements above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does Kling multi-shot work?&lt;/strong&gt; On v3 Omni, set &lt;code&gt;shot_1_prompt&lt;/code&gt;/&lt;code&gt;shot_1_duration&lt;/code&gt; through &lt;code&gt;shot_6_prompt&lt;/code&gt;/&lt;code&gt;shot_6_duration&lt;/code&gt; (minimum 2 shots) instead of a single &lt;code&gt;prompt&lt;/code&gt;/&lt;code&gt;duration&lt;/code&gt;. Shots must be sequential with no gaps and the total duration must be 3–15 seconds. See Multi-shot sequences (v3) above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which Omni version supports multi-shot and Video Elements?&lt;/strong&gt; Both are &lt;code&gt;v3&lt;/code&gt; only (the default). The &lt;code&gt;o1&lt;/code&gt; version supports IMAGE elements and single clips of 3–10s, while &lt;code&gt;v3&lt;/code&gt; adds VIDEO elements, multi-shot, &lt;code&gt;4k&lt;/code&gt; mode, and 3–15s durations. See What Omni does above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is my Omni video watermarked?&lt;/strong&gt; The MP4 at &lt;code&gt;works[0].resource.resource&lt;/code&gt; returned by the poll is the watermarked preview. To get the clean, non-watermarked master, take the &lt;code&gt;workId&lt;/code&gt; from the task's &lt;code&gt;works&lt;/code&gt; array and call &lt;a href="https://useapi.net/docs/api-kling-v1/get-kling-assets-download" rel="noopener noreferrer"&gt;GET /assets/download&lt;/a&gt; — it returns a &lt;code&gt;cdnUrl&lt;/code&gt; to the watermark-free file. This requires a paid Kling account. See Generate a multi-reference video in two API calls above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My generation returns a 500 — what does that mean?&lt;/strong&gt; Kling reuses the &lt;code&gt;500&lt;/code&gt; response for content-moderation rejections as well as genuine server faults, and the generic &lt;code&gt;message&lt;/code&gt; field rarely makes the difference clear. Read the &lt;code&gt;error&lt;/code&gt; text instead. If a job clears creation but the poll later returns &lt;code&gt;404&lt;/code&gt;, the task was deleted, failed at moderation, or your account ran out of credits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How is this different from the official Kling API?&lt;/strong&gt; Kuaishou's &lt;a href="https://klingai.com/global/dev/pricing" rel="noopener noreferrer"&gt;official Kling API&lt;/a&gt; bills per generation at developer rates on a separate developer account. useapi.net instead automates your own consumer Kling account, so you generate at the &lt;a href="https://kling.ai/app/membership/membership-plan" rel="noopener noreferrer"&gt;website subscription&lt;/a&gt; price plus a flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; — and the same one subscription covers &lt;a href="https://useapi.net/" rel="noopener noreferrer"&gt;10+ other AI services&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Visit our &lt;a href="https://discord.gg/w28uK3cnmF" rel="noopener noreferrer"&gt;Discord Server&lt;/a&gt; or &lt;a href="https://t.me/use_api" rel="noopener noreferrer"&gt;Telegram Channel&lt;/a&gt; for any support questions and concerns.&lt;/p&gt;

&lt;p&gt;The full runnable example is in the &lt;a href="https://github.com/useapi/kling-api" rel="noopener noreferrer"&gt;&lt;code&gt;kling-api&lt;/code&gt; GitHub repo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kling</category>
      <category>ai</category>
      <category>api</category>
      <category>aivideo</category>
    </item>
    <item>
      <title>Four AI Music APIs on the Same Six Briefs: TemPolor v4.8, MiniMax Music-3.0, Lyria 3.5 and Mureka V9.5</title>
      <dc:creator>useapi.net</dc:creator>
      <pubDate>Thu, 20 Aug 2026 02:52:41 +0000</pubDate>
      <link>https://dev.to/useapi/ai-music-apis-one-generation-later-minimax-music-30-vs-lyria-35-vs-mureka-v95-365p</link>
      <guid>https://dev.to/useapi/ai-music-apis-one-generation-later-minimax-music-30-vs-lyria-35-vs-mureka-v95-365p</guid>
      <description>&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Yqllep1eMBw" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;TemPolor v4.8, MiniMax Music-3.0, Google's Lyria 3.5 and Mureka V9.5 — four AI music models, the same six briefs, one &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;useapi.net&lt;/a&gt; API token. All 24 tracks are below, complete and unedited, each with the API call that made it.&lt;/strong&gt; They are the same briefs we used in July, so every track here has a predecessor to compare against in &lt;a href="https://useapi.net/docs/articles/ai-music-api-comparison" rel="noopener noreferrer"&gt;AI Music APIs Compared&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;TemPolor is the newcomer, and it prices differently from everything else here: a flat $30 a month for unlimited generations, where the other three charge about a cent a track. What that does to the maths is below. Listen first and judge the models yourself.&lt;/p&gt;

&lt;p&gt;Short on time? There is also a &lt;a href="https://youtu.be/Yqllep1eMBw" rel="noopener noreferrer"&gt;12-minute YouTube video&lt;/a&gt; — each track's loudest 30 seconds back to back, loudness-matched, with the prompt, price, and generation time on screen. The full-length tracks and the exact API call behind each one live on this page.&lt;/p&gt;

&lt;h3&gt;
  
  
  What changed since July
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;July&lt;/th&gt;
&lt;th&gt;Now&lt;/th&gt;
&lt;th&gt;What moved&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TemPolor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;not in the line-up&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;v4.8&lt;/strong&gt; (songs) + &lt;strong&gt;i4&lt;/strong&gt; (instrumentals)&lt;/td&gt;
&lt;td&gt;new to this comparison, and two new models&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mureka&lt;/td&gt;
&lt;td&gt;V9&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;V9.5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;new default model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flow Music&lt;/td&gt;
&lt;td&gt;Lyria 3 Pro&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Lyria 3.5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;new flagship — but 3 Pro is still the API default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MiniMax&lt;/td&gt;
&lt;td&gt;music-2.6 via PixVerse&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Music-3.0, native&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;new model &lt;em&gt;and&lt;/em&gt; a new endpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two of those are ordinary version bumps. The MiniMax row is not: &lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-music-create" rel="noopener noreferrer"&gt;MiniMax music is now a first-class endpoint&lt;/a&gt; rather than something you reach through &lt;a href="https://useapi.net/docs/api-pixverse-v2/post-pixverse-music-create" rel="noopener noreferrer"&gt;PixVerse&lt;/a&gt;. Different endpoint, different billing.&lt;/p&gt;

&lt;p&gt;TemPolor is the other exception. It is the only service here that splits the job across two endpoints with two different models: &lt;a href="https://useapi.net/docs/api-tempolor-v1/post-tempolor-music-song" rel="noopener noreferrer"&gt;&lt;code&gt;POST music/song&lt;/code&gt;&lt;/a&gt; runs &lt;code&gt;v4.8&lt;/code&gt; for anything with vocals, and &lt;a href="https://useapi.net/docs/api-tempolor-v1/post-tempolor-music-instrumental" rel="noopener noreferrer"&gt;&lt;code&gt;POST music/instrumental&lt;/code&gt;&lt;/a&gt; runs &lt;code&gt;i4&lt;/code&gt; for anything without. Older model names still work and are routed to the new ones automatically, so existing code keeps running — but it also means you can be on the new models without noticing, or miss them by passing nothing at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  The lineup and what it costs
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Through useapi.net&lt;/th&gt;
&lt;th&gt;The vendor's own API&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-tempolor-v1" rel="noopener noreferrer"&gt;TemPolor v4.8 / i4&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;$30/month, unlimited tracks&lt;/strong&gt; — no per-track rate at all&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://platform.tempolor.com/docs/6665893m0" rel="noopener noreferrer"&gt;$0.04/call&lt;/a&gt; in prepaid credits — &lt;a href="https://platform.tempolor.com/pricing" rel="noopener noreferrer"&gt;$100 to $5,000&lt;/a&gt; a package, no bulk discount&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-music-create" rel="noopener noreferrer"&gt;MiniMax Music-3.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;$0.010&lt;/strong&gt;/track&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://platform.minimax.io/docs/guides/pricing-paygo#music" rel="noopener noreferrer"&gt;$0.15/composition&lt;/a&gt;, +$0.01 if it writes the lyrics — &lt;strong&gt;15×&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-flowmusic-v1" rel="noopener noreferrer"&gt;Google Lyria 3.5&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;$0.011&lt;/strong&gt;/track&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://cloud.google.com/gemini-enterprise-agent-platform/generative-ai/pricing#lyria" rel="noopener noreferrer"&gt;$0.08/song&lt;/a&gt; — &lt;strong&gt;7×&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://useapi.net/docs/api-mureka-v1" rel="noopener noreferrer"&gt;Mureka V9.5&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;$0.0135&lt;/strong&gt;/track&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://platform.mureka.ai/pricing" rel="noopener noreferrer"&gt;$0.03/song&lt;/a&gt;, and the plan starts at $1,000/month — &lt;strong&gt;2×&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Per-track figures are each service's &lt;strong&gt;highest-volume monthly plan&lt;/strong&gt; — MiniMax Pro, Flow Music Member, Mureka Premier. Smaller plans cost more per track and still come in well under the official APIs.&lt;/p&gt;

&lt;p&gt;TemPolor does not fit that column. Its &lt;a href="https://www.tempolor.com/pricing" rel="noopener noreferrer"&gt;Ultra plan&lt;/a&gt; sells &lt;em&gt;unlimited&lt;/em&gt; generations for a flat monthly fee, and our submit responses came back with &lt;code&gt;"unlimited": true&lt;/code&gt; and no remaining-track count. Its cost per track is therefore just $30 divided by however many you make — a cent at a hundred a month, a tenth of a cent at a thousand. Prices exclude VAT.&lt;/p&gt;

&lt;p&gt;Going direct is a different shape of cost. TemPolor's &lt;a href="https://platform.tempolor.com/docs/6665893m0" rel="noopener noreferrer"&gt;own API&lt;/a&gt; charges $0.04 a call for the same model, paid in credits bought up front. Those credits cost &lt;a href="https://platform.tempolor.com/pricing" rel="noopener noreferrer"&gt;$0.01 each at every package size&lt;/a&gt; — $100 buys 10,000, $5,000 buys 500,000 — so volume never makes a track cheaper.&lt;/p&gt;

&lt;p&gt;What the bigger packages buy is concurrency: five requests at a time at $100, ten at $500, twenty at $5,000, and the tier does not stack if you buy the same package twice. The &lt;a href="https://useapi.net/docs/api-tempolor-v1" rel="noopener noreferrer"&gt;Ultra subscription&lt;/a&gt; this article ran on allows ten concurrent generations, unlimited, for $30 a month.&lt;/p&gt;

&lt;p&gt;One naming quirk if you compare the two routes: the model this article calls &lt;code&gt;v4.8&lt;/code&gt; is &lt;code&gt;tempolor-latest&lt;/code&gt; there. &lt;code&gt;i4&lt;/code&gt; keeps its name.&lt;/p&gt;

&lt;p&gt;These services all sell two things: a &lt;strong&gt;consumer subscription&lt;/strong&gt;, priced per month with a generous allowance, and an &lt;strong&gt;official API&lt;/strong&gt;, priced per call or per credit. The API rate is several times the effective per-song rate of the subscription, because that is where the margin lives.&lt;/p&gt;

&lt;p&gt;useapi.net connects to the account you already have. You subscribe to TemPolor, Mureka, MiniMax or Flow Music the way any user would, and we expose that account as a REST API — so generation is billed at consumer-subscription rates, not API rates. On top of that, useapi.net is a flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; for every service we support, with &lt;strong&gt;no per-generation surcharge&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every call in this article used a single token against all four services — no per-service SDK, no separate API keys, no four sets of billing to reconcile. The same token reaches every other service we support: video, image, speech, face swap.&lt;/p&gt;

&lt;h3&gt;
  
  
  How we tested
&lt;/h3&gt;

&lt;p&gt;Same six briefs as July, copied from the published article rather than retyped — two instrumentals, two vocal tracks where the model writes its own lyrics, and two where we supply both the lyrics and an elaborate style brief. Every model in a round receives the identical text, so what you hear is the model. TemPolor's bodies were copied byte for byte from the MiniMax ones, which take the same &lt;code&gt;prompt&lt;/code&gt; and &lt;code&gt;lyrics&lt;/code&gt; fields.&lt;/p&gt;

&lt;p&gt;Generation times are wall-clock through the API at 15-second polling granularity, so treat them as ballpark rather than benchmark. Where a model titles its own output we kept the title, spelling and stray spaces included. Tracks are complete and unedited, exactly as each API returned them: Mureka two songs per generation as 192 kbps MP3, MiniMax one at 256 kbps, TemPolor one at 48 kHz and roughly 230–320 kbps, and Flow Music an A/B pair as lossless 48 kHz WAV, transcoded to 320 kbps MP3 only so a browser can play it. Flow's lossless originals come straight from the API.&lt;/p&gt;

&lt;p&gt;One thing to expect if you build against TemPolor: a song job reports &lt;code&gt;status_final: true&lt;/code&gt; and &lt;code&gt;COMPLETED&lt;/code&gt; a few seconds &lt;em&gt;before&lt;/em&gt; its file is fetchable, and &lt;a href="https://useapi.net/docs/api-tempolor-v1/get-tempolor-music-download-job_id" rel="noopener noreferrer"&gt;&lt;code&gt;GET music/download/job_id&lt;/code&gt;&lt;/a&gt; answers &lt;code&gt;404&lt;/code&gt; in the gap. Three of our four vocal rounds hit it on the first attempt. Treat that &lt;code&gt;404&lt;/code&gt; as "not yet" and keep polling rather than as a failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1 — Instrumentals
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Round 1: big-band noir
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Big-band noir action theme, around 60 seconds. Walking upright-bass and
baritone-sax groove, snapping rimshot snare, stabbing trumpet-section hits,
vibraphone glints, surf-twang guitar riff over a chromatic minor progression,
roaring full-brass climax with crash cymbals. Retro secret-agent swagger,
punchy analog-style production.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TemPolor i4 — "Generic  Rhythm Tune" · 3:09 · generated in 103 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/tempolor/music/instrumental'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model_instrumental="i4"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="Big-band noir action theme, around 60 seconds. Walking upright-bass and baritone-sax groove, snapping rimshot snare, stabbing trumpet-section hits, vibraphone glints, surf-twang guitar riff over a chromatic minor progression, roaring full-brass climax with crash cymbals. Retro secret-agent swagger, punchy analog-style production."'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-1-big-band-noir" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mureka V9.5 — "Brass Knuckle Boulevard" · 3:19 · generated in 86 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/mureka/music/create-instrumental'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="V9.5"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="Big-band noir action theme, around 60 seconds. Walking upright-bass and baritone-sax groove, snapping rimshot snare, stabbing trumpet-section hits, vibraphone glints, surf-twang guitar riff over a chromatic minor progression, roaring full-brass climax with crash cymbals. Retro secret-agent swagger, punchy analog-style production."'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-1-big-band-noir" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MiniMax Music-3.0 — "Midnight Operative" · 2:51 · generated in 182 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/music/create'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="music-3.0"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="Big-band noir action theme, around 60 seconds. Walking upright-bass and baritone-sax groove, snapping rimshot snare, stabbing trumpet-section hits, vibraphone glints, surf-twang guitar riff over a chromatic minor progression, roaring full-brass climax with crash cymbals. Retro secret-agent swagger, punchy analog-style production."'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'instrumental="true"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-1-big-band-noir" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lyria 3.5 — "Double Cross" · 2:52 · generated in 47 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/flowmusic/music'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="lyria-3.5"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'instrumental="true"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="Big-band noir action theme, around 60 seconds. Walking upright-bass and baritone-sax groove, snapping rimshot snare, stabbing trumpet-section hits, vibraphone glints, surf-twang guitar riff over a chromatic minor progression, roaring full-brass climax with crash cymbals. Retro secret-agent swagger, punchy analog-style production."'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-1-big-band-noir" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The July versions of this brief are on &lt;a href="https://useapi.net/docs/articles/ai-music-api-comparison#round-1-big-band-noir" rel="noopener noreferrer"&gt;the previous page&lt;/a&gt; if you want them back to back.&lt;/p&gt;

&lt;h3&gt;
  
  
  Round 2: liquid drum and bass
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Liquid drum and bass instrumental, around 60 seconds. Fast rolling breakbeats
at 174 BPM, deep warm sub-bass, lush atmospheric pads, delicate piano motif,
airy wordless vocal-chop textures, smooth builds into a euphoric flowing drop.
Silky, melodic, late-night energy, pristine modern production.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TemPolor i4 — " Generic Rhythm Beat" · 3:30 · generated in 69 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/tempolor/music/instrumental'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model_instrumental="i4"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="Liquid drum and bass instrumental, around 60 seconds. Fast rolling breakbeats at 174 BPM, deep warm sub-bass, lush atmospheric pads, delicate piano motif, airy wordless vocal-chop textures, smooth builds into a euphoric flowing drop. Silky, melodic, late-night energy, pristine modern production."'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-2-liquid-drum-and-bass" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mureka V9.5 — "Piano Afterglow" · 3:22 · generated in 85 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/mureka/music/create-instrumental'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="V9.5"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="Liquid drum and bass instrumental, around 60 seconds. Fast rolling breakbeats at 174 BPM, deep warm sub-bass, lush atmospheric pads, delicate piano motif, airy wordless vocal-chop textures, smooth builds into a euphoric flowing drop. Silky, melodic, late-night energy, pristine modern production."'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'title="Take B - Liquid DnB"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-2-liquid-drum-and-bass" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MiniMax Music-3.0 — "Midnight Flow" · 3:45 · generated in 227 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/music/create'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="music-3.0"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="Liquid drum and bass instrumental, around 60 seconds. Fast rolling breakbeats at 174 BPM, deep warm sub-bass, lush atmospheric pads, delicate piano motif, airy wordless vocal-chop textures, smooth builds into a euphoric flowing drop. Silky, melodic, late-night energy, pristine modern production."'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'instrumental="true"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-2-liquid-drum-and-bass" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lyria 3.5 — "Silken Tides" · &lt;strong&gt;1:06&lt;/strong&gt; · generated in 59 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/flowmusic/music'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="lyria-3.5"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="Liquid drum and bass instrumental, around 60 seconds. Fast rolling breakbeats at 174 BPM, deep warm sub-bass, lush atmospheric pads, delicate piano motif, airy wordless vocal-chop textures, smooth builds into a euphoric flowing drop. Silky, melodic, late-night energy, pristine modern production."'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'instrumental="true"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-2-liquid-drum-and-bass" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;None of the four APIs exposes a duration parameter — every brief asked for "around 60 seconds" in prose. Lyria was the only one that ever took the hint, and only here. Lyria 3 Pro answered this same prompt in July at 2:46.&lt;/p&gt;

&lt;p&gt;TemPolor's instrumental endpoint also does not really name its output. It returned "Generic Rhythm Tune" and "Generic Rhythm Beat" for these two briefs — placeholders rather than titles, and not even tidy ones: the first arrives with a double space in the middle, the second with a leading space. Its song endpoint, on the next four rounds, titles properly. If you file tracks by title, generate the name yourself for instrumentals and trim whatever comes back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2 — Vocals, model writes the lyrics
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Round 3: pop duet
&lt;/h3&gt;

&lt;p&gt;One sentence of direction, and a deliberate capability probe — a duet only works if the model can stage two voices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A playful pop duet between a male and a female singer about texting too late
at night, around 60 seconds, catchy back-and-forth chorus.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TemPolor v4.8 — "Text Me" · 1:51 · generated in 70 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/tempolor/music/song'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model_song="v4.8"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="A playful pop duet between a male and a female singer about texting too late at night, around 60 seconds, catchy back-and-forth chorus."'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-3-pop-duet" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Listen to the first line. TemPolor wrote its own lyrics for this brief, and wrote them with the speaker tagged inline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Verse]
[Male] You sent "you up?" at 1:09
[Female] You said "just one more," then took your time
[Male] I saw your typing, then it slipped away
[Female] I dropped my phone and missed your "hey"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Its singer strips &lt;code&gt;[Verse]&lt;/code&gt; and &lt;code&gt;[Chorus]&lt;/code&gt; as structure, but an inline &lt;code&gt;[Male]&lt;/code&gt; is not a tag it recognises — so it sings the words "male" and "female" as part of the line. The two halves of the same model disagree about its own format. MiniMax met exactly the same problem on this brief and got away with it by writing &lt;code&gt;(Male)&lt;/code&gt; and &lt;code&gt;(Female)&lt;/code&gt; in round brackets, which its singer does drop.&lt;/p&gt;

&lt;p&gt;The lesson generalises past this one model. Role labels inside &lt;code&gt;lyrics&lt;/code&gt; are not a portable API feature, so if you are supplying lyrics yourself and want two voices, check what a given model does with your bracket style before you trust it — or leave the labels out and describe the duet in the style prompt instead.&lt;/p&gt;

&lt;p&gt;Mureka V9.5 — "Are You Still Awake?" · 3:05 · generated in 88 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/mureka/music/create'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="V9.5"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="A playful pop duet between a male and a female singer about texting too late at night, around 60 seconds, catchy back-and-forth chorus."'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-3-pop-duet" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MiniMax Music-3.0 — "Three Little Dots" · 2:31 · generated in 146 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/music/create'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="music-3.0"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="A playful pop duet between a male and a female singer about texting too late at night, around 60 seconds, catchy back-and-forth chorus."'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-3-pop-duet" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MiniMax named it after the typing indicator, and its &lt;code&gt;(Male)&lt;/code&gt; / &lt;code&gt;(Female)&lt;/code&gt; tags stayed out of the vocal.&lt;/p&gt;

&lt;p&gt;Lyria 3.5 — "You Go First" · 1:59 · generated in 74 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/flowmusic/music'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="lyria-3.5"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="A playful pop duet between a male and a female singer about texting too late at night, around 60 seconds, catchy back-and-forth chorus."'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-3-pop-duet" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lyria wrote its own two-voice call and response, with the answering lines in parentheses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Round 4: Spanish flamenco-pop
&lt;/h3&gt;

&lt;p&gt;The language probe — the prompt is English, the song should not be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A fiery flamenco-pop song in Spanish about summer rain, around 60 seconds,
passionate female vocals.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TemPolor v4.8 — "Lluvia" · 2:58 · generated in 102 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/tempolor/music/song'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model_song="v4.8"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="A fiery flamenco-pop song in Spanish about summer rain, around 60 seconds, passionate female vocals."'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-4-spanish-flamenco-pop" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mureka V9.5 — "Agua de Julio" · 3:32 · generated in 87 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/mureka/music/create'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="V9.5"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="A fiery flamenco-pop song in Spanish about summer rain, around 60 seconds, passionate female vocals."'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-4-spanish-flamenco-pop" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MiniMax Music-3.0 — "Tacones de Lluvia" · 3:07 · generated in 171 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/music/create'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="music-3.0"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="A fiery flamenco-pop song in Spanish about summer rain, around 60 seconds, passionate female vocals."'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-4-spanish-flamenco-pop" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lyria 3.5 — "Lluvia de Verano" · 2:33 · generated in 73 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/flowmusic/music'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="lyria-3.5"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="A fiery flamenco-pop song in Spanish about summer rain, around 60 seconds, passionate female vocals."'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-4-spanish-flamenco-pop" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All four wrote Spanish lyrics from an English prompt, and all four titled the track in Spanish without being asked. TemPolor's v4.8 is documented as covering &lt;a href="https://useapi.net/docs/api-tempolor-v1" rel="noopener noreferrer"&gt;30+ languages&lt;/a&gt;. One Spanish brief does not test thirty of them, but it answered this one in the right language and named it "Lluvia" unprompted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 3 — Vocals, our lyrics and an elaborate style brief
&lt;/h2&gt;

&lt;p&gt;For the final format each model receives the same original lyrics plus a detailed production brief. Mureka takes these through &lt;a href="https://useapi.net/docs/api-mureka-v1/post-mureka-music-create-advanced" rel="noopener noreferrer"&gt;music/create-advanced&lt;/a&gt; (&lt;code&gt;lyrics&lt;/code&gt; + a comma-separated style &lt;code&gt;desc&lt;/code&gt; + &lt;code&gt;vocal_gender&lt;/code&gt;), while MiniMax, Flow Music and TemPolor all take a &lt;code&gt;lyrics&lt;/code&gt; field next to the style prompt, so the same body works on three of the four unchanged.&lt;/p&gt;

&lt;h3&gt;
  
  
  Round 5: deep house
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Verse]
Two shadows in a velvet room
Moving slow to a midnight tune
Say it soft, we do not need more
The bass is talking through the floor

[Chorus]
Keep it low light, low light, hold me near
All we need is the bassline here
Round and round till the morning shows
Low light, low light, do not let go
(do not let go, do not let go)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Deep house at 121 BPM. Rolling sub-bass groove, shuffled hi-hats, warm Rhodes
chord stabs, subtle chopped vocal echoes, smoky intimate female lead vocal,
understated hypnotic late-night club production.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TemPolor v4.8 — "Low Light" · 1:28 · generated in 51 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/tempolor/music/song'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model_song="v4.8"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="Deep house at 121 BPM. Rolling sub-bass groove, shuffled hi-hats, warm Rhodes chord stabs, subtle chopped vocal echoes, smoky intimate female lead vocal, understated hypnotic late-night club production."'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'lyrics="[Verse]
Two shadows in a velvet room
Moving slow to a midnight tune
Say it soft, we do not need more
The bass is talking through the floor

[Chorus]
Keep it low light, low light, hold me near
All we need is the bassline here
Round and round till the morning shows
Low light, low light, do not let go
(do not let go, do not let go)"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-5-deep-house" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mureka V9.5 — "Low Light" · 3:09 · generated in 101 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/mureka/music/create-advanced'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="V9.5"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'lyrics="[Verse]
Two shadows in a velvet room
Moving slow to a midnight tune
Say it soft, we do not need more
The bass is talking through the floor

[Chorus]
Keep it low light, low light, hold me near
All we need is the bassline here
Round and round till the morning shows
Low light, low light, do not let go
(do not let go, do not let go)"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'desc="deep house, late night, smoky, hypnotic, groovy, 121 bpm, female vocals, warm, understated club production"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'vocal_gender="female"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-5-deep-house" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MiniMax Music-3.0 — "Low Light" · 2:47 · generated in 135 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/music/create'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="music-3.0"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="Deep house at 121 BPM. Rolling sub-bass groove, shuffled hi-hats, warm Rhodes chord stabs, subtle chopped vocal echoes, smoky intimate female lead vocal, understated hypnotic late-night club production."'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'lyrics="[Verse]
Two shadows in a velvet room
Moving slow to a midnight tune
Say it soft, we do not need more
The bass is talking through the floor

[Chorus]
Keep it low light, low light, hold me near
All we need is the bassline here
Round and round till the morning shows
Low light, low light, do not let go
(do not let go, do not let go)"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-5-deep-house" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lyria 3.5 — "Velvet Room" · 2:26 · generated in 43 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/flowmusic/music'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="lyria-3.5"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="Deep house at 121 BPM. Rolling sub-bass groove, shuffled hi-hats, warm Rhodes chord stabs, subtle chopped vocal echoes, smoky intimate female lead vocal, understated hypnotic late-night club production."'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'lyrics="[Verse]
Two shadows in a velvet room
Moving slow to a midnight tune
Say it soft, we do not need more
The bass is talking through the floor

[Chorus]
Keep it low light, low light, hold me near
All we need is the bassline here
Round and round till the morning shows
Low light, low light, do not let go
(do not let go, do not let go)"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-5-deep-house" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Round 6: jazzy house duet
&lt;/h3&gt;

&lt;p&gt;The hardest brief of the set — a two-voice arrangement with live-jazz layers over a house groove, voice roles tagged in the lyrics. The tags are a hint, not an API parameter, so listen for who actually trades verses and who flattens it into one singer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Verse 1 - male]
Blue hour settles on the avenue
Trumpet smoke and a table for two
I talk in rhythm, you answer in rhyme
We swing together on borrowed time

[Verse 2 - female]
You bring the thunder of a double bass
I bring the shimmer of a satin dress
Piano is asking what the night is about
We are the answer when the lights go out

[Chorus - both]
Meet me in the blue hour, where the bass goes slow (blue hour, blue hour)
Sax on the corner and the lights burn low (burn low, burn low)
You take the high note, I will hold the ground
Blue hour, blue hour - do not stop the sound
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TemPolor v4.8 — "Blue Hour" · 2:09 · generated in 69 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/tempolor/music/song'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model_song="v4.8"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="Jazzy deep house duet at 120 BPM. Rolling deep-house groove with swung hi-hats, walking upright-bass motif over the sub, smoky muted trumpet and tenor-sax licks answering the vocals, extended jazz piano chords, a male and a female lead trading verses and joining in harmony on the chorus, small backing ensemble echoing the hook, warm vinyl texture, sophisticated late-night club production."'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'lyrics="[Verse 1 - male]
Blue hour settles on the avenue
Trumpet smoke and a table for two
I talk in rhythm, you answer in rhyme
We swing together on borrowed time

[Verse 2 - female]
You bring the thunder of a double bass
I bring the shimmer of a satin dress
Piano is asking what the night is about
We are the answer when the lights go out

[Chorus - both]
Meet me in the blue hour, where the bass goes slow (blue hour, blue hour)
Sax on the corner and the lights burn low (burn low, burn low)
You take the high note, I will hold the ground
Blue hour, blue hour - do not stop the sound"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-6-jazzy-house-duet" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mureka V9.5 — "Blue Hour" · 3:12 · generated in 70 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/mureka/music/create-advanced'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="V9.5"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'lyrics="[Verse 1 - male]
Blue hour settles on the avenue
Trumpet smoke and a table for two
I talk in rhythm, you answer in rhyme
We swing together on borrowed time

[Verse 2 - female]
You bring the thunder of a double bass
I bring the shimmer of a satin dress
Piano is asking what the night is about
We are the answer when the lights go out

[Chorus - both]
Meet me in the blue hour, where the bass goes slow (blue hour, blue hour)
Sax on the corner and the lights burn low (burn low, burn low)
You take the high note, I will hold the ground
Blue hour, blue hour - do not stop the sound"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'desc="jazzy deep house, jazz house, duet, male and female vocals, group backing vocals, muted trumpet, saxophone, upright bass, swung, 120 bpm, late night, warm sophisticated production"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-6-jazzy-house-duet" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MiniMax Music-3.0 — "Blue Hour" · 2:18 · generated in 134 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/minimax/music/create'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="music-3.0"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="Jazzy deep house duet at 120 BPM. Rolling deep-house groove with swung hi-hats, walking upright-bass motif over the sub, smoky muted trumpet and tenor-sax licks answering the vocals, extended jazz piano chords, a male and a female lead trading verses and joining in harmony on the chorus, small backing ensemble echoing the hook, warm vinyl texture, sophisticated late-night club production."'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'lyrics="[Verse 1 - male]
Blue hour settles on the avenue
Trumpet smoke and a table for two
I talk in rhythm, you answer in rhyme
We swing together on borrowed time

[Verse 2 - female]
You bring the thunder of a double bass
I bring the shimmer of a satin dress
Piano is asking what the night is about
We are the answer when the lights go out

[Chorus - both]
Meet me in the blue hour, where the bass goes slow (blue hour, blue hour)
Sax on the corner and the lights burn low (burn low, burn low)
You take the high note, I will hold the ground
Blue hour, blue hour - do not stop the sound"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-6-jazzy-house-duet" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lyria 3.5 — "Blue Hour" · 2:34 · generated in 58 s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://api.useapi.net/v1/flowmusic/music'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer user:12345-…'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'model="lyria-3.5"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'prompt="Jazzy deep house duet at 120 BPM. Rolling deep-house groove with swung hi-hats, walking upright-bass motif over the sub, smoky muted trumpet and tenor-sax licks answering the vocals, extended jazz piano chords, a male and a female lead trading verses and joining in harmony on the chorus, small backing ensemble echoing the hook, warm vinyl texture, sophisticated late-night club production."'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'lyrics="[Verse 1 - male]
Blue hour settles on the avenue
Trumpet smoke and a table for two
I talk in rhythm, you answer in rhyme
We swing together on borrowed time

[Verse 2 - female]
You bring the thunder of a double bass
I bring the shimmer of a satin dress
Piano is asking what the night is about
We are the answer when the lights go out

[Chorus - both]
Meet me in the blue hour, where the bass goes slow (blue hour, blue hour)
Sax on the corner and the lights burn low (burn low, burn low)
You take the high note, I will hold the ground
Blue hour, blue hour - do not stop the sound"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎧 &lt;a href="https://useapi.net/docs/articles/ai-music-flagships-compared#round-6-jazzy-house-duet" rel="noopener noreferrer"&gt;Play on useapi.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the lyrics supplied, all four took the title from the chorus hook. Note that this round's role labels sit inside the section headers — &lt;code&gt;[Verse 1 - male]&lt;/code&gt; — rather than on their own at the head of a line, which is the form models treat as structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What does a track cost through useapi.net?&lt;/strong&gt; On three of the four, about a cent: &lt;a href="https://useapi.net/docs/api-minimax-v1/post-minimax-music-create" rel="noopener noreferrer"&gt;MiniMax&lt;/a&gt; $0.010 a track, Lyria through &lt;a href="https://useapi.net/docs/api-flowmusic-v1" rel="noopener noreferrer"&gt;Flow Music&lt;/a&gt; $0.011, and &lt;a href="https://useapi.net/docs/api-mureka-v1" rel="noopener noreferrer"&gt;Mureka&lt;/a&gt; $0.0135, each on that service's highest-volume monthly plan. &lt;a href="https://useapi.net/docs/api-tempolor-v1" rel="noopener noreferrer"&gt;TemPolor&lt;/a&gt; has no per-track rate — its Ultra plan is a flat $30 a month for unlimited generations, so the more you generate the less each track costs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which one is cheapest depends on volume, then?&lt;/strong&gt; Yes. Like for like — the same TemPolor model on its own API at &lt;a href="https://platform.tempolor.com/docs/6665893m0" rel="noopener noreferrer"&gt;$0.04 a call&lt;/a&gt; — the flat $30 plan breaks even at 750 tracks a month and wins above it. Because TemPolor's credits cost the same at every package size, that break-even does not move as you scale up. Against the other services here, $30 buys roughly 2,200 tracks at Mureka's rate or 3,000 at MiniMax's. Add useapi.net's flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; once, whichever you pick, and nothing per generation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is it cheaper than the official APIs?&lt;/strong&gt; Because you bring your own account. useapi.net exposes the consumer subscription you already pay for as a REST API, so generation is billed at subscription rates rather than per-call API rates. useapi.net itself is a flat &lt;a href="https://useapi.net/docs/subscription" rel="noopener noreferrer"&gt;$15/month&lt;/a&gt; for every supported service, with no per-generation surcharge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I run all four from one account?&lt;/strong&gt; Yes. One useapi.net token reaches &lt;a href="https://useapi.net/docs/api-tempolor-v1" rel="noopener noreferrer"&gt;TemPolor&lt;/a&gt;, &lt;a href="https://useapi.net/docs/api-mureka-v1" rel="noopener noreferrer"&gt;Mureka&lt;/a&gt;, &lt;a href="https://useapi.net/docs/api-minimax-v1" rel="noopener noreferrer"&gt;MiniMax&lt;/a&gt; and &lt;a href="https://useapi.net/docs/api-flowmusic-v1" rel="noopener noreferrer"&gt;Flow Music&lt;/a&gt; — every call in this article was made with a single token — plus every other service we support. You still hold your own account with each service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I pick TemPolor's newest models?&lt;/strong&gt; They are already the defaults: &lt;code&gt;v4.8&lt;/code&gt; on &lt;a href="https://useapi.net/docs/api-tempolor-v1/post-tempolor-music-song" rel="noopener noreferrer"&gt;POST music/song&lt;/a&gt; via &lt;code&gt;model_song&lt;/code&gt;, and &lt;code&gt;i4&lt;/code&gt; on &lt;a href="https://useapi.net/docs/api-tempolor-v1/post-tempolor-music-instrumental" rel="noopener noreferrer"&gt;POST music/instrumental&lt;/a&gt; via &lt;code&gt;model_instrumental&lt;/code&gt;. Older model names are still accepted and routed to the new ones, so you cannot accidentally stay on an old model — but pass the parameter explicitly if you want your code to state which model produced a track.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does TemPolor have two endpoints when the others have one?&lt;/strong&gt; Because vocals and instrumentals are different models there — &lt;code&gt;v4.8&lt;/code&gt; and &lt;code&gt;i4&lt;/code&gt;. Pick the endpoint by whether you want singing, not by a flag. The other three take an &lt;code&gt;instrumental&lt;/code&gt; parameter on a single endpoint instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I pick Lyria 3.5 rather than 3 Pro?&lt;/strong&gt; Pass &lt;code&gt;model: "lyria-3.5"&lt;/code&gt; on &lt;a href="https://useapi.net/docs/api-flowmusic-v1/post-flowmusic-music" rel="noopener noreferrer"&gt;POST /music&lt;/a&gt;. &lt;code&gt;lyria-3-pro&lt;/code&gt; remains the default, so omitting the parameter renders the older model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do any of these APIs let me set the track length?&lt;/strong&gt; No. None of the four exposes a duration parameter. The amount of &lt;code&gt;lyrics&lt;/code&gt; you supply is the only lever — more words generally means a longer song.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I get more than one track per call?&lt;/strong&gt; On MiniMax, yes — &lt;code&gt;quantity&lt;/code&gt; up to 3, billed as three songs. Mureka returns two songs per generation and Flow Music an A/B pair, both included in the one generation. TemPolor returned one track per call throughout this test, and allows up to ten generations running at once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I put role labels like &lt;code&gt;[Male]&lt;/code&gt; in the lyrics I send?&lt;/strong&gt; You can send them, but no API here treats them as a parameter, and what happens next differs per model — TemPolor sings inline &lt;code&gt;[Male]&lt;/code&gt; out loud, MiniMax drops &lt;code&gt;(Male)&lt;/code&gt;. Describe the duet in the style prompt and test your bracket style before relying on it. See round 3.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>music</category>
      <category>machinelearning</category>
    </item>
  </channel>
</rss>
