{
  "aboutHtml": "<p>HappyHorse-1.1-I2V is an Alibaba model that starts a video scene from an existing image. The image becomes the first frame, while text can specify what happens next: a character&#39;s movement, changes in the scene and the camera&#39;s direction. It is suited to animating an illustration, a product photograph or a prepared visual concept.</p><p>A text prompt is optional. Without one, the model infers possible motion from the initial image. When a prompt is supplied, the source image determines the composition and the appearance of objects, while the words guide how the scene develops over time.</p><h4>From the first frame to motion</h4><p>Alibaba highlights preservation of character appearance, visual consistency, smooth movement and the combination of visuals with audio. Its stated aims also include stable text and textures. These properties describe the model&#39;s intended capabilities; they do not mean that every pixel is literally preserved in every generated frame.</p><p>This mode uses one initial image. It defines the starting scene rather than providing a set of independent references for a new composition. The ability to specify a separate final frame is not stated for this particular version.</p><p>JPEG, JPG, PNG and WEBP are accepted. Each dimension of the input image must be at least 300 pixels; the permitted aspect ratio ranges from 1:2.5 to 2.5:1, and the file size limit is 20 MB. The output video&#39;s aspect ratio follows the first frame.</p><h4>Video parameters</h4><p>The duration is selected as an integer from 3 to 15 seconds. Available resolution levels are 480P, 720P and 1080P; the output format is MP4 at 24 frames per second. Audio can be generated alongside the video.</p><p>The prompt may be in any language and contain up to 5000 non-Chinese or 2500 Chinese characters. Any excess is truncated, so important actions and motion details should fit within that limit. The same random seed may produce similar videos, but does not guarantee a frame-by-frame match.</p>",
  "aboutText": "HappyHorse-1.1-I2V is an Alibaba model that starts a video scene from an existing image. The image becomes the first frame, while text can specify what happens next: a character's movement, changes in the scene and the camera's direction. It is suited to animating an illustration, a product photograph or a prepared visual concept.\n\nA text prompt is optional. Without one, the model infers possible motion from the initial image. When a prompt is supplied, the source image determines the composition and the appearance of objects, while the words guide how the scene develops over time.\n\n### From the first frame to motion\n\nAlibaba highlights preservation of character appearance, visual consistency, smooth movement and the combination of visuals with audio. Its stated aims also include stable text and textures. These properties describe the model's intended capabilities; they do not mean that every pixel is literally preserved in every generated frame.\n\nThis mode uses one initial image. It defines the starting scene rather than providing a set of independent references for a new composition. The ability to specify a separate final frame is not stated for this particular version.\n\nJPEG, JPG, PNG and WEBP are accepted. Each dimension of the input image must be at least 300 pixels; the permitted aspect ratio ranges from 1:2.5 to 2.5:1, and the file size limit is 20 MB. The output video's aspect ratio follows the first frame.\n\n### Video parameters\n\nThe duration is selected as an integer from 3 to 15 seconds. Available resolution levels are 480P, 720P and 1080P; the output format is MP4 at 24 frames per second. Audio can be generated alongside the video.\n\nThe prompt may be in any language and contain up to 5000 non-Chinese or 2500 Chinese characters. Any excess is truncated, so important actions and motion details should fit within that limit. The same random seed may produce similar videos, but does not guarantee a frame-by-frame match.",
  "editorialOverlay": {
    "copy_fields": null,
    "copy_sha256": null,
    "copy_source": null,
    "html_sha256": "e8adfb803b3334d29d211f59bef2c75e1e048e132d8d72df89864caa44cc334f",
    "module_sha256": "ee9dc1c50b1e6a8fb7fa062030fcb4646b9aaaeb08be513b723a5a92a7290f06",
    "raw_model_unchanged": true,
    "schema": "ailoot-native-model-editorial-v1"
  },
  "locale": "en",
  "methods": [
    {
      "html": "<div class=\"sheet-head\"><span class=\"mav\" aria-hidden=\"true\">Al</span><h2 id=\"sheet-title\">happyhorse-1.1-i2v</h2><button class=\"icon-btn\" type=\"button\" data-close-sheet aria-label=\"Close\">×</button></div><div class=\"idline\"><span>Alibaba /</span><code>happyhorse-1.1-i2v</code><button type=\"button\" id=\"copy-id\">Copy ID</button></div><nav class=\"card-jump-nav\" aria-label=\"Model card sections\"><button type=\"button\" data-card-jump=\"overview\">Overview</button><button type=\"button\" data-card-jump=\"methods\">Inputs &amp; methods</button><button type=\"button\" data-card-jump=\"pricing\">Pricing</button><button type=\"button\" data-card-jump=\"examples\">Examples</button><button type=\"button\" data-card-jump=\"results\">Results</button><button type=\"button\" data-card-jump=\"aliases\">Aliases</button></nav><div class=\"card-method-tabs\" role=\"tablist\" aria-label=\"API methods\"><button type=\"button\" role=\"tab\" tabindex=\"0\" aria-controls=\"card-method-content\" aria-selected=\"true\" id=\"card-method-tab-0\" data-card-method=\"Core|videos|/v1/videos/generations|happyhorse-1.1-i2v\">Video</button></div><div class=\"idline\"><label for=\"card-model-id\">Model ID</label><select class=\"sel\" id=\"card-model-id\" style=\"min-width:0;max-width:100%\"><option value=\"Core|videos|/v1/videos/generations|happyhorse-1.1-i2v\" selected>happyhorse-1.1-i2v</option><option value=\"Core|videos|/v1/videos/generations|happyhorse-i2v\">happyhorse-i2v</option><option value=\"Core|videos|/v1/videos/generations|happyhorse-i2v-latest\">happyhorse-i2v-latest</option></select></div><div id=\"card-method-content\" role=\"tabpanel\" aria-labelledby=\"card-method-tab-0\"><section class=\"card-section\" data-card-section=\"overview\"><h3 tabindex=\"-1\">Overview</h3><p class=\"mdesc-full\">An image-to-video model: the source image provides the first frame, and the prompt guides the subsequent motion. Creates a short video with optional accompanying audio.</p><dl class=\"card-io\" data-card-io><div><dt>Accepted inputs</dt><dd>Text · Images</dd></div><div><dt>Results</dt><dd>Video</dd></div></dl><details class=\"card-about\"><summary>About the model</summary><p class=\"note-s\" data-model-method-boundary>This description covers the model’s capabilities. Available in Ailoot inputs, outputs and options are listed for the selected method below.</p><div class=\"mabout\" id=\"m-about\"><p>HappyHorse-1.1-I2V is an Alibaba model that starts a video scene from an existing image. The image becomes the first frame, while text can specify what happens next: a character&#39;s movement, changes in the scene and the camera&#39;s direction. It is suited to animating an illustration, a product photograph or a prepared visual concept.</p><p>A text prompt is optional. Without one, the model infers possible motion from the initial image. When a prompt is supplied, the source image determines the composition and the appearance of objects, while the words guide how the scene develops over time.</p><h4>From the first frame to motion</h4><p>Alibaba highlights preservation of character appearance, visual consistency, smooth movement and the combination of visuals with audio. Its stated aims also include stable text and textures. These properties describe the model&#39;s intended capabilities; they do not mean that every pixel is literally preserved in every generated frame.</p><p>This mode uses one initial image. It defines the starting scene rather than providing a set of independent references for a new composition. The ability to specify a separate final frame is not stated for this particular version.</p><p>JPEG, JPG, PNG and WEBP are accepted. Each dimension of the input image must be at least 300 pixels; the permitted aspect ratio ranges from 1:2.5 to 2.5:1, and the file size limit is 20 MB. The output video&#39;s aspect ratio follows the first frame.</p><h4>Video parameters</h4><p>The duration is selected as an integer from 3 to 15 seconds. Available resolution levels are 480P, 720P and 1080P; the output format is MP4 at 24 frames per second. Audio can be generated alongside the video.</p><p>The prompt may be in any language and contain up to 5000 non-Chinese or 2500 Chinese characters. Any excess is truncated, so important actions and motion details should fit within that limit. The same random seed may produce similar videos, but does not guarantee a frame-by-frame match.</p></div></details></section><section class=\"card-section\" data-card-section=\"methods\"><h3 tabindex=\"-1\">Available in Ailoot · inputs &amp; methods</h3><details class=\"card-method\" open><summary><b>Ailoot · Video</b> <code>POST /v1/videos/generations</code></summary><dl class=\"method-capabilities\"><div><dt>Input types</dt><dd><code>text</code>, <code>image</code></dd></div><div><dt>Output types</dt><dd><code>video</code></dd></div><div><dt>Output format</dt><dd>mp4</dd></div></dl><div class=\"tw\" data-card-parameters data-typed-parameters><table><thead><tr><th>Field</th><th>Type</th><th>Requirement</th><th>Values &amp; limits</th><th>Default</th></tr></thead><tbody><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">model</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Required</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>happyhorse-1.1-i2v</div></td><td data-cell-label=\"Default\" data-default=\"unspecified\"><span class=\"card-cell-label\">Default</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">prompt</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Optional</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>Minimum length: 1</div></td><td data-cell-label=\"Default\" data-default=\"unspecified\"><span class=\"card-cell-label\">Default</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">duration</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>integer</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Optional</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>Minimum: 3</div><div>Maximum: 15</div><div>Unit: seconds</div></td><td data-cell-label=\"Default\" data-default=\"known\"><span class=\"card-cell-label\">Default</span>5</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">resolution</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Optional</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>480P, 720P, 1080P</div></td><td data-cell-label=\"Default\" data-default=\"known\"><span class=\"card-cell-label\">Default</span>720P</td></tr><tr data-parameter-availability=\"unsupported\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">ratio</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Not supported</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span></td><td data-cell-label=\"Default\" data-default=\"unspecified\"><span class=\"card-cell-label\">Default</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">image_urls</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>https_url|data_image_url[]</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Required</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>Minimum items: 1</div><div>Maximum items: 1</div><div>Maximum decoded bytes: 20,971,520</div><div>MIME types: image/jpeg, image/png, image/webp</div></td><td data-cell-label=\"Default\" data-default=\"unspecified\"><span class=\"card-cell-label\">Default</span>—</td></tr></tbody></table></div><details class=\"card-about\" data-material-combinations><summary>Input material combinations</summary><p class=\"note-s\"><b>first_frame_to_video</b> · Required: image_urls</p></details><details class=\"note-s\" data-method-contract><summary>Method parameters and lifecycle</summary><div class=\"tw\" data-card-table=\"contract\"><table><thead><tr><th>Parameter</th><th>Contract</th></tr></thead><tbody><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>content_type</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>application/json</td></tr><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>required</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>model, image_urls</td></tr><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>material_types</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>text, image</td></tr><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>optional</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>duration, resolution, ratio, prompt</td></tr><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>duration_integer_range</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>3, 15</td></tr><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>default_duration</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>5</td></tr><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>resolution</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>480P, 720P, 1080P</td></tr><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>default_resolution</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>720P</td></tr><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>ratio</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span></td></tr><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>ratio_must_omit</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>true</td></tr><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>image_urls</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>{&quot;min_count&quot;:1,&quot;max_count&quot;:1,&quot;schemes&quot;:[&quot;https&quot;,&quot;data raster base64&quot;],&quot;max_data_image_bytes&quot;:20971520}</td></tr></tbody></table></div><p>Lifecycle: <code>submit_once_poll_original</code></p><p class=\"note-s\"><code>GET /v1/videos/{request_id}</code></p><p class=\"note-s\"><code>GET /v1/videos/generations/{request_id}</code></p><p class=\"note-s\"><code>GET /v1/videos/{request_id}/content</code></p><p class=\"note-s\"><code>GET /v1/videos/generations/{request_id}/content</code></p><p class=\"note-s\">Method shapes and IDs are exact; supplier capability is separate from admission.</p></details></details></section><section class=\"card-section\" data-card-section=\"pricing\"><h3 tabindex=\"-1\">Pricing</h3><h4>Ailoot method rates</h4><section class=\"meth\" data-route=\"Core\"><header><b><span class=\"alias\">Ailoot</span> Video</b><code>POST /v1/videos/generations</code></header><dl><div><dt>Output</dt><dd>$0.18 <em>per second at 1080p</em></dd></div><div><dt>Output</dt><dd>$0.07 <em>per second at 480p</em></dd></div><div><dt>Output</dt><dd>$0.14 <em>per second at 720p</em></dd></div></dl></section><p class=\"note-s\">Ailoot reserves an estimated amount before a request. After the result, it settles the final charge from measured usage. Streaming settlement uses the final usage record. <a href=\"/docs/en/billing/reserve/\">How reservation and settlement work →</a></p></section><section class=\"card-section\" data-card-section=\"examples\"><h3 tabindex=\"-1\">Example requests</h3><h4>Ailoot · Video</h4><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Code options\"><button class=\"cg-tab\" id=\"model-code-1-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-1-panel-0\" aria-selected=\"true\" tabindex=\"0\">Image reference</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Copy code\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-1-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-1-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}&quot;\nexport AILOOT_IMAGE_URL\npython3 - &lt;&lt;&#39;PY_REQUEST&#39;\nimport json,os\nfrom pathlib import Path\np=json.loads(&#39;{&quot;model&quot;: &quot;happyhorse-1.1-i2v&quot;, &quot;prompt&quot;: &quot;The subject walks slowly toward the camera.&quot;, &quot;duration&quot;: 5, &quot;resolution&quot;: &quot;720P&quot;}&#39;)\nfrom urllib.parse import urlsplit\nu=os.environ[&quot;AILOOT_IMAGE_URL&quot;]\nz=urlsplit(u)\nif z.scheme!=&quot;https&quot; or not z.netloc or z.username or z.password:raise SystemExit(&quot;Set the actual HTTPS image URL&quot;)\np[&quot;image_urls&quot;]=[u]\nPath(&quot;request.json&quot;).write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -H &#39;Content-Type: application/json&#39; \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - &lt;&lt;&#39;PY_RESULT&#39;\nimport json\nfrom pathlib import Path\nr=json.loads(Path(&quot;result.json&quot;).read_text())\nprint(json.dumps(r))\nPY_RESULT\n</code></pre></div></div></div></section><section class=\"card-section\" data-card-section=\"results\"><h3 tabindex=\"-1\">Receive and save results</h3><h4>Ailoot · Video</h4><p class=\"note-s\">mp4</p><ul class=\"card-result-paths\"><li><code>GET /v1/videos/{request_id}</code></li><li><code>GET /v1/videos/generations/{request_id}</code></li><li><code>GET /v1/videos/{request_id}/content</code></li><li><code>GET /v1/videos/generations/{request_id}/content</code></li></ul><h5>Check job status</h5><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Code options\"><button class=\"cg-tab\" id=\"model-code-2-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-2-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET status</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Copy code\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-2-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-2-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}&quot;\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c &#39;import os,urllib.parse;print(urllib.parse.quote(os.environ[&quot;AILOOT_OPERATION_ID&quot;],safe=&quot;&quot;))&#39;)\ncurl --fail-with-body --silent --show-error &quot;https://api.ailoot.ai/v1/videos/generations/$operation_id&quot; \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o status.json\npython3 - &lt;&lt;&#39;PY_STATUS&#39;\nimport json\nfrom pathlib import Path\nr=json.loads(Path(&quot;status.json&quot;).read_text())\nprint(json.dumps(r))\nif r.get(&quot;status&quot;)==&quot;completed&quot;:\n    for x in r.get(&quot;data&quot;,[]):print(x)\nPY_STATUS\n</code></pre></div></div></div><h5>Save all completed assets</h5><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Code options\"><button class=\"cg-tab\" id=\"model-code-3-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-3-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET all completed assets</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Copy code\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-3-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-3-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}&quot;\nexport AILOOT_STATUS_FILE\npython3 - &lt;&lt;&#39;PY_REQUEST&#39;\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[&quot;AILOOT_STATUS_FILE&quot;])\nif not f.is_file():raise SystemExit(&quot;Choose the actual completed status file&quot;)\nr=json.loads(f.read_text())\nif r.get(&quot;status&quot;)!=&quot;completed&quot; or not isinstance(r.get(&quot;data&quot;),list) or not r[&quot;data&quot;]:raise SystemExit(&quot;Wait for a completed status with asset paths&quot;)\nurls=[]\nfor x in r[&quot;data&quot;]:\n    if not isinstance(x,str) or &quot;\\n&quot; in x or &quot;\\r&quot; in x:raise SystemExit(&quot;Invalid asset path&quot;)\n    u=urljoin(&quot;https://api.ailoot.ai&quot;,x)\n    z=urlsplit(u)\n    if z.scheme!=&quot;https&quot; or z.netloc!=&quot;api.ailoot.ai&quot; or z.username or z.password:raise SystemExit(&quot;Use the actual Ailoot asset paths from status&quot;)\n    urls.append(u)\nPath(&quot;asset-urls.txt&quot;).write_text(&quot;\\n&quot;.join(urls)+&quot;\\n&quot;)\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error &quot;$asset_url&quot; \\\n    -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o &quot;video-${index}.mp4&quot;\n  index=$((index + 1))\ndone &lt; asset-urls.txt\n</code></pre></div></div></div><details class=\"card-about\"><summary>Other content reads</summary><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Code options\"><button class=\"cg-tab\" id=\"model-code-4-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-4-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET content</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Copy code\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-4-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-4-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}&quot;\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c &#39;import os,urllib.parse;print(urllib.parse.quote(os.environ[&quot;AILOOT_OPERATION_ID&quot;],safe=&quot;&quot;))&#39;)\ncurl --fail-with-body --silent --show-error &quot;https://api.ailoot.ai/v1/videos/generations/$operation_id/content&quot; \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o video.mp4\n</code></pre></div></div></div></details><div class=\"card-result-process\" data-all-results><h5>Keep all completed results</h5><p class=\"note-s\">Save every completed video or returned file; retrieve every actual returned asset URL.</p><p class=\"note-s\">Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.</p></div><div class=\"card-result-process\" data-unknown-recovery><h5>If the original response needs checking</h5><p class=\"note-s\">Read existing original job; never resubmit unknown send.</p></div><details class=\"card-about\" data-output-fields><summary>Response fields</summary><div class=\"tw\" data-card-table=\"output\"><table><thead><tr><th>Field</th><th>Type</th></tr></thead><tbody><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">id</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">object</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">model</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">status</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">content_url</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>signed URL</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">data[]</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>signed URL</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">usage</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>object</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">result_pending_check</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>boolean</td></tr></tbody></table></div></details><details class=\"card-about\" data-method-errors><summary>Errors and next steps</summary><div class=\"tw\" data-card-table=\"errors\"><table><thead><tr><th>Response</th><th>Condition</th><th>Next step</th></tr></thead><tbody><tr><th data-cell-label=\"Response\" scope=\"row\"><span class=\"card-cell-label\">Response</span>400 · <code>invalid_request_error</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>Invalid required fields, material representation or parameter value</td><td data-cell-label=\"Next step\"><span class=\"card-cell-label\">Next step</span>Correct the indicated fields before a new creation request.</td></tr><tr><th data-cell-label=\"Response\" scope=\"row\"><span class=\"card-cell-label\">Response</span>409 · <code>video_not_ready</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>Original result content is not yet available</td><td data-cell-label=\"Next step\"><span class=\"card-cell-label\">Next step</span>Poll the original returned ID and respect Retry-After.</td></tr><tr><th data-cell-label=\"Response\" scope=\"row\"><span class=\"card-cell-label\">Response</span><code>server_error</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>The returned response says the operation or result requires a check</td><td data-cell-label=\"Next step\"><span class=\"card-cell-label\">Next step</span>Keep the original returned operation/task ID, request headers and response; continue supported reads of that original operation. Do not resubmit the creation request.</td></tr></tbody></table></div></details></section><section class=\"card-section\" data-card-section=\"aliases\"><h3 tabindex=\"-1\">Aliases</h3><h4>Model aliases</h4><p class=\"note-s\"><span data-model-alias-route=\"Core\"><b>Ailoot</b> <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-1.1-i2v&amp;fmt=videos\"><code>happyhorse-1.1-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v&amp;fmt=videos\"><code>happyhorse-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v-latest&amp;fmt=videos\"><code>happyhorse-i2v-latest</code></a></span></p><h4>Method path aliases</h4><p class=\"note-s\">Use the method paths shown above.</p><h4>Related caller IDs</h4><p class=\"note-s\"><a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-1.1-i2v&amp;fmt=videos\"><code>happyhorse-1.1-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v&amp;fmt=videos\"><code>happyhorse-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v-latest&amp;fmt=videos\"><code>happyhorse-i2v-latest</code></a></p></section></div>",
      "method_identity": {
        "effective_request_model_id": "happyhorse-1.1-i2v",
        "fmt": "videos",
        "http": "POST",
        "path": "/v1/videos/generations",
        "request_model_id": "happyhorse-1.1-i2v",
        "route_label": "Core"
      },
      "method_key": "Core|videos|/v1/videos/generations|happyhorse-1.1-i2v",
      "ordinal": 0,
      "rawMethod": {
        "cache_read": null,
        "cache_write": null,
        "cache_write_1h": null,
        "cache_write_5m": null,
        "conditional_meter": null,
        "contract": {
          "data": {
            "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
            "errors": [
              {
                "code": null,
                "condition": "Invalid required fields, material representation or parameter value",
                "http_status": 400,
                "recovery": "Correct the indicated fields before a new creation request.",
                "type": "invalid_request_error"
              },
              {
                "code": null,
                "condition": "Original result content is not yet available",
                "http_status": 409,
                "recovery": "Poll the original returned ID and respect Retry-After.",
                "type": "video_not_ready"
              },
              {
                "code": null,
                "condition": "The returned response says the operation or result requires a check",
                "http_status": null,
                "recovery": "Keep the original returned operation/task ID, request headers and response; continue supported reads of that original operation. Do not resubmit the creation request.",
                "type": "server_error"
              }
            ],
            "hints": [],
            "ignored_fields": [],
            "lifecycle": {
              "all_results": "Follow everyactualreturnedoutputandownedasset; no result is discardedbecauseindex0orcontent_urlalreadyexists.",
              "content": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}/content"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}/content"
                }
              ],
              "create": {
                "http": "POST",
                "path": "/v1/videos/generations"
              },
              "id_source": "Actualreturnedpublicid; opaque URLencodeit forGET",
              "mode": "submit_once_poll_original",
              "multioutputs": "retain every completed data output; index0 alone is not all outputs",
              "operation_id_is_not_task_id": true,
              "owned_result": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}"
              },
              "status": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}"
                }
              ],
              "submit_status": 202,
              "unknown": "Read existing original job; never resubmit unknown send.",
              "unknown_no_replay": true
            },
            "material_combinations": [
              {
                "mode": "first_frame_to_video",
                "required": [
                  "image_urls"
                ]
              }
            ],
            "media_library": {
              "asset": {
                "fields": [
                  {
                    "description": null,
                    "name": "asset_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "task_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "output_key",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "family",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "model",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "method",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "status",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "content_type",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "sha256",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "size_bytes",
                    "type": "integer"
                  },
                  {
                    "description": null,
                    "name": "content_url",
                    "type": "string"
                  }
                ],
                "http": "GET",
                "id_source": "actual returned asset_id",
                "path": "/v1/media/assets/{asset_id}"
              },
              "content": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}/content",
                "range_header_supported": true,
                "url_source": "Use exact returned signed content_url including its token; do not construct a token."
              },
              "expired_link": {
                "code": "link_expired",
                "http_status": 404,
                "recovery": "Read the asset again to obtain its refreshed signed content_url, then fetch that URL. Do not regenerate."
              },
              "list": {
                "all_pages": "Follow every returned next_cursor, then select records by their actual task_id/output_key.",
                "http": "GET",
                "output_fields": [
                  {
                    "description": null,
                    "name": "object",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "data",
                    "type": "asset[]"
                  },
                  {
                    "description": null,
                    "name": "next_cursor",
                    "type": "string|null"
                  }
                ],
                "parameters": [
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "family",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "cursor",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": 20,
                    "default_known": true,
                    "enum": null,
                    "enum_known": false,
                    "maximum": 100,
                    "minimum": 1,
                    "name": "limit",
                    "required": false,
                    "type": "integer"
                  }
                ],
                "path": "/v1/media/assets"
              },
              "revoke": {
                "http": "DELETE",
                "meaning": "Revokes/deletes the existing owned file; this is not generation cancellation.",
                "path": "/v1/media/assets/{asset_id}",
                "pending_status": "revoking",
                "success_statuses": [
                  202,
                  204
                ]
              },
              "task": {
                "http": "GET",
                "id_source": "actual returned task_id or media library record; operation_id is not task_id",
                "path": "/v1/media/tasks/{task_id}"
              }
            },
            "operation_modes": [
              "first_frame_to_video"
            ],
            "outputs": {
              "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
              "content_selection": "Oneownedvideo; use actualreturnedcontent_url/data[] ororiginalcontentread. No indexedselection field is promised by thisCorehandler.",
              "create_status": 202,
              "family": "video",
              "fields": [
                {
                  "description": null,
                  "name": "id",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "object",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "model",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "status",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "content_url",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "data[]",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "usage",
                  "type": "object"
                },
                {
                  "description": null,
                  "name": "result_pending_check",
                  "type": "boolean"
                }
              ],
              "format": "mp4"
            },
            "parameters": [
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": [
                  "happyhorse-1.1-i2v"
                ],
                "enum_known": true,
                "name": "model",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "min_length": 1,
                "name": "prompt",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": 5,
                "default_known": true,
                "enum": null,
                "enum_known": false,
                "maximum": 15,
                "minimum": 3,
                "name": "duration",
                "required": false,
                "type": "integer",
                "unit": "seconds"
              },
              {
                "availability": "source_interface",
                "default": "720P",
                "default_known": true,
                "enum": [
                  "480P",
                  "720P",
                  "1080P"
                ],
                "enum_known": true,
                "name": "resolution",
                "required": false,
                "type": "string"
              },
              {
                "availability": "unsupported",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "name": "ratio",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maximum_decoded_bytes": 20971520,
                "maximum_items": 1,
                "mime_types": [
                  "image/jpeg",
                  "image/png",
                  "image/webp"
                ],
                "minimum_items": 1,
                "name": "image_urls",
                "required": true,
                "type": "https_url|data_image_url[]"
              }
            ],
            "profile_binding": "Exact existing Ailoot model and method; interface constraints below do not assert provider qualification.",
            "unsupported": [
              "ratiofield"
            ]
          },
          "hints": [
            "Method shapes and IDs are exact; supplier capability is separate from admission."
          ],
          "input": {
            "content_type": "application/json",
            "default_duration": 5,
            "default_resolution": "720P",
            "duration_integer_range": [
              3,
              15
            ],
            "image_urls": {
              "max_count": 1,
              "max_data_image_bytes": 20971520,
              "min_count": 1,
              "schemes": [
                "https",
                "data raster base64"
              ]
            },
            "material_types": [
              "text",
              "image"
            ],
            "optional": [
              "duration",
              "resolution",
              "ratio",
              "prompt"
            ],
            "ratio": [],
            "ratio_must_omit": true,
            "required": [
              "model",
              "image_urls"
            ],
            "resolution": [
              "480P",
              "720P",
              "1080P"
            ]
          },
          "lifecycle": {
            "content": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}/content",
                "query": {
                  "index": "actual output index; default0"
                }
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}/content"
              }
            ],
            "id_source": "only actual ID/path from creation/status",
            "mode": "submit_once_poll_original",
            "multioutputs": "retain every completed data output; index0 alone is not all outputs",
            "owned_result": {
              "http": "GET",
              "path": "/v1/media/assets/{asset_id}"
            },
            "status": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}"
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}"
              }
            ],
            "submit_status": 202,
            "unknown": "Read existing original job; never resubmit unknown send."
          },
          "method": {
            "http": "POST",
            "path": "/v1/videos/generations"
          },
          "operation_modes": [
            "first_frame_to_video"
          ],
          "output": {
            "family": [
              "video"
            ],
            "format": null,
            "multioutputs": "retain every actual response output"
          }
        },
        "ctx": null,
        "examples": [
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}\"\nexport AILOOT_IMAGE_URL\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\np=json.loads('{\"model\": \"happyhorse-1.1-i2v\", \"prompt\": \"The subject walks slowly toward the camera.\", \"duration\": 5, \"resolution\": \"720P\"}')\nfrom urllib.parse import urlsplit\nu=os.environ[\"AILOOT_IMAGE_URL\"]\nz=urlsplit(u)\nif z.scheme!=\"https\" or not z.netloc or z.username or z.password:raise SystemExit(\"Set the actual HTTPS image URL\")\np[\"image_urls\"]=[u]\nPath(\"request.json\").write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -H 'Content-Type: application/json' \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - <<'PY_RESULT'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"result.json\").read_text())\nprint(json.dumps(r))\nPY_RESULT\n",
            "label": "Use your actual image reference",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o status.json\npython3 - <<'PY_STATUS'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"status.json\").read_text())\nprint(json.dumps(r))\nif r.get(\"status\")==\"completed\":\n    for x in r.get(\"data\",[]):print(x)\nPY_STATUS\n",
            "label": "GET status",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id/content\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o video.mp4\n",
            "label": "GET content",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}\"\nexport AILOOT_STATUS_FILE\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[\"AILOOT_STATUS_FILE\"])\nif not f.is_file():raise SystemExit(\"Choose the actual completed status file\")\nr=json.loads(f.read_text())\nif r.get(\"status\")!=\"completed\" or not isinstance(r.get(\"data\"),list) or not r[\"data\"]:raise SystemExit(\"Wait for a completed status with asset paths\")\nurls=[]\nfor x in r[\"data\"]:\n    if not isinstance(x,str) or \"\\n\" in x or \"\\r\" in x:raise SystemExit(\"Invalid asset path\")\n    u=urljoin(\"https://api.ailoot.ai\",x)\n    z=urlsplit(u)\n    if z.scheme!=\"https\" or z.netloc!=\"api.ailoot.ai\" or z.username or z.password:raise SystemExit(\"Use the actual Ailoot asset paths from status\")\n    urls.append(u)\nPath(\"asset-urls.txt\").write_text(\"\\n\".join(urls)+\"\\n\")\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error \"$asset_url\" \\\n    -H \"Authorization: Bearer $AILOOT_API_KEY\" -o \"video-${index}.mp4\"\n  index=$((index + 1))\ndone < asset-urls.txt\n",
            "label": "GET all completed assets",
            "language": "bash"
          }
        ],
        "family": "openai",
        "fast_multiplier": null,
        "flex_multiplier": null,
        "fmt": "videos",
        "http": "POST",
        "img_in": null,
        "img_out": null,
        "in": null,
        "input": [
          "text",
          "image"
        ],
        "label": "Video",
        "max_out": null,
        "max_tool_calls": null,
        "out": null,
        "output": [
          "video"
        ],
        "path": "/v1/videos/generations",
        "pricing_profiles": [
          {
            "dimensions": {},
            "label": "Core",
            "units": [
              {
                "amount": 0.18,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_1080p_second",
                "label": "per second at 1080p",
                "side": "out"
              },
              {
                "amount": 0.07,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_480p_second",
                "label": "per second at 480p",
                "side": "out"
              },
              {
                "amount": 0.14,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_720p_second",
                "label": "per second at 720p",
                "side": "out"
              }
            ]
          }
        ],
        "request_model_id": "happyhorse-1.1-i2v",
        "route_label": "Core",
        "status_reads": [
          "GET /v1/videos/generations/{id}",
          "GET /v1/videos/generations/{id}/content"
        ],
        "tiers": [],
        "tool_prices": null,
        "unit": "conditional",
        "units": [
          {
            "key": "video_output_1080p_second",
            "label": "per second at 1080p",
            "side": "out",
            "usd": 0.18
          },
          {
            "key": "video_output_480p_second",
            "label": "per second at 480p",
            "side": "out",
            "usd": 0.07
          },
          {
            "key": "video_output_720p_second",
            "label": "per second at 720p",
            "side": "out",
            "usd": 0.14
          }
        ]
      }
    },
    {
      "html": "<div class=\"sheet-head\"><span class=\"mav\" aria-hidden=\"true\">Al</span><h2 id=\"sheet-title\">happyhorse-1.1-i2v</h2><button class=\"icon-btn\" type=\"button\" data-close-sheet aria-label=\"Close\">×</button></div><div class=\"idline\"><span>Alibaba /</span><code>happyhorse-i2v</code><button type=\"button\" id=\"copy-id\">Copy ID</button></div><nav class=\"card-jump-nav\" aria-label=\"Model card sections\"><button type=\"button\" data-card-jump=\"overview\">Overview</button><button type=\"button\" data-card-jump=\"methods\">Inputs &amp; methods</button><button type=\"button\" data-card-jump=\"pricing\">Pricing</button><button type=\"button\" data-card-jump=\"examples\">Examples</button><button type=\"button\" data-card-jump=\"results\">Results</button><button type=\"button\" data-card-jump=\"aliases\">Aliases</button></nav><div class=\"card-method-tabs\" role=\"tablist\" aria-label=\"API methods\"><button type=\"button\" role=\"tab\" tabindex=\"0\" aria-controls=\"card-method-content\" aria-selected=\"true\" id=\"card-method-tab-0\" data-card-method=\"Core|videos|/v1/videos/generations|happyhorse-i2v\">Video</button></div><div class=\"idline\"><label for=\"card-model-id\">Model ID</label><select class=\"sel\" id=\"card-model-id\" style=\"min-width:0;max-width:100%\"><option value=\"Core|videos|/v1/videos/generations|happyhorse-1.1-i2v\">happyhorse-1.1-i2v</option><option value=\"Core|videos|/v1/videos/generations|happyhorse-i2v\" selected>happyhorse-i2v</option><option value=\"Core|videos|/v1/videos/generations|happyhorse-i2v-latest\">happyhorse-i2v-latest</option></select></div><div id=\"card-method-content\" role=\"tabpanel\" aria-labelledby=\"card-method-tab-0\"><section class=\"card-section\" data-card-section=\"overview\"><h3 tabindex=\"-1\">Overview</h3><p class=\"mdesc-full\">An image-to-video model: the source image provides the first frame, and the prompt guides the subsequent motion. Creates a short video with optional accompanying audio.</p><dl class=\"card-io\" data-card-io><div><dt>Accepted inputs</dt><dd>Text · Images</dd></div><div><dt>Results</dt><dd>Video</dd></div></dl><details class=\"card-about\"><summary>About the model</summary><p class=\"note-s\" data-model-method-boundary>This description covers the model’s capabilities. Available in Ailoot inputs, outputs and options are listed for the selected method below.</p><div class=\"mabout\" id=\"m-about\"><p>HappyHorse-1.1-I2V is an Alibaba model that starts a video scene from an existing image. The image becomes the first frame, while text can specify what happens next: a character&#39;s movement, changes in the scene and the camera&#39;s direction. It is suited to animating an illustration, a product photograph or a prepared visual concept.</p><p>A text prompt is optional. Without one, the model infers possible motion from the initial image. When a prompt is supplied, the source image determines the composition and the appearance of objects, while the words guide how the scene develops over time.</p><h4>From the first frame to motion</h4><p>Alibaba highlights preservation of character appearance, visual consistency, smooth movement and the combination of visuals with audio. Its stated aims also include stable text and textures. These properties describe the model&#39;s intended capabilities; they do not mean that every pixel is literally preserved in every generated frame.</p><p>This mode uses one initial image. It defines the starting scene rather than providing a set of independent references for a new composition. The ability to specify a separate final frame is not stated for this particular version.</p><p>JPEG, JPG, PNG and WEBP are accepted. Each dimension of the input image must be at least 300 pixels; the permitted aspect ratio ranges from 1:2.5 to 2.5:1, and the file size limit is 20 MB. The output video&#39;s aspect ratio follows the first frame.</p><h4>Video parameters</h4><p>The duration is selected as an integer from 3 to 15 seconds. Available resolution levels are 480P, 720P and 1080P; the output format is MP4 at 24 frames per second. Audio can be generated alongside the video.</p><p>The prompt may be in any language and contain up to 5000 non-Chinese or 2500 Chinese characters. Any excess is truncated, so important actions and motion details should fit within that limit. The same random seed may produce similar videos, but does not guarantee a frame-by-frame match.</p></div></details></section><section class=\"card-section\" data-card-section=\"methods\"><h3 tabindex=\"-1\">Available in Ailoot · inputs &amp; methods</h3><details class=\"card-method\" open><summary><b>Ailoot · Video</b> <code>POST /v1/videos/generations</code></summary><dl class=\"method-capabilities\"><div><dt>Input types</dt><dd><code>text</code>, <code>image</code></dd></div><div><dt>Output types</dt><dd><code>video</code></dd></div><div><dt>Output format</dt><dd>mp4</dd></div></dl><div class=\"tw\" data-card-parameters data-typed-parameters><table><thead><tr><th>Field</th><th>Type</th><th>Requirement</th><th>Values &amp; limits</th><th>Default</th></tr></thead><tbody><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">model</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Required</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>happyhorse-i2v</div></td><td data-cell-label=\"Default\" data-default=\"unspecified\"><span class=\"card-cell-label\">Default</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">prompt</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Optional</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>Minimum length: 1</div></td><td data-cell-label=\"Default\" data-default=\"unspecified\"><span class=\"card-cell-label\">Default</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">duration</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>integer</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Optional</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>Minimum: 3</div><div>Maximum: 15</div><div>Unit: seconds</div></td><td data-cell-label=\"Default\" data-default=\"known\"><span class=\"card-cell-label\">Default</span>5</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">resolution</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Optional</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>480P, 720P, 1080P</div></td><td data-cell-label=\"Default\" data-default=\"known\"><span class=\"card-cell-label\">Default</span>720P</td></tr><tr data-parameter-availability=\"unsupported\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">ratio</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Not supported</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span></td><td data-cell-label=\"Default\" data-default=\"unspecified\"><span class=\"card-cell-label\">Default</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">image_urls</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>https_url|data_image_url[]</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Required</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>Minimum items: 1</div><div>Maximum items: 1</div><div>Maximum decoded bytes: 20,971,520</div><div>MIME types: image/jpeg, image/png, image/webp</div></td><td data-cell-label=\"Default\" data-default=\"unspecified\"><span class=\"card-cell-label\">Default</span>—</td></tr></tbody></table></div><details class=\"card-about\" data-material-combinations><summary>Input material combinations</summary><p class=\"note-s\"><b>first_frame_to_video</b> · Required: image_urls</p></details><details class=\"note-s\" data-method-contract><summary>Method parameters and lifecycle</summary><div class=\"tw\" data-card-table=\"contract\"><table><thead><tr><th>Parameter</th><th>Contract</th></tr></thead><tbody><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>material_types</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>text, image</td></tr><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>required</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>null</td></tr><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>optional_controls</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>null</td></tr></tbody></table></div><p>Lifecycle: <code>submit_once_poll_original</code></p><p class=\"note-s\"><code>GET /v1/videos/{request_id}</code></p><p class=\"note-s\"><code>GET /v1/videos/generations/{request_id}</code></p><p class=\"note-s\"><code>GET /v1/videos/{request_id}/content</code></p><p class=\"note-s\"><code>GET /v1/videos/generations/{request_id}/content</code></p><p class=\"note-s\">Method shapes and IDs are exact; supplier capability is separate from admission.</p></details></details></section><section class=\"card-section\" data-card-section=\"pricing\"><h3 tabindex=\"-1\">Pricing</h3><h4>Ailoot method rates</h4><section class=\"meth\" data-route=\"Core\"><header><b><span class=\"alias\">Ailoot</span> Video</b><code>POST /v1/videos/generations</code></header><dl><div><dt>Output</dt><dd>$0.18 <em>per second at 1080p</em></dd></div><div><dt>Output</dt><dd>$0.07 <em>per second at 480p</em></dd></div><div><dt>Output</dt><dd>$0.14 <em>per second at 720p</em></dd></div></dl></section><p class=\"note-s\">Ailoot reserves an estimated amount before a request. After the result, it settles the final charge from measured usage. Streaming settlement uses the final usage record. <a href=\"/docs/en/billing/reserve/\">How reservation and settlement work →</a></p></section><section class=\"card-section\" data-card-section=\"examples\"><h3 tabindex=\"-1\">Example requests</h3><h4>Ailoot · Video</h4><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Code options\"><button class=\"cg-tab\" id=\"model-code-5-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-5-panel-0\" aria-selected=\"true\" tabindex=\"0\">Image reference</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Copy code\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-5-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-5-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}&quot;\nexport AILOOT_IMAGE_URL\npython3 - &lt;&lt;&#39;PY_REQUEST&#39;\nimport json,os\nfrom pathlib import Path\np=json.loads(&#39;{&quot;model&quot;: &quot;happyhorse-i2v&quot;, &quot;prompt&quot;: &quot;The subject walks slowly toward the camera.&quot;, &quot;duration&quot;: 5, &quot;resolution&quot;: &quot;720P&quot;}&#39;)\nfrom urllib.parse import urlsplit\nu=os.environ[&quot;AILOOT_IMAGE_URL&quot;]\nz=urlsplit(u)\nif z.scheme!=&quot;https&quot; or not z.netloc or z.username or z.password:raise SystemExit(&quot;Set the actual HTTPS image URL&quot;)\np[&quot;image_urls&quot;]=[u]\nPath(&quot;request.json&quot;).write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -H &#39;Content-Type: application/json&#39; \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - &lt;&lt;&#39;PY_RESULT&#39;\nimport json\nfrom pathlib import Path\nr=json.loads(Path(&quot;result.json&quot;).read_text())\nprint(json.dumps(r))\nPY_RESULT\n</code></pre></div></div></div></section><section class=\"card-section\" data-card-section=\"results\"><h3 tabindex=\"-1\">Receive and save results</h3><h4>Ailoot · Video</h4><p class=\"note-s\">mp4</p><ul class=\"card-result-paths\"><li><code>GET /v1/videos/{request_id}</code></li><li><code>GET /v1/videos/generations/{request_id}</code></li><li><code>GET /v1/videos/{request_id}/content</code></li><li><code>GET /v1/videos/generations/{request_id}/content</code></li></ul><h5>Check job status</h5><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Code options\"><button class=\"cg-tab\" id=\"model-code-6-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-6-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET status</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Copy code\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-6-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-6-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}&quot;\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c &#39;import os,urllib.parse;print(urllib.parse.quote(os.environ[&quot;AILOOT_OPERATION_ID&quot;],safe=&quot;&quot;))&#39;)\ncurl --fail-with-body --silent --show-error &quot;https://api.ailoot.ai/v1/videos/generations/$operation_id&quot; \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o status.json\npython3 - &lt;&lt;&#39;PY_STATUS&#39;\nimport json\nfrom pathlib import Path\nr=json.loads(Path(&quot;status.json&quot;).read_text())\nprint(json.dumps(r))\nif r.get(&quot;status&quot;)==&quot;completed&quot;:\n    for x in r.get(&quot;data&quot;,[]):print(x)\nPY_STATUS\n</code></pre></div></div></div><h5>Save all completed assets</h5><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Code options\"><button class=\"cg-tab\" id=\"model-code-7-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-7-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET all completed assets</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Copy code\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-7-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-7-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}&quot;\nexport AILOOT_STATUS_FILE\npython3 - &lt;&lt;&#39;PY_REQUEST&#39;\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[&quot;AILOOT_STATUS_FILE&quot;])\nif not f.is_file():raise SystemExit(&quot;Choose the actual completed status file&quot;)\nr=json.loads(f.read_text())\nif r.get(&quot;status&quot;)!=&quot;completed&quot; or not isinstance(r.get(&quot;data&quot;),list) or not r[&quot;data&quot;]:raise SystemExit(&quot;Wait for a completed status with asset paths&quot;)\nurls=[]\nfor x in r[&quot;data&quot;]:\n    if not isinstance(x,str) or &quot;\\n&quot; in x or &quot;\\r&quot; in x:raise SystemExit(&quot;Invalid asset path&quot;)\n    u=urljoin(&quot;https://api.ailoot.ai&quot;,x)\n    z=urlsplit(u)\n    if z.scheme!=&quot;https&quot; or z.netloc!=&quot;api.ailoot.ai&quot; or z.username or z.password:raise SystemExit(&quot;Use the actual Ailoot asset paths from status&quot;)\n    urls.append(u)\nPath(&quot;asset-urls.txt&quot;).write_text(&quot;\\n&quot;.join(urls)+&quot;\\n&quot;)\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error &quot;$asset_url&quot; \\\n    -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o &quot;video-${index}.mp4&quot;\n  index=$((index + 1))\ndone &lt; asset-urls.txt\n</code></pre></div></div></div><details class=\"card-about\"><summary>Other content reads</summary><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Code options\"><button class=\"cg-tab\" id=\"model-code-8-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-8-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET content</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Copy code\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-8-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-8-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}&quot;\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c &#39;import os,urllib.parse;print(urllib.parse.quote(os.environ[&quot;AILOOT_OPERATION_ID&quot;],safe=&quot;&quot;))&#39;)\ncurl --fail-with-body --silent --show-error &quot;https://api.ailoot.ai/v1/videos/generations/$operation_id/content&quot; \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o video.mp4\n</code></pre></div></div></div></details><div class=\"card-result-process\" data-all-results><h5>Keep all completed results</h5><p class=\"note-s\">Save every completed video or returned file; retrieve every actual returned asset URL.</p><p class=\"note-s\">Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.</p></div><div class=\"card-result-process\" data-unknown-recovery><h5>If the original response needs checking</h5><p class=\"note-s\">Read existing original job; never resubmit unknown send.</p></div><details class=\"card-about\" data-output-fields><summary>Response fields</summary><div class=\"tw\" data-card-table=\"output\"><table><thead><tr><th>Field</th><th>Type</th></tr></thead><tbody><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">id</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">object</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">model</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">status</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">content_url</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>signed URL</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">data[]</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>signed URL</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">usage</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>object</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">result_pending_check</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>boolean</td></tr></tbody></table></div></details><details class=\"card-about\" data-method-errors><summary>Errors and next steps</summary><div class=\"tw\" data-card-table=\"errors\"><table><thead><tr><th>Response</th><th>Condition</th><th>Next step</th></tr></thead><tbody><tr><th data-cell-label=\"Response\" scope=\"row\"><span class=\"card-cell-label\">Response</span>400 · <code>invalid_request_error</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>Invalid required fields, material representation or parameter value</td><td data-cell-label=\"Next step\"><span class=\"card-cell-label\">Next step</span>Correct the indicated fields before a new creation request.</td></tr><tr><th data-cell-label=\"Response\" scope=\"row\"><span class=\"card-cell-label\">Response</span>409 · <code>video_not_ready</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>Original result content is not yet available</td><td data-cell-label=\"Next step\"><span class=\"card-cell-label\">Next step</span>Poll the original returned ID and respect Retry-After.</td></tr><tr><th data-cell-label=\"Response\" scope=\"row\"><span class=\"card-cell-label\">Response</span><code>server_error</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>The returned response says the operation or result requires a check</td><td data-cell-label=\"Next step\"><span class=\"card-cell-label\">Next step</span>Keep the original returned operation/task ID, request headers and response; continue supported reads of that original operation. Do not resubmit the creation request.</td></tr></tbody></table></div></details></section><section class=\"card-section\" data-card-section=\"aliases\"><h3 tabindex=\"-1\">Aliases</h3><h4>Model aliases</h4><p class=\"note-s\"><span data-model-alias-route=\"Core\"><b>Ailoot</b> <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-1.1-i2v&amp;fmt=videos\"><code>happyhorse-1.1-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v&amp;fmt=videos\"><code>happyhorse-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v-latest&amp;fmt=videos\"><code>happyhorse-i2v-latest</code></a></span></p><h4>Method path aliases</h4><p class=\"note-s\">Use the method paths shown above.</p><h4>Related caller IDs</h4><p class=\"note-s\"><a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-1.1-i2v&amp;fmt=videos\"><code>happyhorse-1.1-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v&amp;fmt=videos\"><code>happyhorse-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v-latest&amp;fmt=videos\"><code>happyhorse-i2v-latest</code></a></p></section></div>",
      "method_identity": {
        "effective_request_model_id": "happyhorse-i2v",
        "fmt": "videos",
        "http": "POST",
        "path": "/v1/videos/generations",
        "request_model_id": "happyhorse-i2v",
        "route_label": "Core"
      },
      "method_key": "Core|videos|/v1/videos/generations|happyhorse-i2v",
      "ordinal": 1,
      "rawMethod": {
        "cache_read": null,
        "cache_write": null,
        "cache_write_1h": null,
        "cache_write_5m": null,
        "conditional_meter": null,
        "contract": {
          "data": {
            "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
            "errors": [
              {
                "code": null,
                "condition": "Invalid required fields, material representation or parameter value",
                "http_status": 400,
                "recovery": "Correct the indicated fields before a new creation request.",
                "type": "invalid_request_error"
              },
              {
                "code": null,
                "condition": "Original result content is not yet available",
                "http_status": 409,
                "recovery": "Poll the original returned ID and respect Retry-After.",
                "type": "video_not_ready"
              },
              {
                "code": null,
                "condition": "The returned response says the operation or result requires a check",
                "http_status": null,
                "recovery": "Keep the original returned operation/task ID, request headers and response; continue supported reads of that original operation. Do not resubmit the creation request.",
                "type": "server_error"
              }
            ],
            "hints": [],
            "ignored_fields": [],
            "lifecycle": {
              "all_results": "Follow everyactualreturnedoutputandownedasset; no result is discardedbecauseindex0orcontent_urlalreadyexists.",
              "content": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}/content"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}/content"
                }
              ],
              "create": {
                "http": "POST",
                "path": "/v1/videos/generations"
              },
              "id_source": "Actualreturnedpublicid; opaque URLencodeit forGET",
              "mode": "submit_once_poll_original",
              "multioutputs": "retain every completed data output; index0 alone is not all outputs",
              "operation_id_is_not_task_id": true,
              "owned_result": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}"
              },
              "status": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}"
                }
              ],
              "submit_status": 202,
              "unknown": "Read existing original job; never resubmit unknown send.",
              "unknown_no_replay": true
            },
            "material_combinations": [
              {
                "mode": "first_frame_to_video",
                "required": [
                  "image_urls"
                ]
              }
            ],
            "media_library": {
              "asset": {
                "fields": [
                  {
                    "description": null,
                    "name": "asset_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "task_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "output_key",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "family",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "model",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "method",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "status",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "content_type",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "sha256",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "size_bytes",
                    "type": "integer"
                  },
                  {
                    "description": null,
                    "name": "content_url",
                    "type": "string"
                  }
                ],
                "http": "GET",
                "id_source": "actual returned asset_id",
                "path": "/v1/media/assets/{asset_id}"
              },
              "content": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}/content",
                "range_header_supported": true,
                "url_source": "Use exact returned signed content_url including its token; do not construct a token."
              },
              "expired_link": {
                "code": "link_expired",
                "http_status": 404,
                "recovery": "Read the asset again to obtain its refreshed signed content_url, then fetch that URL. Do not regenerate."
              },
              "list": {
                "all_pages": "Follow every returned next_cursor, then select records by their actual task_id/output_key.",
                "http": "GET",
                "output_fields": [
                  {
                    "description": null,
                    "name": "object",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "data",
                    "type": "asset[]"
                  },
                  {
                    "description": null,
                    "name": "next_cursor",
                    "type": "string|null"
                  }
                ],
                "parameters": [
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "family",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "cursor",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": 20,
                    "default_known": true,
                    "enum": null,
                    "enum_known": false,
                    "maximum": 100,
                    "minimum": 1,
                    "name": "limit",
                    "required": false,
                    "type": "integer"
                  }
                ],
                "path": "/v1/media/assets"
              },
              "revoke": {
                "http": "DELETE",
                "meaning": "Revokes/deletes the existing owned file; this is not generation cancellation.",
                "path": "/v1/media/assets/{asset_id}",
                "pending_status": "revoking",
                "success_statuses": [
                  202,
                  204
                ]
              },
              "task": {
                "http": "GET",
                "id_source": "actual returned task_id or media library record; operation_id is not task_id",
                "path": "/v1/media/tasks/{task_id}"
              }
            },
            "operation_modes": [
              "videos"
            ],
            "outputs": {
              "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
              "content_selection": "Oneownedvideo; use actualreturnedcontent_url/data[] ororiginalcontentread. No indexedselection field is promised by thisCorehandler.",
              "create_status": 202,
              "family": "video",
              "fields": [
                {
                  "description": null,
                  "name": "id",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "object",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "model",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "status",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "content_url",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "data[]",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "usage",
                  "type": "object"
                },
                {
                  "description": null,
                  "name": "result_pending_check",
                  "type": "boolean"
                }
              ],
              "format": "mp4"
            },
            "parameters": [
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": [
                  "happyhorse-i2v"
                ],
                "enum_known": true,
                "name": "model",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "min_length": 1,
                "name": "prompt",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": 5,
                "default_known": true,
                "enum": null,
                "enum_known": false,
                "maximum": 15,
                "minimum": 3,
                "name": "duration",
                "required": false,
                "type": "integer",
                "unit": "seconds"
              },
              {
                "availability": "source_interface",
                "default": "720P",
                "default_known": true,
                "enum": [
                  "480P",
                  "720P",
                  "1080P"
                ],
                "enum_known": true,
                "name": "resolution",
                "required": false,
                "type": "string"
              },
              {
                "availability": "unsupported",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "name": "ratio",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maximum_decoded_bytes": 20971520,
                "maximum_items": 1,
                "mime_types": [
                  "image/jpeg",
                  "image/png",
                  "image/webp"
                ],
                "minimum_items": 1,
                "name": "image_urls",
                "required": true,
                "type": "https_url|data_image_url[]"
              }
            ],
            "profile_binding": "Exact existing Ailoot model and method; interface constraints below do not assert provider qualification.",
            "unsupported": [
              "ratiofield"
            ]
          },
          "hints": [
            "Method shapes and IDs are exact; supplier capability is separate from admission."
          ],
          "input": {
            "material_types": [
              "text",
              "image"
            ],
            "optional_controls": null,
            "required": null
          },
          "lifecycle": {
            "content": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}/content",
                "query": {
                  "index": "actual output index; default0"
                }
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}/content"
              }
            ],
            "id_source": "only actual ID/path from creation/status",
            "mode": "submit_once_poll_original",
            "multioutputs": "retain every completed data output; index0 alone is not all outputs",
            "owned_result": {
              "http": "GET",
              "path": "/v1/media/assets/{asset_id}"
            },
            "status": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}"
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}"
              }
            ],
            "submit_status": 202,
            "unknown": "Read existing original job; never resubmit unknown send."
          },
          "method": {
            "http": "POST",
            "path": "/v1/videos/generations"
          },
          "operation_modes": [
            "videos"
          ],
          "output": {
            "family": [
              "video"
            ],
            "format": null,
            "multioutputs": "retain every actual response output"
          }
        },
        "ctx": null,
        "examples": [
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}\"\nexport AILOOT_IMAGE_URL\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\np=json.loads('{\"model\": \"happyhorse-i2v\", \"prompt\": \"The subject walks slowly toward the camera.\", \"duration\": 5, \"resolution\": \"720P\"}')\nfrom urllib.parse import urlsplit\nu=os.environ[\"AILOOT_IMAGE_URL\"]\nz=urlsplit(u)\nif z.scheme!=\"https\" or not z.netloc or z.username or z.password:raise SystemExit(\"Set the actual HTTPS image URL\")\np[\"image_urls\"]=[u]\nPath(\"request.json\").write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -H 'Content-Type: application/json' \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - <<'PY_RESULT'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"result.json\").read_text())\nprint(json.dumps(r))\nPY_RESULT\n",
            "label": "Use your actual image reference",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o status.json\npython3 - <<'PY_STATUS'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"status.json\").read_text())\nprint(json.dumps(r))\nif r.get(\"status\")==\"completed\":\n    for x in r.get(\"data\",[]):print(x)\nPY_STATUS\n",
            "label": "GET status",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id/content\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o video.mp4\n",
            "label": "GET content",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}\"\nexport AILOOT_STATUS_FILE\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[\"AILOOT_STATUS_FILE\"])\nif not f.is_file():raise SystemExit(\"Choose the actual completed status file\")\nr=json.loads(f.read_text())\nif r.get(\"status\")!=\"completed\" or not isinstance(r.get(\"data\"),list) or not r[\"data\"]:raise SystemExit(\"Wait for a completed status with asset paths\")\nurls=[]\nfor x in r[\"data\"]:\n    if not isinstance(x,str) or \"\\n\" in x or \"\\r\" in x:raise SystemExit(\"Invalid asset path\")\n    u=urljoin(\"https://api.ailoot.ai\",x)\n    z=urlsplit(u)\n    if z.scheme!=\"https\" or z.netloc!=\"api.ailoot.ai\" or z.username or z.password:raise SystemExit(\"Use the actual Ailoot asset paths from status\")\n    urls.append(u)\nPath(\"asset-urls.txt\").write_text(\"\\n\".join(urls)+\"\\n\")\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error \"$asset_url\" \\\n    -H \"Authorization: Bearer $AILOOT_API_KEY\" -o \"video-${index}.mp4\"\n  index=$((index + 1))\ndone < asset-urls.txt\n",
            "label": "GET all completed assets",
            "language": "bash"
          }
        ],
        "family": "openai",
        "fast_multiplier": null,
        "flex_multiplier": null,
        "fmt": "videos",
        "http": "POST",
        "img_in": null,
        "img_out": null,
        "in": null,
        "input": [
          "text",
          "image"
        ],
        "label": "Video",
        "max_out": null,
        "max_tool_calls": null,
        "out": null,
        "output": [
          "video"
        ],
        "path": "/v1/videos/generations",
        "pricing_profiles": [
          {
            "dimensions": {},
            "label": "Core",
            "units": [
              {
                "amount": 0.18,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_1080p_second",
                "label": "per second at 1080p",
                "side": "out"
              },
              {
                "amount": 0.07,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_480p_second",
                "label": "per second at 480p",
                "side": "out"
              },
              {
                "amount": 0.14,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_720p_second",
                "label": "per second at 720p",
                "side": "out"
              }
            ]
          }
        ],
        "request_model_id": "happyhorse-i2v",
        "route_label": "Core",
        "status_reads": [
          "GET /v1/videos/generations/{id}",
          "GET /v1/videos/generations/{id}/content"
        ],
        "tiers": [],
        "tool_prices": null,
        "unit": "conditional",
        "units": [
          {
            "key": "video_output_1080p_second",
            "label": "per second at 1080p",
            "side": "out",
            "usd": 0.18
          },
          {
            "key": "video_output_480p_second",
            "label": "per second at 480p",
            "side": "out",
            "usd": 0.07
          },
          {
            "key": "video_output_720p_second",
            "label": "per second at 720p",
            "side": "out",
            "usd": 0.14
          }
        ]
      }
    },
    {
      "html": "<div class=\"sheet-head\"><span class=\"mav\" aria-hidden=\"true\">Al</span><h2 id=\"sheet-title\">happyhorse-1.1-i2v</h2><button class=\"icon-btn\" type=\"button\" data-close-sheet aria-label=\"Close\">×</button></div><div class=\"idline\"><span>Alibaba /</span><code>happyhorse-i2v-latest</code><button type=\"button\" id=\"copy-id\">Copy ID</button></div><nav class=\"card-jump-nav\" aria-label=\"Model card sections\"><button type=\"button\" data-card-jump=\"overview\">Overview</button><button type=\"button\" data-card-jump=\"methods\">Inputs &amp; methods</button><button type=\"button\" data-card-jump=\"pricing\">Pricing</button><button type=\"button\" data-card-jump=\"examples\">Examples</button><button type=\"button\" data-card-jump=\"results\">Results</button><button type=\"button\" data-card-jump=\"aliases\">Aliases</button></nav><div class=\"card-method-tabs\" role=\"tablist\" aria-label=\"API methods\"><button type=\"button\" role=\"tab\" tabindex=\"0\" aria-controls=\"card-method-content\" aria-selected=\"true\" id=\"card-method-tab-0\" data-card-method=\"Core|videos|/v1/videos/generations|happyhorse-i2v-latest\">Video</button></div><div class=\"idline\"><label for=\"card-model-id\">Model ID</label><select class=\"sel\" id=\"card-model-id\" style=\"min-width:0;max-width:100%\"><option value=\"Core|videos|/v1/videos/generations|happyhorse-1.1-i2v\">happyhorse-1.1-i2v</option><option value=\"Core|videos|/v1/videos/generations|happyhorse-i2v\">happyhorse-i2v</option><option value=\"Core|videos|/v1/videos/generations|happyhorse-i2v-latest\" selected>happyhorse-i2v-latest</option></select></div><div id=\"card-method-content\" role=\"tabpanel\" aria-labelledby=\"card-method-tab-0\"><section class=\"card-section\" data-card-section=\"overview\"><h3 tabindex=\"-1\">Overview</h3><p class=\"mdesc-full\">An image-to-video model: the source image provides the first frame, and the prompt guides the subsequent motion. Creates a short video with optional accompanying audio.</p><dl class=\"card-io\" data-card-io><div><dt>Accepted inputs</dt><dd>Text · Images</dd></div><div><dt>Results</dt><dd>Video</dd></div></dl><details class=\"card-about\"><summary>About the model</summary><p class=\"note-s\" data-model-method-boundary>This description covers the model’s capabilities. Available in Ailoot inputs, outputs and options are listed for the selected method below.</p><div class=\"mabout\" id=\"m-about\"><p>HappyHorse-1.1-I2V is an Alibaba model that starts a video scene from an existing image. The image becomes the first frame, while text can specify what happens next: a character&#39;s movement, changes in the scene and the camera&#39;s direction. It is suited to animating an illustration, a product photograph or a prepared visual concept.</p><p>A text prompt is optional. Without one, the model infers possible motion from the initial image. When a prompt is supplied, the source image determines the composition and the appearance of objects, while the words guide how the scene develops over time.</p><h4>From the first frame to motion</h4><p>Alibaba highlights preservation of character appearance, visual consistency, smooth movement and the combination of visuals with audio. Its stated aims also include stable text and textures. These properties describe the model&#39;s intended capabilities; they do not mean that every pixel is literally preserved in every generated frame.</p><p>This mode uses one initial image. It defines the starting scene rather than providing a set of independent references for a new composition. The ability to specify a separate final frame is not stated for this particular version.</p><p>JPEG, JPG, PNG and WEBP are accepted. Each dimension of the input image must be at least 300 pixels; the permitted aspect ratio ranges from 1:2.5 to 2.5:1, and the file size limit is 20 MB. The output video&#39;s aspect ratio follows the first frame.</p><h4>Video parameters</h4><p>The duration is selected as an integer from 3 to 15 seconds. Available resolution levels are 480P, 720P and 1080P; the output format is MP4 at 24 frames per second. Audio can be generated alongside the video.</p><p>The prompt may be in any language and contain up to 5000 non-Chinese or 2500 Chinese characters. Any excess is truncated, so important actions and motion details should fit within that limit. The same random seed may produce similar videos, but does not guarantee a frame-by-frame match.</p></div></details></section><section class=\"card-section\" data-card-section=\"methods\"><h3 tabindex=\"-1\">Available in Ailoot · inputs &amp; methods</h3><details class=\"card-method\" open><summary><b>Ailoot · Video</b> <code>POST /v1/videos/generations</code></summary><dl class=\"method-capabilities\"><div><dt>Input types</dt><dd><code>text</code>, <code>image</code></dd></div><div><dt>Output types</dt><dd><code>video</code></dd></div><div><dt>Output format</dt><dd>mp4</dd></div></dl><div class=\"tw\" data-card-parameters data-typed-parameters><table><thead><tr><th>Field</th><th>Type</th><th>Requirement</th><th>Values &amp; limits</th><th>Default</th></tr></thead><tbody><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">model</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Required</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>happyhorse-i2v-latest</div></td><td data-cell-label=\"Default\" data-default=\"unspecified\"><span class=\"card-cell-label\">Default</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">prompt</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Optional</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>Minimum length: 1</div></td><td data-cell-label=\"Default\" data-default=\"unspecified\"><span class=\"card-cell-label\">Default</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">duration</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>integer</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Optional</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>Minimum: 3</div><div>Maximum: 15</div><div>Unit: seconds</div></td><td data-cell-label=\"Default\" data-default=\"known\"><span class=\"card-cell-label\">Default</span>5</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">resolution</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Optional</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>480P, 720P, 1080P</div></td><td data-cell-label=\"Default\" data-default=\"known\"><span class=\"card-cell-label\">Default</span>720P</td></tr><tr data-parameter-availability=\"unsupported\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">ratio</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Not supported</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span></td><td data-cell-label=\"Default\" data-default=\"unspecified\"><span class=\"card-cell-label\">Default</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">image_urls</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>https_url|data_image_url[]</code></td><td data-cell-label=\"Requirement\"><span class=\"card-cell-label\">Requirement</span>Required</td><td data-cell-label=\"Values &amp; limits\"><span class=\"card-cell-label\">Values &amp; limits</span><div>Minimum items: 1</div><div>Maximum items: 1</div><div>Maximum decoded bytes: 20,971,520</div><div>MIME types: image/jpeg, image/png, image/webp</div></td><td data-cell-label=\"Default\" data-default=\"unspecified\"><span class=\"card-cell-label\">Default</span>—</td></tr></tbody></table></div><details class=\"card-about\" data-material-combinations><summary>Input material combinations</summary><p class=\"note-s\"><b>first_frame_to_video</b> · Required: image_urls</p></details><details class=\"note-s\" data-method-contract><summary>Method parameters and lifecycle</summary><div class=\"tw\" data-card-table=\"contract\"><table><thead><tr><th>Parameter</th><th>Contract</th></tr></thead><tbody><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>material_types</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>text, image</td></tr><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>required</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>null</td></tr><tr><th data-cell-label=\"Parameter\" scope=\"row\"><span class=\"card-cell-label\">Parameter</span><code>optional_controls</code></th><td data-cell-label=\"Contract\"><span class=\"card-cell-label\">Contract</span>null</td></tr></tbody></table></div><p>Lifecycle: <code>submit_once_poll_original</code></p><p class=\"note-s\"><code>GET /v1/videos/{request_id}</code></p><p class=\"note-s\"><code>GET /v1/videos/generations/{request_id}</code></p><p class=\"note-s\"><code>GET /v1/videos/{request_id}/content</code></p><p class=\"note-s\"><code>GET /v1/videos/generations/{request_id}/content</code></p><p class=\"note-s\">Method shapes and IDs are exact; supplier capability is separate from admission.</p></details></details></section><section class=\"card-section\" data-card-section=\"pricing\"><h3 tabindex=\"-1\">Pricing</h3><h4>Ailoot method rates</h4><section class=\"meth\" data-route=\"Core\"><header><b><span class=\"alias\">Ailoot</span> Video</b><code>POST /v1/videos/generations</code></header><dl><div><dt>Output</dt><dd>$0.18 <em>per second at 1080p</em></dd></div><div><dt>Output</dt><dd>$0.07 <em>per second at 480p</em></dd></div><div><dt>Output</dt><dd>$0.14 <em>per second at 720p</em></dd></div></dl></section><p class=\"note-s\">Ailoot reserves an estimated amount before a request. After the result, it settles the final charge from measured usage. Streaming settlement uses the final usage record. <a href=\"/docs/en/billing/reserve/\">How reservation and settlement work →</a></p></section><section class=\"card-section\" data-card-section=\"examples\"><h3 tabindex=\"-1\">Example requests</h3><h4>Ailoot · Video</h4><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Code options\"><button class=\"cg-tab\" id=\"model-code-9-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-9-panel-0\" aria-selected=\"true\" tabindex=\"0\">Image reference</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Copy code\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-9-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-9-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}&quot;\nexport AILOOT_IMAGE_URL\npython3 - &lt;&lt;&#39;PY_REQUEST&#39;\nimport json,os\nfrom pathlib import Path\np=json.loads(&#39;{&quot;model&quot;: &quot;happyhorse-i2v-latest&quot;, &quot;prompt&quot;: &quot;The subject walks slowly toward the camera.&quot;, &quot;duration&quot;: 5, &quot;resolution&quot;: &quot;720P&quot;}&#39;)\nfrom urllib.parse import urlsplit\nu=os.environ[&quot;AILOOT_IMAGE_URL&quot;]\nz=urlsplit(u)\nif z.scheme!=&quot;https&quot; or not z.netloc or z.username or z.password:raise SystemExit(&quot;Set the actual HTTPS image URL&quot;)\np[&quot;image_urls&quot;]=[u]\nPath(&quot;request.json&quot;).write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -H &#39;Content-Type: application/json&#39; \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - &lt;&lt;&#39;PY_RESULT&#39;\nimport json\nfrom pathlib import Path\nr=json.loads(Path(&quot;result.json&quot;).read_text())\nprint(json.dumps(r))\nPY_RESULT\n</code></pre></div></div></div></section><section class=\"card-section\" data-card-section=\"results\"><h3 tabindex=\"-1\">Receive and save results</h3><h4>Ailoot · Video</h4><p class=\"note-s\">mp4</p><ul class=\"card-result-paths\"><li><code>GET /v1/videos/{request_id}</code></li><li><code>GET /v1/videos/generations/{request_id}</code></li><li><code>GET /v1/videos/{request_id}/content</code></li><li><code>GET /v1/videos/generations/{request_id}/content</code></li></ul><h5>Check job status</h5><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Code options\"><button class=\"cg-tab\" id=\"model-code-10-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-10-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET status</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Copy code\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-10-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-10-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}&quot;\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c &#39;import os,urllib.parse;print(urllib.parse.quote(os.environ[&quot;AILOOT_OPERATION_ID&quot;],safe=&quot;&quot;))&#39;)\ncurl --fail-with-body --silent --show-error &quot;https://api.ailoot.ai/v1/videos/generations/$operation_id&quot; \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o status.json\npython3 - &lt;&lt;&#39;PY_STATUS&#39;\nimport json\nfrom pathlib import Path\nr=json.loads(Path(&quot;status.json&quot;).read_text())\nprint(json.dumps(r))\nif r.get(&quot;status&quot;)==&quot;completed&quot;:\n    for x in r.get(&quot;data&quot;,[]):print(x)\nPY_STATUS\n</code></pre></div></div></div><h5>Save all completed assets</h5><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Code options\"><button class=\"cg-tab\" id=\"model-code-11-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-11-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET all completed assets</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Copy code\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-11-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-11-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}&quot;\nexport AILOOT_STATUS_FILE\npython3 - &lt;&lt;&#39;PY_REQUEST&#39;\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[&quot;AILOOT_STATUS_FILE&quot;])\nif not f.is_file():raise SystemExit(&quot;Choose the actual completed status file&quot;)\nr=json.loads(f.read_text())\nif r.get(&quot;status&quot;)!=&quot;completed&quot; or not isinstance(r.get(&quot;data&quot;),list) or not r[&quot;data&quot;]:raise SystemExit(&quot;Wait for a completed status with asset paths&quot;)\nurls=[]\nfor x in r[&quot;data&quot;]:\n    if not isinstance(x,str) or &quot;\\n&quot; in x or &quot;\\r&quot; in x:raise SystemExit(&quot;Invalid asset path&quot;)\n    u=urljoin(&quot;https://api.ailoot.ai&quot;,x)\n    z=urlsplit(u)\n    if z.scheme!=&quot;https&quot; or z.netloc!=&quot;api.ailoot.ai&quot; or z.username or z.password:raise SystemExit(&quot;Use the actual Ailoot asset paths from status&quot;)\n    urls.append(u)\nPath(&quot;asset-urls.txt&quot;).write_text(&quot;\\n&quot;.join(urls)+&quot;\\n&quot;)\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error &quot;$asset_url&quot; \\\n    -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o &quot;video-${index}.mp4&quot;\n  index=$((index + 1))\ndone &lt; asset-urls.txt\n</code></pre></div></div></div><details class=\"card-about\"><summary>Other content reads</summary><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Code options\"><button class=\"cg-tab\" id=\"model-code-12-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-12-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET content</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Copy code\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-12-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-12-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}&quot;\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c &#39;import os,urllib.parse;print(urllib.parse.quote(os.environ[&quot;AILOOT_OPERATION_ID&quot;],safe=&quot;&quot;))&#39;)\ncurl --fail-with-body --silent --show-error &quot;https://api.ailoot.ai/v1/videos/generations/$operation_id/content&quot; \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o video.mp4\n</code></pre></div></div></div></details><div class=\"card-result-process\" data-all-results><h5>Keep all completed results</h5><p class=\"note-s\">Save every completed video or returned file; retrieve every actual returned asset URL.</p><p class=\"note-s\">Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.</p></div><div class=\"card-result-process\" data-unknown-recovery><h5>If the original response needs checking</h5><p class=\"note-s\">Read existing original job; never resubmit unknown send.</p></div><details class=\"card-about\" data-output-fields><summary>Response fields</summary><div class=\"tw\" data-card-table=\"output\"><table><thead><tr><th>Field</th><th>Type</th></tr></thead><tbody><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">id</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">object</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">model</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">status</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">content_url</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>signed URL</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">data[]</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>signed URL</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">usage</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>object</td></tr><tr><th data-cell-label=\"Field\" scope=\"row\"><span class=\"card-cell-label\">Field</span><code class=\"card-field-name\">result_pending_check</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>boolean</td></tr></tbody></table></div></details><details class=\"card-about\" data-method-errors><summary>Errors and next steps</summary><div class=\"tw\" data-card-table=\"errors\"><table><thead><tr><th>Response</th><th>Condition</th><th>Next step</th></tr></thead><tbody><tr><th data-cell-label=\"Response\" scope=\"row\"><span class=\"card-cell-label\">Response</span>400 · <code>invalid_request_error</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>Invalid required fields, material representation or parameter value</td><td data-cell-label=\"Next step\"><span class=\"card-cell-label\">Next step</span>Correct the indicated fields before a new creation request.</td></tr><tr><th data-cell-label=\"Response\" scope=\"row\"><span class=\"card-cell-label\">Response</span>409 · <code>video_not_ready</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>Original result content is not yet available</td><td data-cell-label=\"Next step\"><span class=\"card-cell-label\">Next step</span>Poll the original returned ID and respect Retry-After.</td></tr><tr><th data-cell-label=\"Response\" scope=\"row\"><span class=\"card-cell-label\">Response</span><code>server_error</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>The returned response says the operation or result requires a check</td><td data-cell-label=\"Next step\"><span class=\"card-cell-label\">Next step</span>Keep the original returned operation/task ID, request headers and response; continue supported reads of that original operation. Do not resubmit the creation request.</td></tr></tbody></table></div></details></section><section class=\"card-section\" data-card-section=\"aliases\"><h3 tabindex=\"-1\">Aliases</h3><h4>Model aliases</h4><p class=\"note-s\"><span data-model-alias-route=\"Core\"><b>Ailoot</b> <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-1.1-i2v&amp;fmt=videos\"><code>happyhorse-1.1-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v&amp;fmt=videos\"><code>happyhorse-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v-latest&amp;fmt=videos\"><code>happyhorse-i2v-latest</code></a></span></p><h4>Method path aliases</h4><p class=\"note-s\">Use the method paths shown above.</p><h4>Related caller IDs</h4><p class=\"note-s\"><a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-1.1-i2v&amp;fmt=videos\"><code>happyhorse-1.1-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v&amp;fmt=videos\"><code>happyhorse-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v-latest&amp;fmt=videos\"><code>happyhorse-i2v-latest</code></a></p></section></div>",
      "method_identity": {
        "effective_request_model_id": "happyhorse-i2v-latest",
        "fmt": "videos",
        "http": "POST",
        "path": "/v1/videos/generations",
        "request_model_id": "happyhorse-i2v-latest",
        "route_label": "Core"
      },
      "method_key": "Core|videos|/v1/videos/generations|happyhorse-i2v-latest",
      "ordinal": 2,
      "rawMethod": {
        "cache_read": null,
        "cache_write": null,
        "cache_write_1h": null,
        "cache_write_5m": null,
        "conditional_meter": null,
        "contract": {
          "data": {
            "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
            "errors": [
              {
                "code": null,
                "condition": "Invalid required fields, material representation or parameter value",
                "http_status": 400,
                "recovery": "Correct the indicated fields before a new creation request.",
                "type": "invalid_request_error"
              },
              {
                "code": null,
                "condition": "Original result content is not yet available",
                "http_status": 409,
                "recovery": "Poll the original returned ID and respect Retry-After.",
                "type": "video_not_ready"
              },
              {
                "code": null,
                "condition": "The returned response says the operation or result requires a check",
                "http_status": null,
                "recovery": "Keep the original returned operation/task ID, request headers and response; continue supported reads of that original operation. Do not resubmit the creation request.",
                "type": "server_error"
              }
            ],
            "hints": [],
            "ignored_fields": [],
            "lifecycle": {
              "all_results": "Follow everyactualreturnedoutputandownedasset; no result is discardedbecauseindex0orcontent_urlalreadyexists.",
              "content": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}/content"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}/content"
                }
              ],
              "create": {
                "http": "POST",
                "path": "/v1/videos/generations"
              },
              "id_source": "Actualreturnedpublicid; opaque URLencodeit forGET",
              "mode": "submit_once_poll_original",
              "multioutputs": "retain every completed data output; index0 alone is not all outputs",
              "operation_id_is_not_task_id": true,
              "owned_result": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}"
              },
              "status": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}"
                }
              ],
              "submit_status": 202,
              "unknown": "Read existing original job; never resubmit unknown send.",
              "unknown_no_replay": true
            },
            "material_combinations": [
              {
                "mode": "first_frame_to_video",
                "required": [
                  "image_urls"
                ]
              }
            ],
            "media_library": {
              "asset": {
                "fields": [
                  {
                    "description": null,
                    "name": "asset_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "task_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "output_key",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "family",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "model",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "method",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "status",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "content_type",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "sha256",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "size_bytes",
                    "type": "integer"
                  },
                  {
                    "description": null,
                    "name": "content_url",
                    "type": "string"
                  }
                ],
                "http": "GET",
                "id_source": "actual returned asset_id",
                "path": "/v1/media/assets/{asset_id}"
              },
              "content": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}/content",
                "range_header_supported": true,
                "url_source": "Use exact returned signed content_url including its token; do not construct a token."
              },
              "expired_link": {
                "code": "link_expired",
                "http_status": 404,
                "recovery": "Read the asset again to obtain its refreshed signed content_url, then fetch that URL. Do not regenerate."
              },
              "list": {
                "all_pages": "Follow every returned next_cursor, then select records by their actual task_id/output_key.",
                "http": "GET",
                "output_fields": [
                  {
                    "description": null,
                    "name": "object",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "data",
                    "type": "asset[]"
                  },
                  {
                    "description": null,
                    "name": "next_cursor",
                    "type": "string|null"
                  }
                ],
                "parameters": [
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "family",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "cursor",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": 20,
                    "default_known": true,
                    "enum": null,
                    "enum_known": false,
                    "maximum": 100,
                    "minimum": 1,
                    "name": "limit",
                    "required": false,
                    "type": "integer"
                  }
                ],
                "path": "/v1/media/assets"
              },
              "revoke": {
                "http": "DELETE",
                "meaning": "Revokes/deletes the existing owned file; this is not generation cancellation.",
                "path": "/v1/media/assets/{asset_id}",
                "pending_status": "revoking",
                "success_statuses": [
                  202,
                  204
                ]
              },
              "task": {
                "http": "GET",
                "id_source": "actual returned task_id or media library record; operation_id is not task_id",
                "path": "/v1/media/tasks/{task_id}"
              }
            },
            "operation_modes": [
              "videos"
            ],
            "outputs": {
              "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
              "content_selection": "Oneownedvideo; use actualreturnedcontent_url/data[] ororiginalcontentread. No indexedselection field is promised by thisCorehandler.",
              "create_status": 202,
              "family": "video",
              "fields": [
                {
                  "description": null,
                  "name": "id",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "object",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "model",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "status",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "content_url",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "data[]",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "usage",
                  "type": "object"
                },
                {
                  "description": null,
                  "name": "result_pending_check",
                  "type": "boolean"
                }
              ],
              "format": "mp4"
            },
            "parameters": [
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": [
                  "happyhorse-i2v-latest"
                ],
                "enum_known": true,
                "name": "model",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "min_length": 1,
                "name": "prompt",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": 5,
                "default_known": true,
                "enum": null,
                "enum_known": false,
                "maximum": 15,
                "minimum": 3,
                "name": "duration",
                "required": false,
                "type": "integer",
                "unit": "seconds"
              },
              {
                "availability": "source_interface",
                "default": "720P",
                "default_known": true,
                "enum": [
                  "480P",
                  "720P",
                  "1080P"
                ],
                "enum_known": true,
                "name": "resolution",
                "required": false,
                "type": "string"
              },
              {
                "availability": "unsupported",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "name": "ratio",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maximum_decoded_bytes": 20971520,
                "maximum_items": 1,
                "mime_types": [
                  "image/jpeg",
                  "image/png",
                  "image/webp"
                ],
                "minimum_items": 1,
                "name": "image_urls",
                "required": true,
                "type": "https_url|data_image_url[]"
              }
            ],
            "profile_binding": "Exact existing Ailoot model and method; interface constraints below do not assert provider qualification.",
            "unsupported": [
              "ratiofield"
            ]
          },
          "hints": [
            "Method shapes and IDs are exact; supplier capability is separate from admission."
          ],
          "input": {
            "material_types": [
              "text",
              "image"
            ],
            "optional_controls": null,
            "required": null
          },
          "lifecycle": {
            "content": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}/content",
                "query": {
                  "index": "actual output index; default0"
                }
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}/content"
              }
            ],
            "id_source": "only actual ID/path from creation/status",
            "mode": "submit_once_poll_original",
            "multioutputs": "retain every completed data output; index0 alone is not all outputs",
            "owned_result": {
              "http": "GET",
              "path": "/v1/media/assets/{asset_id}"
            },
            "status": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}"
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}"
              }
            ],
            "submit_status": 202,
            "unknown": "Read existing original job; never resubmit unknown send."
          },
          "method": {
            "http": "POST",
            "path": "/v1/videos/generations"
          },
          "operation_modes": [
            "videos"
          ],
          "output": {
            "family": [
              "video"
            ],
            "format": null,
            "multioutputs": "retain every actual response output"
          }
        },
        "ctx": null,
        "examples": [
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}\"\nexport AILOOT_IMAGE_URL\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\np=json.loads('{\"model\": \"happyhorse-i2v-latest\", \"prompt\": \"The subject walks slowly toward the camera.\", \"duration\": 5, \"resolution\": \"720P\"}')\nfrom urllib.parse import urlsplit\nu=os.environ[\"AILOOT_IMAGE_URL\"]\nz=urlsplit(u)\nif z.scheme!=\"https\" or not z.netloc or z.username or z.password:raise SystemExit(\"Set the actual HTTPS image URL\")\np[\"image_urls\"]=[u]\nPath(\"request.json\").write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -H 'Content-Type: application/json' \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - <<'PY_RESULT'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"result.json\").read_text())\nprint(json.dumps(r))\nPY_RESULT\n",
            "label": "Use your actual image reference",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o status.json\npython3 - <<'PY_STATUS'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"status.json\").read_text())\nprint(json.dumps(r))\nif r.get(\"status\")==\"completed\":\n    for x in r.get(\"data\",[]):print(x)\nPY_STATUS\n",
            "label": "GET status",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id/content\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o video.mp4\n",
            "label": "GET content",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}\"\nexport AILOOT_STATUS_FILE\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[\"AILOOT_STATUS_FILE\"])\nif not f.is_file():raise SystemExit(\"Choose the actual completed status file\")\nr=json.loads(f.read_text())\nif r.get(\"status\")!=\"completed\" or not isinstance(r.get(\"data\"),list) or not r[\"data\"]:raise SystemExit(\"Wait for a completed status with asset paths\")\nurls=[]\nfor x in r[\"data\"]:\n    if not isinstance(x,str) or \"\\n\" in x or \"\\r\" in x:raise SystemExit(\"Invalid asset path\")\n    u=urljoin(\"https://api.ailoot.ai\",x)\n    z=urlsplit(u)\n    if z.scheme!=\"https\" or z.netloc!=\"api.ailoot.ai\" or z.username or z.password:raise SystemExit(\"Use the actual Ailoot asset paths from status\")\n    urls.append(u)\nPath(\"asset-urls.txt\").write_text(\"\\n\".join(urls)+\"\\n\")\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error \"$asset_url\" \\\n    -H \"Authorization: Bearer $AILOOT_API_KEY\" -o \"video-${index}.mp4\"\n  index=$((index + 1))\ndone < asset-urls.txt\n",
            "label": "GET all completed assets",
            "language": "bash"
          }
        ],
        "family": "openai",
        "fast_multiplier": null,
        "flex_multiplier": null,
        "fmt": "videos",
        "http": "POST",
        "img_in": null,
        "img_out": null,
        "in": null,
        "input": [
          "text",
          "image"
        ],
        "label": "Video",
        "max_out": null,
        "max_tool_calls": null,
        "out": null,
        "output": [
          "video"
        ],
        "path": "/v1/videos/generations",
        "pricing_profiles": [
          {
            "dimensions": {},
            "label": "Core",
            "units": [
              {
                "amount": 0.18,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_1080p_second",
                "label": "per second at 1080p",
                "side": "out"
              },
              {
                "amount": 0.07,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_480p_second",
                "label": "per second at 480p",
                "side": "out"
              },
              {
                "amount": 0.14,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_720p_second",
                "label": "per second at 720p",
                "side": "out"
              }
            ]
          }
        ],
        "request_model_id": "happyhorse-i2v-latest",
        "route_label": "Core",
        "status_reads": [
          "GET /v1/videos/generations/{id}",
          "GET /v1/videos/generations/{id}/content"
        ],
        "tiers": [],
        "tool_prices": null,
        "unit": "conditional",
        "units": [
          {
            "key": "video_output_1080p_second",
            "label": "per second at 1080p",
            "side": "out",
            "usd": 0.18
          },
          {
            "key": "video_output_480p_second",
            "label": "per second at 480p",
            "side": "out",
            "usd": 0.07
          },
          {
            "key": "video_output_720p_second",
            "label": "per second at 720p",
            "side": "out",
            "usd": 0.14
          }
        ]
      }
    }
  ],
  "model_id": "happyhorse-1.1-i2v",
  "nativeProvenance": {
    "input_facts_canonical_sha256": "23cf7f373a6799f0acd6192681cf0b2c3ff7642a3e1040a7b923a84fbf14b141",
    "input_html_sha256": "41687795e4a61db9115a89ae333b548d5218cad908e50008531751ea9e3c6922",
    "private_audit_sha256": "87a8f505d2b7c9c40d94401e161a53a858fa7f4eafe35993cddb5484a3fb715f",
    "role": "historical-normalized-input-audit-hashes",
    "schema": "ailoot-native-model-provenance-v2"
  },
  "page": {
    "canonical": "https://ailoot.ai/models/en/happyhorse-1-1-i2v/",
    "description": "An image-to-video model: the source image provides the first frame, and the prompt guides the subsequent motion. Creates a short video with optional accompanying audio.",
    "locale": "en",
    "md_url": "https://ailoot.ai/models/en/happyhorse-1-1-i2v/index.md",
    "title": "happyhorse-1.1-i2v — Ailoot",
    "url": "https://ailoot.ai/models/en/happyhorse-1-1-i2v/"
  },
  "rawModel": {
    "about": "HappyHorse-1.1-I2V is an Alibaba model that starts a video scene from an existing image. The image becomes the first frame, while text can specify what happens next: a character's movement, changes in the scene and the camera's direction. It is suited to animating an illustration, a product photograph or a prepared visual concept.\n\nA text prompt is optional. Without one, the model infers possible motion from the initial image. When a prompt is supplied, the source image determines the composition and the appearance of objects, while the words guide how the scene develops over time.\n\n### From the first frame to motion\n\nAlibaba highlights preservation of character appearance, visual consistency, smooth movement and the combination of visuals with audio. Its stated aims also include stable text and textures. These properties describe the model's intended capabilities; they do not mean that every pixel is literally preserved in every generated frame.\n\nThis mode uses one initial image. It defines the starting scene rather than providing a set of independent references for a new composition. The ability to specify a separate final frame is not stated for this particular version.\n\nJPEG, JPG, PNG and WEBP are accepted. Each dimension of the input image must be at least 300 pixels; the permitted aspect ratio ranges from 1:2.5 to 2.5:1, and the file size limit is 20 MB. The output video's aspect ratio follows the first frame.\n\n### Video parameters\n\nThe duration is selected as an integer from 3 to 15 seconds. Available resolution levels are 480P, 720P and 1080P; the output format is MP4 at 24 frames per second. Audio can be generated alongside the video.\n\nThe prompt may be in any language and contain up to 5000 non-Chinese or 2500 Chinese characters. Any excess is truncated, so important actions and motion details should fit within that limit. The same random seed may produce similar videos, but does not guarantee a frame-by-frame match.",
    "alias_of": null,
    "aliases": [
      "happyhorse-i2v",
      "happyhorse-i2v-latest"
    ],
    "author": "Alibaba",
    "ctx": null,
    "formats": [
      "videos"
    ],
    "id": "happyhorse-1.1-i2v",
    "input": [
      "text",
      "image"
    ],
    "kind": "video",
    "max_out": null,
    "methods": [
      {
        "cache_read": null,
        "cache_write": null,
        "cache_write_1h": null,
        "cache_write_5m": null,
        "conditional_meter": null,
        "contract": {
          "data": {
            "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
            "errors": [
              {
                "code": null,
                "condition": "Invalid required fields, material representation or parameter value",
                "http_status": 400,
                "recovery": "Correct the indicated fields before a new creation request.",
                "type": "invalid_request_error"
              },
              {
                "code": null,
                "condition": "Original result content is not yet available",
                "http_status": 409,
                "recovery": "Poll the original returned ID and respect Retry-After.",
                "type": "video_not_ready"
              },
              {
                "code": null,
                "condition": "The returned response says the operation or result requires a check",
                "http_status": null,
                "recovery": "Keep the original returned operation/task ID, request headers and response; continue supported reads of that original operation. Do not resubmit the creation request.",
                "type": "server_error"
              }
            ],
            "hints": [],
            "ignored_fields": [],
            "lifecycle": {
              "all_results": "Follow everyactualreturnedoutputandownedasset; no result is discardedbecauseindex0orcontent_urlalreadyexists.",
              "content": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}/content"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}/content"
                }
              ],
              "create": {
                "http": "POST",
                "path": "/v1/videos/generations"
              },
              "id_source": "Actualreturnedpublicid; opaque URLencodeit forGET",
              "mode": "submit_once_poll_original",
              "multioutputs": "retain every completed data output; index0 alone is not all outputs",
              "operation_id_is_not_task_id": true,
              "owned_result": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}"
              },
              "status": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}"
                }
              ],
              "submit_status": 202,
              "unknown": "Read existing original job; never resubmit unknown send.",
              "unknown_no_replay": true
            },
            "material_combinations": [
              {
                "mode": "first_frame_to_video",
                "required": [
                  "image_urls"
                ]
              }
            ],
            "media_library": {
              "asset": {
                "fields": [
                  {
                    "description": null,
                    "name": "asset_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "task_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "output_key",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "family",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "model",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "method",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "status",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "content_type",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "sha256",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "size_bytes",
                    "type": "integer"
                  },
                  {
                    "description": null,
                    "name": "content_url",
                    "type": "string"
                  }
                ],
                "http": "GET",
                "id_source": "actual returned asset_id",
                "path": "/v1/media/assets/{asset_id}"
              },
              "content": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}/content",
                "range_header_supported": true,
                "url_source": "Use exact returned signed content_url including its token; do not construct a token."
              },
              "expired_link": {
                "code": "link_expired",
                "http_status": 404,
                "recovery": "Read the asset again to obtain its refreshed signed content_url, then fetch that URL. Do not regenerate."
              },
              "list": {
                "all_pages": "Follow every returned next_cursor, then select records by their actual task_id/output_key.",
                "http": "GET",
                "output_fields": [
                  {
                    "description": null,
                    "name": "object",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "data",
                    "type": "asset[]"
                  },
                  {
                    "description": null,
                    "name": "next_cursor",
                    "type": "string|null"
                  }
                ],
                "parameters": [
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "family",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "cursor",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": 20,
                    "default_known": true,
                    "enum": null,
                    "enum_known": false,
                    "maximum": 100,
                    "minimum": 1,
                    "name": "limit",
                    "required": false,
                    "type": "integer"
                  }
                ],
                "path": "/v1/media/assets"
              },
              "revoke": {
                "http": "DELETE",
                "meaning": "Revokes/deletes the existing owned file; this is not generation cancellation.",
                "path": "/v1/media/assets/{asset_id}",
                "pending_status": "revoking",
                "success_statuses": [
                  202,
                  204
                ]
              },
              "task": {
                "http": "GET",
                "id_source": "actual returned task_id or media library record; operation_id is not task_id",
                "path": "/v1/media/tasks/{task_id}"
              }
            },
            "operation_modes": [
              "first_frame_to_video"
            ],
            "outputs": {
              "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
              "content_selection": "Oneownedvideo; use actualreturnedcontent_url/data[] ororiginalcontentread. No indexedselection field is promised by thisCorehandler.",
              "create_status": 202,
              "family": "video",
              "fields": [
                {
                  "description": null,
                  "name": "id",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "object",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "model",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "status",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "content_url",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "data[]",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "usage",
                  "type": "object"
                },
                {
                  "description": null,
                  "name": "result_pending_check",
                  "type": "boolean"
                }
              ],
              "format": "mp4"
            },
            "parameters": [
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": [
                  "happyhorse-1.1-i2v"
                ],
                "enum_known": true,
                "name": "model",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "min_length": 1,
                "name": "prompt",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": 5,
                "default_known": true,
                "enum": null,
                "enum_known": false,
                "maximum": 15,
                "minimum": 3,
                "name": "duration",
                "required": false,
                "type": "integer",
                "unit": "seconds"
              },
              {
                "availability": "source_interface",
                "default": "720P",
                "default_known": true,
                "enum": [
                  "480P",
                  "720P",
                  "1080P"
                ],
                "enum_known": true,
                "name": "resolution",
                "required": false,
                "type": "string"
              },
              {
                "availability": "unsupported",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "name": "ratio",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maximum_decoded_bytes": 20971520,
                "maximum_items": 1,
                "mime_types": [
                  "image/jpeg",
                  "image/png",
                  "image/webp"
                ],
                "minimum_items": 1,
                "name": "image_urls",
                "required": true,
                "type": "https_url|data_image_url[]"
              }
            ],
            "profile_binding": "Exact existing Ailoot model and method; interface constraints below do not assert provider qualification.",
            "unsupported": [
              "ratiofield"
            ]
          },
          "hints": [
            "Method shapes and IDs are exact; supplier capability is separate from admission."
          ],
          "input": {
            "content_type": "application/json",
            "default_duration": 5,
            "default_resolution": "720P",
            "duration_integer_range": [
              3,
              15
            ],
            "image_urls": {
              "max_count": 1,
              "max_data_image_bytes": 20971520,
              "min_count": 1,
              "schemes": [
                "https",
                "data raster base64"
              ]
            },
            "material_types": [
              "text",
              "image"
            ],
            "optional": [
              "duration",
              "resolution",
              "ratio",
              "prompt"
            ],
            "ratio": [],
            "ratio_must_omit": true,
            "required": [
              "model",
              "image_urls"
            ],
            "resolution": [
              "480P",
              "720P",
              "1080P"
            ]
          },
          "lifecycle": {
            "content": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}/content",
                "query": {
                  "index": "actual output index; default0"
                }
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}/content"
              }
            ],
            "id_source": "only actual ID/path from creation/status",
            "mode": "submit_once_poll_original",
            "multioutputs": "retain every completed data output; index0 alone is not all outputs",
            "owned_result": {
              "http": "GET",
              "path": "/v1/media/assets/{asset_id}"
            },
            "status": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}"
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}"
              }
            ],
            "submit_status": 202,
            "unknown": "Read existing original job; never resubmit unknown send."
          },
          "method": {
            "http": "POST",
            "path": "/v1/videos/generations"
          },
          "operation_modes": [
            "first_frame_to_video"
          ],
          "output": {
            "family": [
              "video"
            ],
            "format": null,
            "multioutputs": "retain every actual response output"
          }
        },
        "ctx": null,
        "examples": [
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}\"\nexport AILOOT_IMAGE_URL\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\np=json.loads('{\"model\": \"happyhorse-1.1-i2v\", \"prompt\": \"The subject walks slowly toward the camera.\", \"duration\": 5, \"resolution\": \"720P\"}')\nfrom urllib.parse import urlsplit\nu=os.environ[\"AILOOT_IMAGE_URL\"]\nz=urlsplit(u)\nif z.scheme!=\"https\" or not z.netloc or z.username or z.password:raise SystemExit(\"Set the actual HTTPS image URL\")\np[\"image_urls\"]=[u]\nPath(\"request.json\").write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -H 'Content-Type: application/json' \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - <<'PY_RESULT'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"result.json\").read_text())\nprint(json.dumps(r))\nPY_RESULT\n",
            "label": "Use your actual image reference",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o status.json\npython3 - <<'PY_STATUS'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"status.json\").read_text())\nprint(json.dumps(r))\nif r.get(\"status\")==\"completed\":\n    for x in r.get(\"data\",[]):print(x)\nPY_STATUS\n",
            "label": "GET status",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id/content\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o video.mp4\n",
            "label": "GET content",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}\"\nexport AILOOT_STATUS_FILE\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[\"AILOOT_STATUS_FILE\"])\nif not f.is_file():raise SystemExit(\"Choose the actual completed status file\")\nr=json.loads(f.read_text())\nif r.get(\"status\")!=\"completed\" or not isinstance(r.get(\"data\"),list) or not r[\"data\"]:raise SystemExit(\"Wait for a completed status with asset paths\")\nurls=[]\nfor x in r[\"data\"]:\n    if not isinstance(x,str) or \"\\n\" in x or \"\\r\" in x:raise SystemExit(\"Invalid asset path\")\n    u=urljoin(\"https://api.ailoot.ai\",x)\n    z=urlsplit(u)\n    if z.scheme!=\"https\" or z.netloc!=\"api.ailoot.ai\" or z.username or z.password:raise SystemExit(\"Use the actual Ailoot asset paths from status\")\n    urls.append(u)\nPath(\"asset-urls.txt\").write_text(\"\\n\".join(urls)+\"\\n\")\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error \"$asset_url\" \\\n    -H \"Authorization: Bearer $AILOOT_API_KEY\" -o \"video-${index}.mp4\"\n  index=$((index + 1))\ndone < asset-urls.txt\n",
            "label": "GET all completed assets",
            "language": "bash"
          }
        ],
        "family": "openai",
        "fast_multiplier": null,
        "flex_multiplier": null,
        "fmt": "videos",
        "http": "POST",
        "img_in": null,
        "img_out": null,
        "in": null,
        "input": [
          "text",
          "image"
        ],
        "label": "Video",
        "max_out": null,
        "max_tool_calls": null,
        "out": null,
        "output": [
          "video"
        ],
        "path": "/v1/videos/generations",
        "pricing_profiles": [
          {
            "dimensions": {},
            "label": "Core",
            "units": [
              {
                "amount": 0.18,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_1080p_second",
                "label": "per second at 1080p",
                "side": "out"
              },
              {
                "amount": 0.07,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_480p_second",
                "label": "per second at 480p",
                "side": "out"
              },
              {
                "amount": 0.14,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_720p_second",
                "label": "per second at 720p",
                "side": "out"
              }
            ]
          }
        ],
        "request_model_id": "happyhorse-1.1-i2v",
        "route_label": "Core",
        "status_reads": [
          "GET /v1/videos/generations/{id}",
          "GET /v1/videos/generations/{id}/content"
        ],
        "tiers": [],
        "tool_prices": null,
        "unit": "conditional",
        "units": [
          {
            "key": "video_output_1080p_second",
            "label": "per second at 1080p",
            "side": "out",
            "usd": 0.18
          },
          {
            "key": "video_output_480p_second",
            "label": "per second at 480p",
            "side": "out",
            "usd": 0.07
          },
          {
            "key": "video_output_720p_second",
            "label": "per second at 720p",
            "side": "out",
            "usd": 0.14
          }
        ]
      },
      {
        "cache_read": null,
        "cache_write": null,
        "cache_write_1h": null,
        "cache_write_5m": null,
        "conditional_meter": null,
        "contract": {
          "data": {
            "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
            "errors": [
              {
                "code": null,
                "condition": "Invalid required fields, material representation or parameter value",
                "http_status": 400,
                "recovery": "Correct the indicated fields before a new creation request.",
                "type": "invalid_request_error"
              },
              {
                "code": null,
                "condition": "Original result content is not yet available",
                "http_status": 409,
                "recovery": "Poll the original returned ID and respect Retry-After.",
                "type": "video_not_ready"
              },
              {
                "code": null,
                "condition": "The returned response says the operation or result requires a check",
                "http_status": null,
                "recovery": "Keep the original returned operation/task ID, request headers and response; continue supported reads of that original operation. Do not resubmit the creation request.",
                "type": "server_error"
              }
            ],
            "hints": [],
            "ignored_fields": [],
            "lifecycle": {
              "all_results": "Follow everyactualreturnedoutputandownedasset; no result is discardedbecauseindex0orcontent_urlalreadyexists.",
              "content": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}/content"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}/content"
                }
              ],
              "create": {
                "http": "POST",
                "path": "/v1/videos/generations"
              },
              "id_source": "Actualreturnedpublicid; opaque URLencodeit forGET",
              "mode": "submit_once_poll_original",
              "multioutputs": "retain every completed data output; index0 alone is not all outputs",
              "operation_id_is_not_task_id": true,
              "owned_result": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}"
              },
              "status": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}"
                }
              ],
              "submit_status": 202,
              "unknown": "Read existing original job; never resubmit unknown send.",
              "unknown_no_replay": true
            },
            "material_combinations": [
              {
                "mode": "first_frame_to_video",
                "required": [
                  "image_urls"
                ]
              }
            ],
            "media_library": {
              "asset": {
                "fields": [
                  {
                    "description": null,
                    "name": "asset_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "task_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "output_key",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "family",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "model",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "method",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "status",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "content_type",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "sha256",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "size_bytes",
                    "type": "integer"
                  },
                  {
                    "description": null,
                    "name": "content_url",
                    "type": "string"
                  }
                ],
                "http": "GET",
                "id_source": "actual returned asset_id",
                "path": "/v1/media/assets/{asset_id}"
              },
              "content": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}/content",
                "range_header_supported": true,
                "url_source": "Use exact returned signed content_url including its token; do not construct a token."
              },
              "expired_link": {
                "code": "link_expired",
                "http_status": 404,
                "recovery": "Read the asset again to obtain its refreshed signed content_url, then fetch that URL. Do not regenerate."
              },
              "list": {
                "all_pages": "Follow every returned next_cursor, then select records by their actual task_id/output_key.",
                "http": "GET",
                "output_fields": [
                  {
                    "description": null,
                    "name": "object",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "data",
                    "type": "asset[]"
                  },
                  {
                    "description": null,
                    "name": "next_cursor",
                    "type": "string|null"
                  }
                ],
                "parameters": [
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "family",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "cursor",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": 20,
                    "default_known": true,
                    "enum": null,
                    "enum_known": false,
                    "maximum": 100,
                    "minimum": 1,
                    "name": "limit",
                    "required": false,
                    "type": "integer"
                  }
                ],
                "path": "/v1/media/assets"
              },
              "revoke": {
                "http": "DELETE",
                "meaning": "Revokes/deletes the existing owned file; this is not generation cancellation.",
                "path": "/v1/media/assets/{asset_id}",
                "pending_status": "revoking",
                "success_statuses": [
                  202,
                  204
                ]
              },
              "task": {
                "http": "GET",
                "id_source": "actual returned task_id or media library record; operation_id is not task_id",
                "path": "/v1/media/tasks/{task_id}"
              }
            },
            "operation_modes": [
              "videos"
            ],
            "outputs": {
              "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
              "content_selection": "Oneownedvideo; use actualreturnedcontent_url/data[] ororiginalcontentread. No indexedselection field is promised by thisCorehandler.",
              "create_status": 202,
              "family": "video",
              "fields": [
                {
                  "description": null,
                  "name": "id",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "object",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "model",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "status",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "content_url",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "data[]",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "usage",
                  "type": "object"
                },
                {
                  "description": null,
                  "name": "result_pending_check",
                  "type": "boolean"
                }
              ],
              "format": "mp4"
            },
            "parameters": [
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": [
                  "happyhorse-i2v"
                ],
                "enum_known": true,
                "name": "model",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "min_length": 1,
                "name": "prompt",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": 5,
                "default_known": true,
                "enum": null,
                "enum_known": false,
                "maximum": 15,
                "minimum": 3,
                "name": "duration",
                "required": false,
                "type": "integer",
                "unit": "seconds"
              },
              {
                "availability": "source_interface",
                "default": "720P",
                "default_known": true,
                "enum": [
                  "480P",
                  "720P",
                  "1080P"
                ],
                "enum_known": true,
                "name": "resolution",
                "required": false,
                "type": "string"
              },
              {
                "availability": "unsupported",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "name": "ratio",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maximum_decoded_bytes": 20971520,
                "maximum_items": 1,
                "mime_types": [
                  "image/jpeg",
                  "image/png",
                  "image/webp"
                ],
                "minimum_items": 1,
                "name": "image_urls",
                "required": true,
                "type": "https_url|data_image_url[]"
              }
            ],
            "profile_binding": "Exact existing Ailoot model and method; interface constraints below do not assert provider qualification.",
            "unsupported": [
              "ratiofield"
            ]
          },
          "hints": [
            "Method shapes and IDs are exact; supplier capability is separate from admission."
          ],
          "input": {
            "material_types": [
              "text",
              "image"
            ],
            "optional_controls": null,
            "required": null
          },
          "lifecycle": {
            "content": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}/content",
                "query": {
                  "index": "actual output index; default0"
                }
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}/content"
              }
            ],
            "id_source": "only actual ID/path from creation/status",
            "mode": "submit_once_poll_original",
            "multioutputs": "retain every completed data output; index0 alone is not all outputs",
            "owned_result": {
              "http": "GET",
              "path": "/v1/media/assets/{asset_id}"
            },
            "status": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}"
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}"
              }
            ],
            "submit_status": 202,
            "unknown": "Read existing original job; never resubmit unknown send."
          },
          "method": {
            "http": "POST",
            "path": "/v1/videos/generations"
          },
          "operation_modes": [
            "videos"
          ],
          "output": {
            "family": [
              "video"
            ],
            "format": null,
            "multioutputs": "retain every actual response output"
          }
        },
        "ctx": null,
        "examples": [
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}\"\nexport AILOOT_IMAGE_URL\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\np=json.loads('{\"model\": \"happyhorse-i2v\", \"prompt\": \"The subject walks slowly toward the camera.\", \"duration\": 5, \"resolution\": \"720P\"}')\nfrom urllib.parse import urlsplit\nu=os.environ[\"AILOOT_IMAGE_URL\"]\nz=urlsplit(u)\nif z.scheme!=\"https\" or not z.netloc or z.username or z.password:raise SystemExit(\"Set the actual HTTPS image URL\")\np[\"image_urls\"]=[u]\nPath(\"request.json\").write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -H 'Content-Type: application/json' \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - <<'PY_RESULT'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"result.json\").read_text())\nprint(json.dumps(r))\nPY_RESULT\n",
            "label": "Use your actual image reference",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o status.json\npython3 - <<'PY_STATUS'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"status.json\").read_text())\nprint(json.dumps(r))\nif r.get(\"status\")==\"completed\":\n    for x in r.get(\"data\",[]):print(x)\nPY_STATUS\n",
            "label": "GET status",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id/content\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o video.mp4\n",
            "label": "GET content",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}\"\nexport AILOOT_STATUS_FILE\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[\"AILOOT_STATUS_FILE\"])\nif not f.is_file():raise SystemExit(\"Choose the actual completed status file\")\nr=json.loads(f.read_text())\nif r.get(\"status\")!=\"completed\" or not isinstance(r.get(\"data\"),list) or not r[\"data\"]:raise SystemExit(\"Wait for a completed status with asset paths\")\nurls=[]\nfor x in r[\"data\"]:\n    if not isinstance(x,str) or \"\\n\" in x or \"\\r\" in x:raise SystemExit(\"Invalid asset path\")\n    u=urljoin(\"https://api.ailoot.ai\",x)\n    z=urlsplit(u)\n    if z.scheme!=\"https\" or z.netloc!=\"api.ailoot.ai\" or z.username or z.password:raise SystemExit(\"Use the actual Ailoot asset paths from status\")\n    urls.append(u)\nPath(\"asset-urls.txt\").write_text(\"\\n\".join(urls)+\"\\n\")\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error \"$asset_url\" \\\n    -H \"Authorization: Bearer $AILOOT_API_KEY\" -o \"video-${index}.mp4\"\n  index=$((index + 1))\ndone < asset-urls.txt\n",
            "label": "GET all completed assets",
            "language": "bash"
          }
        ],
        "family": "openai",
        "fast_multiplier": null,
        "flex_multiplier": null,
        "fmt": "videos",
        "http": "POST",
        "img_in": null,
        "img_out": null,
        "in": null,
        "input": [
          "text",
          "image"
        ],
        "label": "Video",
        "max_out": null,
        "max_tool_calls": null,
        "out": null,
        "output": [
          "video"
        ],
        "path": "/v1/videos/generations",
        "pricing_profiles": [
          {
            "dimensions": {},
            "label": "Core",
            "units": [
              {
                "amount": 0.18,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_1080p_second",
                "label": "per second at 1080p",
                "side": "out"
              },
              {
                "amount": 0.07,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_480p_second",
                "label": "per second at 480p",
                "side": "out"
              },
              {
                "amount": 0.14,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_720p_second",
                "label": "per second at 720p",
                "side": "out"
              }
            ]
          }
        ],
        "request_model_id": "happyhorse-i2v",
        "route_label": "Core",
        "status_reads": [
          "GET /v1/videos/generations/{id}",
          "GET /v1/videos/generations/{id}/content"
        ],
        "tiers": [],
        "tool_prices": null,
        "unit": "conditional",
        "units": [
          {
            "key": "video_output_1080p_second",
            "label": "per second at 1080p",
            "side": "out",
            "usd": 0.18
          },
          {
            "key": "video_output_480p_second",
            "label": "per second at 480p",
            "side": "out",
            "usd": 0.07
          },
          {
            "key": "video_output_720p_second",
            "label": "per second at 720p",
            "side": "out",
            "usd": 0.14
          }
        ]
      },
      {
        "cache_read": null,
        "cache_write": null,
        "cache_write_1h": null,
        "cache_write_5m": null,
        "conditional_meter": null,
        "contract": {
          "data": {
            "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
            "errors": [
              {
                "code": null,
                "condition": "Invalid required fields, material representation or parameter value",
                "http_status": 400,
                "recovery": "Correct the indicated fields before a new creation request.",
                "type": "invalid_request_error"
              },
              {
                "code": null,
                "condition": "Original result content is not yet available",
                "http_status": 409,
                "recovery": "Poll the original returned ID and respect Retry-After.",
                "type": "video_not_ready"
              },
              {
                "code": null,
                "condition": "The returned response says the operation or result requires a check",
                "http_status": null,
                "recovery": "Keep the original returned operation/task ID, request headers and response; continue supported reads of that original operation. Do not resubmit the creation request.",
                "type": "server_error"
              }
            ],
            "hints": [],
            "ignored_fields": [],
            "lifecycle": {
              "all_results": "Follow everyactualreturnedoutputandownedasset; no result is discardedbecauseindex0orcontent_urlalreadyexists.",
              "content": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}/content"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}/content"
                }
              ],
              "create": {
                "http": "POST",
                "path": "/v1/videos/generations"
              },
              "id_source": "Actualreturnedpublicid; opaque URLencodeit forGET",
              "mode": "submit_once_poll_original",
              "multioutputs": "retain every completed data output; index0 alone is not all outputs",
              "operation_id_is_not_task_id": true,
              "owned_result": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}"
              },
              "status": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}"
                }
              ],
              "submit_status": 202,
              "unknown": "Read existing original job; never resubmit unknown send.",
              "unknown_no_replay": true
            },
            "material_combinations": [
              {
                "mode": "first_frame_to_video",
                "required": [
                  "image_urls"
                ]
              }
            ],
            "media_library": {
              "asset": {
                "fields": [
                  {
                    "description": null,
                    "name": "asset_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "task_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "output_key",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "family",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "model",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "method",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "status",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "content_type",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "sha256",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "size_bytes",
                    "type": "integer"
                  },
                  {
                    "description": null,
                    "name": "content_url",
                    "type": "string"
                  }
                ],
                "http": "GET",
                "id_source": "actual returned asset_id",
                "path": "/v1/media/assets/{asset_id}"
              },
              "content": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}/content",
                "range_header_supported": true,
                "url_source": "Use exact returned signed content_url including its token; do not construct a token."
              },
              "expired_link": {
                "code": "link_expired",
                "http_status": 404,
                "recovery": "Read the asset again to obtain its refreshed signed content_url, then fetch that URL. Do not regenerate."
              },
              "list": {
                "all_pages": "Follow every returned next_cursor, then select records by their actual task_id/output_key.",
                "http": "GET",
                "output_fields": [
                  {
                    "description": null,
                    "name": "object",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "data",
                    "type": "asset[]"
                  },
                  {
                    "description": null,
                    "name": "next_cursor",
                    "type": "string|null"
                  }
                ],
                "parameters": [
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "family",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "cursor",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": 20,
                    "default_known": true,
                    "enum": null,
                    "enum_known": false,
                    "maximum": 100,
                    "minimum": 1,
                    "name": "limit",
                    "required": false,
                    "type": "integer"
                  }
                ],
                "path": "/v1/media/assets"
              },
              "revoke": {
                "http": "DELETE",
                "meaning": "Revokes/deletes the existing owned file; this is not generation cancellation.",
                "path": "/v1/media/assets/{asset_id}",
                "pending_status": "revoking",
                "success_statuses": [
                  202,
                  204
                ]
              },
              "task": {
                "http": "GET",
                "id_source": "actual returned task_id or media library record; operation_id is not task_id",
                "path": "/v1/media/tasks/{task_id}"
              }
            },
            "operation_modes": [
              "videos"
            ],
            "outputs": {
              "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
              "content_selection": "Oneownedvideo; use actualreturnedcontent_url/data[] ororiginalcontentread. No indexedselection field is promised by thisCorehandler.",
              "create_status": 202,
              "family": "video",
              "fields": [
                {
                  "description": null,
                  "name": "id",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "object",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "model",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "status",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "content_url",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "data[]",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "usage",
                  "type": "object"
                },
                {
                  "description": null,
                  "name": "result_pending_check",
                  "type": "boolean"
                }
              ],
              "format": "mp4"
            },
            "parameters": [
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": [
                  "happyhorse-i2v-latest"
                ],
                "enum_known": true,
                "name": "model",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "min_length": 1,
                "name": "prompt",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": 5,
                "default_known": true,
                "enum": null,
                "enum_known": false,
                "maximum": 15,
                "minimum": 3,
                "name": "duration",
                "required": false,
                "type": "integer",
                "unit": "seconds"
              },
              {
                "availability": "source_interface",
                "default": "720P",
                "default_known": true,
                "enum": [
                  "480P",
                  "720P",
                  "1080P"
                ],
                "enum_known": true,
                "name": "resolution",
                "required": false,
                "type": "string"
              },
              {
                "availability": "unsupported",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "name": "ratio",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maximum_decoded_bytes": 20971520,
                "maximum_items": 1,
                "mime_types": [
                  "image/jpeg",
                  "image/png",
                  "image/webp"
                ],
                "minimum_items": 1,
                "name": "image_urls",
                "required": true,
                "type": "https_url|data_image_url[]"
              }
            ],
            "profile_binding": "Exact existing Ailoot model and method; interface constraints below do not assert provider qualification.",
            "unsupported": [
              "ratiofield"
            ]
          },
          "hints": [
            "Method shapes and IDs are exact; supplier capability is separate from admission."
          ],
          "input": {
            "material_types": [
              "text",
              "image"
            ],
            "optional_controls": null,
            "required": null
          },
          "lifecycle": {
            "content": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}/content",
                "query": {
                  "index": "actual output index; default0"
                }
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}/content"
              }
            ],
            "id_source": "only actual ID/path from creation/status",
            "mode": "submit_once_poll_original",
            "multioutputs": "retain every completed data output; index0 alone is not all outputs",
            "owned_result": {
              "http": "GET",
              "path": "/v1/media/assets/{asset_id}"
            },
            "status": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}"
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}"
              }
            ],
            "submit_status": 202,
            "unknown": "Read existing original job; never resubmit unknown send."
          },
          "method": {
            "http": "POST",
            "path": "/v1/videos/generations"
          },
          "operation_modes": [
            "videos"
          ],
          "output": {
            "family": [
              "video"
            ],
            "format": null,
            "multioutputs": "retain every actual response output"
          }
        },
        "ctx": null,
        "examples": [
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}\"\nexport AILOOT_IMAGE_URL\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\np=json.loads('{\"model\": \"happyhorse-i2v-latest\", \"prompt\": \"The subject walks slowly toward the camera.\", \"duration\": 5, \"resolution\": \"720P\"}')\nfrom urllib.parse import urlsplit\nu=os.environ[\"AILOOT_IMAGE_URL\"]\nz=urlsplit(u)\nif z.scheme!=\"https\" or not z.netloc or z.username or z.password:raise SystemExit(\"Set the actual HTTPS image URL\")\np[\"image_urls\"]=[u]\nPath(\"request.json\").write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -H 'Content-Type: application/json' \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - <<'PY_RESULT'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"result.json\").read_text())\nprint(json.dumps(r))\nPY_RESULT\n",
            "label": "Use your actual image reference",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o status.json\npython3 - <<'PY_STATUS'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"status.json\").read_text())\nprint(json.dumps(r))\nif r.get(\"status\")==\"completed\":\n    for x in r.get(\"data\",[]):print(x)\nPY_STATUS\n",
            "label": "GET status",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id/content\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o video.mp4\n",
            "label": "GET content",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}\"\nexport AILOOT_STATUS_FILE\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[\"AILOOT_STATUS_FILE\"])\nif not f.is_file():raise SystemExit(\"Choose the actual completed status file\")\nr=json.loads(f.read_text())\nif r.get(\"status\")!=\"completed\" or not isinstance(r.get(\"data\"),list) or not r[\"data\"]:raise SystemExit(\"Wait for a completed status with asset paths\")\nurls=[]\nfor x in r[\"data\"]:\n    if not isinstance(x,str) or \"\\n\" in x or \"\\r\" in x:raise SystemExit(\"Invalid asset path\")\n    u=urljoin(\"https://api.ailoot.ai\",x)\n    z=urlsplit(u)\n    if z.scheme!=\"https\" or z.netloc!=\"api.ailoot.ai\" or z.username or z.password:raise SystemExit(\"Use the actual Ailoot asset paths from status\")\n    urls.append(u)\nPath(\"asset-urls.txt\").write_text(\"\\n\".join(urls)+\"\\n\")\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error \"$asset_url\" \\\n    -H \"Authorization: Bearer $AILOOT_API_KEY\" -o \"video-${index}.mp4\"\n  index=$((index + 1))\ndone < asset-urls.txt\n",
            "label": "GET all completed assets",
            "language": "bash"
          }
        ],
        "family": "openai",
        "fast_multiplier": null,
        "flex_multiplier": null,
        "fmt": "videos",
        "http": "POST",
        "img_in": null,
        "img_out": null,
        "in": null,
        "input": [
          "text",
          "image"
        ],
        "label": "Video",
        "max_out": null,
        "max_tool_calls": null,
        "out": null,
        "output": [
          "video"
        ],
        "path": "/v1/videos/generations",
        "pricing_profiles": [
          {
            "dimensions": {},
            "label": "Core",
            "units": [
              {
                "amount": 0.18,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_1080p_second",
                "label": "per second at 1080p",
                "side": "out"
              },
              {
                "amount": 0.07,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_480p_second",
                "label": "per second at 480p",
                "side": "out"
              },
              {
                "amount": 0.14,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_720p_second",
                "label": "per second at 720p",
                "side": "out"
              }
            ]
          }
        ],
        "request_model_id": "happyhorse-i2v-latest",
        "route_label": "Core",
        "status_reads": [
          "GET /v1/videos/generations/{id}",
          "GET /v1/videos/generations/{id}/content"
        ],
        "tiers": [],
        "tool_prices": null,
        "unit": "conditional",
        "units": [
          {
            "key": "video_output_1080p_second",
            "label": "per second at 1080p",
            "side": "out",
            "usd": 0.18
          },
          {
            "key": "video_output_480p_second",
            "label": "per second at 480p",
            "side": "out",
            "usd": 0.07
          },
          {
            "key": "video_output_720p_second",
            "label": "per second at 720p",
            "side": "out",
            "usd": 0.14
          }
        ]
      }
    ],
    "model_aliases": [
      {
        "canonical_model_id": "happyhorse-1.1-i2v",
        "request_model_id": "happyhorse-1.1-i2v",
        "route_label": "Core"
      },
      {
        "canonical_model_id": "happyhorse-1.1-i2v",
        "request_model_id": "happyhorse-i2v",
        "route_label": "Core"
      },
      {
        "canonical_model_id": "happyhorse-1.1-i2v",
        "request_model_id": "happyhorse-i2v-latest",
        "route_label": "Core"
      }
    ],
    "name": "happyhorse-1.1-i2v",
    "price": {
      "in": null,
      "in_label": null,
      "out": 0.07,
      "out_label": "per second at 480p",
      "sort_in": null,
      "sort_out": null,
      "varies": false
    },
    "short": "An image-to-video model: the source image provides the first frame, and the prompt guides the subsequent motion. Creates a short video with optional accompanying audio."
  },
  "renderer_schema": {
    "method_order": "Original DTO methods order; every exact route/format/path/caller survives.",
    "prices": "Original public DTO fields and original native display HTML; no flattened or normalized offers."
  },
  "representation": "exact-public-dto-and-native-renderer-html",
  "representationNotes": {
    "current_reference": {
      "about_json_pointer": "/aboutHtml",
      "methods": [
        {
          "contract_json_pointer": "/methods/0/rawMethod/contract",
          "html_json_pointer": "/methods/0/html",
          "method_ordinal": 0
        },
        {
          "contract_json_pointer": "/methods/1/rawMethod/contract",
          "html_json_pointer": "/methods/1/html",
          "method_ordinal": 1
        },
        {
          "contract_json_pointer": "/methods/2/rawMethod/contract",
          "html_json_pointer": "/methods/2/html",
          "method_ordinal": 2
        }
      ],
      "role": "current-semantic-reference"
    },
    "raw_input": {
      "examples_role": "historical-input-not-current-ready-examples",
      "json_pointers": [
        "/rawModel",
        "/methods/0/rawMethod",
        "/methods/1/rawMethod",
        "/methods/2/rawMethod"
      ],
      "role": "historical-owner-input"
    },
    "schema": "ailoot-native-model-representations-v1"
  },
  "schema": "ailoot-static-model-facts-v1",
  "schema_version": 1,
  "shortText": "An image-to-video model: the source image provides the first frame, and the prompt guides the subsequent motion. Creates a short video with optional accompanying audio.",
  "source": {
    "audit_sha256": "2e00086bcbfc28e64d0cebe97aa47c17d8d5618963027f8ffb9dc6123d7d25b1",
    "bridge_map_sha256": "1125275768b9636fc8461bc7da5061239a81ddfe508e2557843ca42c58ab0036",
    "raw_model_json_sha256": "c52288bcae4551593854fbc16a3bc94b9283513216f9013e317122ac311d2e93",
    "renderer_sha256": "fed50305bd3bcc4980ac14df23640efb8c1bc1e819f9d53643d6f43e8974d3fe"
  },
  "sourceRevision": "a5df230a78a929a68c6ff96536290419b7c53bab190b476959cfb19b285bf37a"
}
