<?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: vancine-fan</title>
    <description>The latest articles on DEV Community by vancine-fan (@vancine-fan).</description>
    <link>https://dev.to/vancine-fan</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%2F4033382%2Fbbc76161-37bc-41e8-bc1e-015b14057418.png</url>
      <title>DEV Community: vancine-fan</title>
      <link>https://dev.to/vancine-fan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vancine-fan"/>
    <language>en</language>
    <item>
      <title>Use Vancine Models in Pi Without Maintaining models.json</title>
      <dc:creator>vancine-fan</dc:creator>
      <pubDate>Mon, 31 Aug 2026 15:36:13 +0000</pubDate>
      <link>https://dev.to/vancine-fan/use-vancine-models-in-pi-without-maintaining-modelsjson-43cl</link>
      <guid>https://dev.to/vancine-fan/use-vancine-models-in-pi-without-maintaining-modelsjson-43cl</guid>
      <description>&lt;p&gt;Vancine is now available in &lt;a href="https://github.com/earendil-works/pi" rel="noopener noreferrer"&gt;Pi&lt;/a&gt; through the community extension &lt;code&gt;pi-provider-vancine&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pi &lt;span class="nb"&gt;install &lt;/span&gt;npm:pi-provider-vancine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart Pi after installation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Log in
&lt;/h2&gt;

&lt;p&gt;Inside Pi, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Choose &lt;strong&gt;Vancine&lt;/strong&gt;, then paste your own Vancine API key into Pi's secret prompt. The extension uses Pi's credential store and does not create a separate credential file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose a model
&lt;/h2&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Select a model under the &lt;strong&gt;Vancine&lt;/strong&gt; provider and start using it. You do not need to create or maintain &lt;code&gt;~/.pi/agent/models.json&lt;/code&gt; for this setup.&lt;/p&gt;

&lt;p&gt;The extension loads compatible Chat Completions models from Vancine's dynamic catalog. It caches and revalidates the catalog, so this is not a claim that every startup fetch is realtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pi.dev/packages/pi-provider-vancine" rel="noopener noreferrer"&gt;Pi Package Catalog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/pi-provider-vancine" rel="noopener noreferrer"&gt;npm package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/fx247562340/vancine-pi-provider" rel="noopener noreferrer"&gt;GitHub source&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vancine.com/docs/agents?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=pi_provider_launch#agents-pi" rel="noopener noreferrer"&gt;Vancine setup guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;pi-provider-vancine&lt;/code&gt; is a community extension published and maintained by Vancine. It is not an official Pi or Earendil Works extension, partnership, certification, or endorsement.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>opensource</category>
      <category>agents</category>
    </item>
    <item>
      <title>One Endpoint, Four Coding Models: A Practical Switching Workflow</title>
      <dc:creator>vancine-fan</dc:creator>
      <pubDate>Sun, 30 Aug 2026 16:52:20 +0000</pubDate>
      <link>https://dev.to/vancine-fan/one-endpoint-four-coding-models-a-practical-switching-workflow-58je</link>
      <guid>https://dev.to/vancine-fan/one-endpoint-four-coding-models-a-practical-switching-workflow-58je</guid>
      <description>&lt;p&gt;Disclosure: I work on Vancine, the API platform used in the examples below. This article was prepared with AI assistance and reviewed against the live product documentation.&lt;/p&gt;

&lt;p&gt;Coding agents do not always need the same model.&lt;/p&gt;

&lt;p&gt;One task may benefit from an experimental vision-capable model. Another may need a lightweight flash model for a fast edit-test loop. The integration problem is that evaluating several models often means managing different endpoints, credentials, and request formats.&lt;/p&gt;

&lt;p&gt;An OpenAI-compatible endpoint makes the comparison simpler: keep the client configuration fixed and change only the &lt;code&gt;model&lt;/code&gt; field.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four model IDs
&lt;/h2&gt;

&lt;p&gt;This workflow uses four exact model IDs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;hy4-preview&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;deepseek-v4-flash-vision-exp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;glm-5.3-flash&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;qwen3.8-flash&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They are available through the same base URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://vancine.com/v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Current prices and catalog metadata can change, so I am deliberately not freezing them into this article. The &lt;a href="https://vancine.com/guides/fast-coding-models?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=fast_coding_models_guide&amp;amp;utm_content=article" rel="noopener noreferrer"&gt;live comparison page&lt;/a&gt; reads them from the pricing API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Send the first request
&lt;/h2&gt;

&lt;p&gt;Store the API key in an environment variable:&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;VANCINE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-api-key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then send a standard Chat Completions request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://vancine.com/v1/chat/completions &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;$VANCINE_API_KEY&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": "glm-5.3-flash",
    "messages": [
      {
        "role": "user",
        "content": "Fix this function so the tests pass."
      }
    ]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To try another model, change only this line:&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;"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;"qwen3.8-flash"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The endpoint, authorization header, and message format stay the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I would approach model selection
&lt;/h2&gt;

&lt;p&gt;These are selection hypotheses, not benchmark conclusions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hy4 Preview&lt;/strong&gt; - worth considering when you want early access and can tolerate preview-level changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DeepSeek V4 Flash Vision Exp&lt;/strong&gt; - worth considering for coding workflows that involve screenshots or other visual input.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GLM-5.3 Flash&lt;/strong&gt; - a candidate for flash-class coding-agent loops and one of the models included in Vancine's Pi evaluation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Qwen3.8 Flash&lt;/strong&gt; - another flash-class candidate included in the same Pi evaluation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A useful evaluation loop is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start with one representative task from your real workload.&lt;/li&gt;
&lt;li&gt;Keep the prompt, tool configuration, and acceptance criteria fixed.&lt;/li&gt;
&lt;li&gt;Change only the model ID.&lt;/li&gt;
&lt;li&gt;Record correctness, tool behavior, latency, and total cost separately.&lt;/li&gt;
&lt;li&gt;Repeat with several tasks before choosing a default.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This avoids treating one successful run as a general model ranking.&lt;/p&gt;

&lt;h2&gt;
  
  
  An important evidence boundary
&lt;/h2&gt;

&lt;p&gt;The existing Vancine Pi coding-agent evaluation contains &lt;code&gt;glm-5.3-flash&lt;/code&gt; and &lt;code&gt;qwen3.8-flash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It does &lt;strong&gt;not&lt;/strong&gt; contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;hy4-preview&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;deepseek-v4-flash-vision-exp&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The evaluation contains a different model ID named &lt;code&gt;deepseek-v4-flash&lt;/code&gt;, so its result should not be transferred to the vision-exp model.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://vancine.com/coding-agent-benchmark?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=fast_coding_models_guide&amp;amp;utm_content=benchmark" rel="noopener noreferrer"&gt;benchmark page&lt;/a&gt; should therefore be read as limited evidence from a single controlled task, not as proof that one model is universally faster or better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting a coding-agent client
&lt;/h2&gt;

&lt;p&gt;The same base URL can be used with OpenAI-compatible clients. Vancine currently provides configuration guides for OpenCode, Cline, and Roo Code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vancine.com/docs/agents?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=fast_coding_models_guide&amp;amp;utm_content=docs" rel="noopener noreferrer"&gt;Open the coding-agent integration guides&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are configuration guides, not claims that Vancine is an official provider or partner of those tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  The practical takeaway
&lt;/h2&gt;

&lt;p&gt;The main benefit is not that one model wins every task. It is that model switching becomes cheap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one endpoint;&lt;/li&gt;
&lt;li&gt;one credential;&lt;/li&gt;
&lt;li&gt;one request format;&lt;/li&gt;
&lt;li&gt;four exact model IDs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That makes it easier to evaluate models against your own repository and keep different defaults for different coding workloads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vancine.com/guides/fast-coding-models?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=fast_coding_models_guide&amp;amp;utm_content=article_final" rel="noopener noreferrer"&gt;Compare the four models with live pricing&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>ai</category>
      <category>programming</category>
      <category>api</category>
    </item>
    <item>
      <title>8 Chinese AI models on the same Pi coding-agent task: what we measured</title>
      <dc:creator>vancine-fan</dc:creator>
      <pubDate>Fri, 28 Aug 2026 16:14:44 +0000</pubDate>
      <link>https://dev.to/vancine-fan/8-chinese-ai-models-on-the-same-pi-coding-agent-task-what-we-measured-oin</link>
      <guid>https://dev.to/vancine-fan/8-chinese-ai-models-on-the-same-pi-coding-agent-task-what-we-measured-oin</guid>
      <description>&lt;p&gt;Most model comparisons try to answer a question that is too broad: “Which model is best?” We wanted a smaller, reproducible question instead:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What happens when eight current Chinese AI models receive the same coding task through the same agent?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We used Pi as the coding agent and ran one isolated JavaScript task across these models:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GLM-5.3&lt;/li&gt;
&lt;li&gt;GLM-5.3-Flash&lt;/li&gt;
&lt;li&gt;Kimi K3&lt;/li&gt;
&lt;li&gt;Qwen3.8-Max&lt;/li&gt;
&lt;li&gt;Qwen3.8-Flash&lt;/li&gt;
&lt;li&gt;DeepSeek-V4-Flash&lt;/li&gt;
&lt;li&gt;DeepSeek-V4-Pro&lt;/li&gt;
&lt;li&gt;MiniMax-M3&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Method
&lt;/h2&gt;

&lt;p&gt;Each run started from its own copy of the fixture. The test directory was kept unchanged, the work directory was checked for unexpected files, and raw run evidence was stored separately from the task workspace. The same Pi provider configuration and task contract were used for every model.&lt;/p&gt;

&lt;p&gt;This is deliberately a narrow test. It does not measure architecture work, long-horizon debugging, frontend judgment, or performance on a real production repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we measured
&lt;/h2&gt;

&lt;p&gt;All eight models completed the task successfully. Across the complete run we recorded:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;8/8 passing runs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;45 Pi requests&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;94,502 tokens&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;$0.037618 production-audited billed cost&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The public page includes the model-by-model table, runtime and token measurements, the Pi configuration, methodology notes, and a downloadable JSON file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vancine.com/coding-agent-benchmark?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=pi_benchmark_launch" rel="noopener noreferrer"&gt;View the full benchmark and data&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why publish a small benchmark?
&lt;/h2&gt;

&lt;p&gt;A small benchmark cannot tell you which model is generally better. It can still answer useful operational questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Can every model finish the same concrete agent task?&lt;/li&gt;
&lt;li&gt;How many agent requests does the run take?&lt;/li&gt;
&lt;li&gt;How many tokens are consumed?&lt;/li&gt;
&lt;li&gt;Does the billed amount match the evidence in production logs?&lt;/li&gt;
&lt;li&gt;Can someone else inspect the setup rather than trusting a screenshot?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For this task, the answer to the first question was yes for all eight models. The differences are in the detailed run data, not a winner label.&lt;/p&gt;

&lt;h2&gt;
  
  
  A note on cost
&lt;/h2&gt;

&lt;p&gt;The total above is the audited amount recorded for these eight runs, not a forecast for arbitrary coding work. Agent cost depends heavily on task length, retries, context growth, and tool behavior. A real repository can be much more expensive than this small fixture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproducing it
&lt;/h2&gt;

&lt;p&gt;The benchmark page includes the Pi setup and downloadable structured results. If you repeat it, keep the task, tests, agent version, model IDs, timeout, and evidence rules fixed. Otherwise you are comparing different experiments.&lt;/p&gt;

&lt;p&gt;Disclosure: I operate Vancine, the OpenAI-compatible API used for these runs. The page is published as product evidence, and the result should not be read as a general model ranking.&lt;/p&gt;

&lt;p&gt;I would especially value feedback on the harness and on what the next coding-agent task should test.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>api</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I wanted a smaller OpenRouter catalog for Chinese models, so I built one</title>
      <dc:creator>vancine-fan</dc:creator>
      <pubDate>Thu, 27 Aug 2026 13:05:34 +0000</pubDate>
      <link>https://dev.to/vancine-fan/i-wanted-a-smaller-openrouter-catalog-for-chinese-models-so-i-built-one-24op</link>
      <guid>https://dev.to/vancine-fan/i-wanted-a-smaller-openrouter-catalog-for-chinese-models-so-i-built-one-24op</guid>
      <description>&lt;p&gt;OpenRouter is useful. I still use it when I need broad model coverage.&lt;/p&gt;

&lt;p&gt;But for one part of my work, that broad catalog became friction. I mainly wanted the current flagship models from Qwen, Kimi, GLM, MiniMax, and DeepSeek. I kept sorting through old versions, free routes, provider variants, and model IDs.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://vancine.com/openrouter-alternative?utm_source=devto&amp;amp;utm_medium=content&amp;amp;utm_campaign=openrouter_launch&amp;amp;utm_content=migration_guide" rel="noopener noreferrer"&gt;Vancine&lt;/a&gt;, a smaller OpenAI-compatible API focused on current Chinese models.&lt;/p&gt;

&lt;p&gt;Disclosure: I run Vancine. This is a product post, not an independent comparison. English is not my first language, and I used an AI writing assistant to edit the wording.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;Vancine uses one API key, one balance, and one OpenAI-compatible endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://vancine.com/v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The catalog is intentionally small. When a Chinese provider replaces a flagship model, I update the catalog and retire the older listing instead of keeping every generation around.&lt;/p&gt;

&lt;p&gt;The same account also reaches Chinese image, video, audio, and 3D models. I started with text and coding workloads, but media access has become useful for people who do not want separate accounts with several Chinese providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The price comparison
&lt;/h2&gt;

&lt;p&gt;These are the four exact paid listings I compared on August 27, 2026. Prices are USD per 1M tokens.&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;Vancine input / output&lt;/th&gt;
&lt;th&gt;OpenRouter input / output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;qwen3.8-max&lt;/td&gt;
&lt;td&gt;$1.60 / $4.80&lt;/td&gt;
&lt;td&gt;$2.00 / $6.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;kimi-k3&lt;/td&gt;
&lt;td&gt;$2.40 / $12.00&lt;/td&gt;
&lt;td&gt;$3.00 / $15.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;glm-5.3&lt;/td&gt;
&lt;td&gt;$1.12 / $3.52&lt;/td&gt;
&lt;td&gt;$1.40 / $4.40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MiniMax-M3&lt;/td&gt;
&lt;td&gt;$0.24 / $0.96&lt;/td&gt;
&lt;td&gt;$0.30 / $1.20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is 20% lower for these four listings. Free variants, promotional routes, and temporary provider discounts are excluded. I am not claiming that every model is cheaper.&lt;/p&gt;

&lt;p&gt;The live pricing page is the source of truth because provider prices can change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving an existing OpenAI client
&lt;/h2&gt;

&lt;p&gt;The change is small:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;VANCINE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://vancine.com/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;qwen3.8-max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Explain this failing test.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&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;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenRouter model IDs include a provider prefix. Vancine IDs do not, so &lt;code&gt;qwen/qwen3.8-max&lt;/code&gt; becomes &lt;code&gt;qwen3.8-max&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Chat completions and streaming follow the OpenAI-compatible format. Provider-specific errors may differ, so I would still test the exact tool and model combination before moving production traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I have actually tested
&lt;/h2&gt;

&lt;p&gt;I have run Pi against Kimi K3 through Vancine on a real edit-and-test coding task. It completed the tool loop and left the tests passing.&lt;/p&gt;

&lt;p&gt;I have not independently verified every coding agent. I would rather publish one reproducible result than put a long compatibility matrix on the page and pretend every green check means the same thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  When OpenRouter is still the better choice
&lt;/h2&gt;

&lt;p&gt;If you need Claude, GPT, Gemini, Llama, and hundreds of provider routes behind one account, OpenRouter is the obvious fit. Vancine is for the narrower case: you mainly want current Chinese frontier models, a short catalog, and lower prices on the compared paid listings.&lt;/p&gt;

&lt;p&gt;I am still deciding what a smaller provider needs to publish before developers will trust it with production traffic. Uptime history? Rate-limit details? Version pinning? Better cost exports?&lt;/p&gt;

&lt;p&gt;If you work with these models, I would like to hear which one matters most.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>python</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Kimi K3 in OpenCode: What One Finished Coding Task Actually Cost</title>
      <dc:creator>vancine-fan</dc:creator>
      <pubDate>Tue, 21 Jul 2026 00:36:29 +0000</pubDate>
      <link>https://dev.to/vancine-fan/kimi-k3-in-opencode-what-one-finished-coding-task-actually-cost-38m1</link>
      <guid>https://dev.to/vancine-fan/kimi-k3-in-opencode-what-one-finished-coding-task-actually-cost-38m1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Update — July 23, 2026: I published a fuller reproducible guide covering the Starter, OpenCode configuration, evidence JSON, measured run, and its limitations:&lt;br&gt;
&lt;a href="https://xingod.me/journal/kimi-k3-opencode-starter?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=kimi_k3_opencode_starter&amp;amp;utm_content=expanded_guide" rel="noopener noreferrer"&gt;Kimi K3 in OpenCode: A Reproducible Starter and One Measured Agent Run&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kimi K3 launched with impressive benchmark results—and a lot of debate about its price.&lt;/p&gt;

&lt;p&gt;For developers using coding agents, however, price per million tokens is only part of the story.&lt;/p&gt;

&lt;p&gt;A more useful question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How much does it cost to finish an actual coding task—with file reads, edits, tool calls, and passing tests?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We ran one controlled Kimi K3 coding task through OpenCode and recorded the result.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; I work on Vancine, a third-party API aggregation platform. Vancine is not Moonshot AI and is not an official Kimi service. The cost below is measured Vancine usage for one specific run, not official Kimi pricing or a fixed-price promise.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The task
&lt;/h2&gt;

&lt;p&gt;The agent received a small repository containing a faulty leap-year implementation.&lt;/p&gt;

&lt;p&gt;It had to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;inspect the source code and failing tests;&lt;/li&gt;
&lt;li&gt;identify the bug;&lt;/li&gt;
&lt;li&gt;edit the source file;&lt;/li&gt;
&lt;li&gt;leave the test file unchanged;&lt;/li&gt;
&lt;li&gt;run the actual test suite;&lt;/li&gt;
&lt;li&gt;finish with all tests passing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The run used &lt;strong&gt;OpenCode v1.18.3&lt;/strong&gt; inside an isolated Docker Linux ARM64 environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Completed model steps&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Completed tool calls&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File reads&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Source edits&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shell commands&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failed tool calls&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total tokens&lt;/td&gt;
&lt;td&gt;28,707&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duration&lt;/td&gt;
&lt;td&gt;84.3 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tests passed&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Measured Vancine usage&lt;/td&gt;
&lt;td&gt;$0.19&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The 28,707 total tokens included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3,746 input tokens;&lt;/li&gt;
&lt;li&gt;1,019 output tokens;&lt;/li&gt;
&lt;li&gt;902 reasoning tokens;&lt;/li&gt;
&lt;li&gt;23,040 cached-read tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The run completed without recorded HTTP 429 responses, HTTP 5xx responses, provider errors, or permission failures.&lt;/p&gt;

&lt;p&gt;You can inspect the sanitized machine-readable evidence here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/VancineAI/kimi-k3-api-starter/blob/main/results/opencode-agent.verified.json" rel="noopener noreferrer"&gt;Kimi K3 OpenCode verification evidence&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What this result proves
&lt;/h2&gt;

&lt;p&gt;For this specific task, Kimi K3 successfully:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;inspected multiple files;&lt;/li&gt;
&lt;li&gt;understood the failing behavior;&lt;/li&gt;
&lt;li&gt;made the required source change;&lt;/li&gt;
&lt;li&gt;invoked the test command;&lt;/li&gt;
&lt;li&gt;reached a passing solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The source file was modified, the test file remained unchanged, and no unexpected files were created.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does not prove
&lt;/h2&gt;

&lt;p&gt;This is one controlled task—not a general benchmark.&lt;/p&gt;

&lt;p&gt;It does not prove that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;every Kimi K3 task will cost $0.19;&lt;/li&gt;
&lt;li&gt;every repository will complete in six steps;&lt;/li&gt;
&lt;li&gt;Kimi K3 is universally better than Claude, GPT, GLM, or other models;&lt;/li&gt;
&lt;li&gt;every OpenCode version or coding-agent client behaves identically;&lt;/li&gt;
&lt;li&gt;$1 of starting credit will complete a particular agent task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cline and Roo Code configuration examples are included in the starter repository, but they have not yet been independently live-verified. Only the recorded OpenCode v1.18.3 task is verified.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why cost per finished task matters
&lt;/h2&gt;

&lt;p&gt;Coding agents rarely make one isolated API request.&lt;/p&gt;

&lt;p&gt;A normal agent loop may:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;read multiple files;&lt;/li&gt;
&lt;li&gt;build and rebuild context;&lt;/li&gt;
&lt;li&gt;reason about the change;&lt;/li&gt;
&lt;li&gt;call tools;&lt;/li&gt;
&lt;li&gt;edit code;&lt;/li&gt;
&lt;li&gt;run tests;&lt;/li&gt;
&lt;li&gt;inspect failures;&lt;/li&gt;
&lt;li&gt;retry until the task is complete.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because of that, the cheapest model per token is not necessarily the cheapest model per finished task.&lt;/p&gt;

&lt;p&gt;A useful coding-model evaluation should report:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;whether the task was completed;&lt;/li&gt;
&lt;li&gt;whether the tests passed;&lt;/li&gt;
&lt;li&gt;model steps;&lt;/li&gt;
&lt;li&gt;successful and failed tool calls;&lt;/li&gt;
&lt;li&gt;total tokens;&lt;/li&gt;
&lt;li&gt;elapsed time;&lt;/li&gt;
&lt;li&gt;final billed usage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One task is not a leaderboard, but it is a more concrete starting point than benchmark scores or token prices alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Kimi K3 with OpenCode
&lt;/h2&gt;

&lt;p&gt;Vancine exposes the model alias &lt;code&gt;kimi-k3&lt;/code&gt; through an OpenAI-compatible API.&lt;/p&gt;

&lt;p&gt;A minimal OpenCode provider configuration looks like this:&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;"$schema"&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://opencode.ai/config.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&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;"vancine"&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;"npm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@ai-sdk/openai-compatible"&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;"Vancine"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&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;"baseURL"&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://vancine.com/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"apiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{env:VANCINE_API_KEY}"&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;"models"&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;"kimi-k3"&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;"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;"Kimi K3"&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;p&gt;Keep the API key in an environment variable:&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;VANCINE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-api-key"&lt;/span&gt;
opencode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then select:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vancine/kimi-k3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not commit real API keys to source control or paste them into shared configuration files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Direct API request
&lt;/h2&gt;

&lt;p&gt;The same model can be called through the OpenAI-compatible Chat Completions endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://vancine.com/v1/chat/completions &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;$VANCINE_API_KEY&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": "kimi-k3",
    "messages": [
      {
        "role": "user",
        "content": "Review this function and identify the bug."
      }
    ]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Vancine model alias is &lt;code&gt;kimi-k3&lt;/code&gt;. Kimi’s first-party documentation uses &lt;code&gt;k3&lt;/code&gt; for the official Kimi Code model ID, so always use the identifier required by the provider you are connecting to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduce the setup
&lt;/h2&gt;

&lt;p&gt;The public starter repository includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenCode configuration;&lt;/li&gt;
&lt;li&gt;Cline and Roo Code configuration examples;&lt;/li&gt;
&lt;li&gt;cURL, Python, and Node.js requests;&lt;/li&gt;
&lt;li&gt;offline configuration validation;&lt;/li&gt;
&lt;li&gt;sanitized OpenCode evidence;&lt;/li&gt;
&lt;li&gt;credential-safety guidance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/VancineAI/kimi-k3-api-starter" rel="noopener noreferrer"&gt;View the Kimi K3 API Starter on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also open the complete quick start here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vancine.com/kimi-k3-api?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=kimi_k3_cost_to_solution&amp;amp;utm_content=opencode_case_study" rel="noopener noreferrer"&gt;Kimi K3 API for coding agents&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;New Vancine accounts currently receive &lt;strong&gt;$1 in starting credit&lt;/strong&gt;, with no credit card required.&lt;/p&gt;

&lt;p&gt;Usage depends on the model, prompt size, context, tool loop, and number of requests. The starting credit does not guarantee that any particular coding task will complete within that amount.&lt;/p&gt;

&lt;p&gt;The broader takeaway is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For coding agents, measure the cost of reaching a tested solution—not just the price of generating a token.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>opencode</category>
      <category>kimik3</category>
    </item>
    <item>
      <title>Seedance + n8n: Build a Bounded Async Polling Workflow</title>
      <dc:creator>vancine-fan</dc:creator>
      <pubDate>Fri, 17 Jul 2026 17:43:52 +0000</pubDate>
      <link>https://dev.to/vancine-fan/seedance-n8n-build-a-bounded-async-polling-workflow-374d</link>
      <guid>https://dev.to/vancine-fan/seedance-n8n-build-a-bounded-async-polling-workflow-374d</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article was originally published on &lt;a href="https://xingod.me/journal/seedance-n8n-bounded-async-polling" rel="noopener noreferrer"&gt;XINGOD.ME&lt;/a&gt;. This DEV edition keeps the implementation complete while adapting the explanation for automation builders.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Video generation APIs are asynchronous by design. The first request does not return a finished MP4. It returns a task identifier that you must preserve while the provider queues, processes, and eventually completes—or fails—the job.&lt;/p&gt;

&lt;p&gt;That changes the automation problem. A production-ready workflow must do more than “poll until done.” It must:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;submit exactly once;&lt;/li&gt;
&lt;li&gt;preserve &lt;code&gt;task_id&lt;/code&gt; and loop configuration across every node;&lt;/li&gt;
&lt;li&gt;wait between status requests;&lt;/li&gt;
&lt;li&gt;stop immediately on success or failure;&lt;/li&gt;
&lt;li&gt;enforce a hard polling limit; and&lt;/li&gt;
&lt;li&gt;make the final timeout observable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this tutorial, the default polling budget is &lt;strong&gt;5 seconds × 120 polls&lt;/strong&gt;, or roughly &lt;strong&gt;10 minutes&lt;/strong&gt;. Both values are configurable, but the loop always remains bounded.&lt;/p&gt;

&lt;h2&gt;
  
  
  The state machine
&lt;/h2&gt;

&lt;p&gt;At a high level, the workflow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;submit
  → save task_id and loop state
  → wait
  → poll
  → merge the API response with carried state
  → completed / failed / timeout / continue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tested n8n workflow uses these concrete nodes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;manualTrigger
  → setFields
  → submitTask
  → saveTaskId
  → waitInterval
       ├─→ pollTask ─────┐
       └─→ carryState ───┴─→ Merge (append)
                               → mergeState
                               → ifCompleted
                                  ├─ true  → outputResult
                                  └─ false → ifFailed
                                               ├─ true  → failNode
                                               └─ false → ifTimeout
                                                            ├─ true  → timeoutFail
                                                            └─ false → continuePolling
                                                                          → waitInterval
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The branching around &lt;code&gt;pollTask&lt;/code&gt; and &lt;code&gt;carryState&lt;/code&gt; is the critical part. An n8n HTTP Request node replaces the current item with the HTTP response. Without a parallel state branch, the response can erase the loop counter and configuration needed for the next iteration.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Configure the request and polling budget
&lt;/h2&gt;

&lt;p&gt;Start with an Edit Fields node named &lt;code&gt;setFields&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model = Doubao-Seedance-1.5-pro
prompt = A timelapse of a flower blooming at sunrise
size = 1280x720
base_url = https://vancine.com
intervalSeconds = 5
maxPolls = 120
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;intervalSeconds&lt;/code&gt; and &lt;code&gt;maxPolls&lt;/code&gt; are configuration, not hidden constants. A different workflow may need a shorter interval or a different deadline, but it should still have an explicit upper bound.&lt;/p&gt;

&lt;p&gt;Store authentication in n8n Credentials, for example with a reusable Header Auth credential. Never paste a real API key into exported workflow JSON, screenshots, or code examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Submit once and normalize &lt;code&gt;task_id&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Configure &lt;code&gt;submitTask&lt;/code&gt; as an HTTP Request node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST https://vancine.com/v1/video/generations
Content-Type: application/json
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Send the configured model, prompt, and size in the JSON body. The exact supported models and request fields can change, so check the live documentation before using the workflow in production.&lt;/p&gt;

&lt;p&gt;Immediately after submission, &lt;code&gt;saveTaskId&lt;/code&gt; creates the loop envelope:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;task_id = {{ $json.task_id || $json.id || ($json.data &amp;amp;&amp;amp; $json.data.task_id) || ($json.data &amp;amp;&amp;amp; $json.data.id) }}
base_url = {{ $('setFields').first().json.base_url || 'https://vancine.com' }}
intervalSeconds = {{ $('setFields').first().json.intervalSeconds || 5 }}
maxPolls = {{ $('setFields').first().json.maxPolls || 120 }}
poll_index = 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The submit response is a receipt. &lt;code&gt;task_id&lt;/code&gt; is the durable hand-off value for every later status request, error message, and audit record.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Wait, then fork response and state
&lt;/h2&gt;

&lt;p&gt;Connect &lt;code&gt;saveTaskId&lt;/code&gt; to a Wait node named &lt;code&gt;waitInterval&lt;/code&gt;. Its amount is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{{ $json.intervalSeconds || 5 }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the wait, send the same item to two nodes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;pollTask&lt;/code&gt; performs the status request.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;carryState&lt;/code&gt; retains the state required by the next iteration.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;pollTask&lt;/code&gt; calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET {{$json.base_url}}/v1/video/generations/{{$json.task_id}}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;carryState&lt;/code&gt; outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;task_id = {{ $json.task_id }}
poll_index = {{ $json.poll_index || 0 }}
maxPolls = {{ $json.maxPolls || 120 }}
intervalSeconds = {{ $json.intervalSeconds || 5 }}
base_url = {{ $json.base_url || 'https://vancine.com' }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both branches feed a Merge node configured in &lt;strong&gt;append&lt;/strong&gt; mode. The resulting item list contains the API response and the carried loop state.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Merge locally and increment exactly once
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;mergeState&lt;/code&gt; Code node makes &lt;strong&gt;no network request&lt;/strong&gt;. It identifies the two appended items, merges them, and increments the counter from the carried item exactly once:&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;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;items&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;carried&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;poll_index&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&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;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="nx"&gt;items&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pollIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carried&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;poll_index&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;taskId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;task_id&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="nx"&gt;carried&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;video_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;taskId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;poll_index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pollIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;maxPolls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;carried&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxPolls&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;intervalSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;carried&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intervalSeconds&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;base_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;carried&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;base_url&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://vancine.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;result_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;resultUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important invariant is:&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;pollIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carried&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;poll_index&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The counter comes from the latest carried state, not from the initial state node. This is what allows the workflow to reach &lt;code&gt;maxPolls&lt;/code&gt; and guarantees that a non-terminal task cannot loop forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Route completed, failed, and timeout separately
&lt;/h2&gt;

&lt;p&gt;Run the terminal checks in order.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ifCompleted&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Treat &lt;code&gt;completed&lt;/code&gt; and the legacy value &lt;code&gt;SUCCESS&lt;/code&gt; as success:&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="nx"&gt;$json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;completed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="nx"&gt;$json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SUCCESS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;completed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;$json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SUCCESS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The true branch goes to &lt;code&gt;outputResult&lt;/code&gt;, where you can return or persist &lt;code&gt;result_url&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ifFailed&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The false branch from &lt;code&gt;ifCompleted&lt;/code&gt; reaches &lt;code&gt;ifFailed&lt;/code&gt;. Treat &lt;code&gt;failed&lt;/code&gt; and &lt;code&gt;FAILURE&lt;/code&gt; as terminal errors:&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="nx"&gt;$json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="nx"&gt;$json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FAILURE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;$json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FAILURE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Send the true branch to a Stop And Error node. A failed generation is a business terminal state, not a reason to keep polling.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ifTimeout&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Only a non-terminal, non-failed item reaches &lt;code&gt;ifTimeout&lt;/code&gt;:&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;poll_index&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxPolls&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The true branch stops with a timeout error. The false branch reaches &lt;code&gt;continuePolling&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;continuePolling&lt;/code&gt; copies the &lt;strong&gt;latest&lt;/strong&gt; values back into the loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;task_id
poll_index
maxPolls
intervalSeconds
base_url
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It then reconnects to &lt;code&gt;waitInterval&lt;/code&gt;. With the defaults, the 120th non-terminal response enters the timeout branch instead of starting iteration 121.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Keep transport retries separate from task polling
&lt;/h2&gt;

&lt;p&gt;A task that is still &lt;code&gt;processing&lt;/code&gt; is not the same as an HTTP request that received a transient &lt;code&gt;429&lt;/code&gt; or &lt;code&gt;5xx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Use two separate budgets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a small, explicit retry policy with backoff for transient transport failures;&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;poll_index / maxPolls&lt;/code&gt; budget for valid task-status responses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation prevents network noise from silently changing the business timeout. Also test the following paths independently:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;completed;&lt;/li&gt;
&lt;li&gt;failed;&lt;/li&gt;
&lt;li&gt;timeout;&lt;/li&gt;
&lt;li&gt;missing &lt;code&gt;task_id&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;429&lt;/code&gt; and &lt;code&gt;5xx&lt;/code&gt;; and&lt;/li&gt;
&lt;li&gt;malformed or unknown status values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Log &lt;code&gt;task_id&lt;/code&gt;, &lt;code&gt;poll_index&lt;/code&gt;, the last status, and elapsed time. Never log the Authorization header.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try the tested workflow
&lt;/h2&gt;

&lt;p&gt;The public &lt;a href="https://github.com/VancineAI/seedance-api-starter?utm_source=dev_community&amp;amp;utm_medium=organic_content&amp;amp;utm_campaign=seedance_n8n_bounded_polling&amp;amp;utm_content=starter_kit" rel="noopener noreferrer"&gt;Seedance API Starter Kit&lt;/a&gt; includes the tested n8n workflow plus Node.js, Python, cURL, and Postman examples.&lt;/p&gt;

&lt;p&gt;Additional resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vancine.com/docs?utm_source=dev_community&amp;amp;utm_medium=organic_content&amp;amp;utm_campaign=seedance_n8n_bounded_polling&amp;amp;utm_content=docs#video" rel="noopener noreferrer"&gt;Live API documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.postman.com/vancine-ai/vancine-seedance-api/collection/jej2ty/vancine-seedance?utm_source=dev_community&amp;amp;utm_medium=organic_content&amp;amp;utm_campaign=seedance_n8n_bounded_polling&amp;amp;utm_content=postman" rel="noopener noreferrer"&gt;Postman Collection&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Start with Vancine
&lt;/h2&gt;

&lt;p&gt;New Vancine accounts receive &lt;strong&gt;$1 in free credit&lt;/strong&gt;, with &lt;strong&gt;no credit card required&lt;/strong&gt;. You can &lt;a href="https://vancine.com/register?utm_source=dev_community&amp;amp;utm_medium=organic_content&amp;amp;utm_campaign=seedance_n8n_bounded_polling&amp;amp;utm_content=cta" rel="noopener noreferrer"&gt;create an account here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Credit usage depends on the selected model, inputs, duration, and current pricing. The $1 credit does &lt;strong&gt;not&lt;/strong&gt; guarantee that any specific video generation will complete within that amount.&lt;/p&gt;

&lt;p&gt;Bounded polling is a small architectural choice with a large operational payoff: every execution has an inspectable state, every terminal outcome has an explicit branch, and every loop has a known failure budget.&lt;/p&gt;

</description>
      <category>n8n</category>
      <category>automation</category>
      <category>api</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
