{
  "openapi": "3.1.0",
  "info": {
    "title": "HappyHorse Video Create API",
    "version": "1.0.0",
    "description": "Create an asynchronous HappyHorse video task through CometAPI. Send text-to-video and reference-image video requests through the same POST /v1/videos multipart endpoint. Save the returned id, poll GET /v1/videos/{task_id}, and download the completed MP4 file."
  },
  "servers": [
    {
      "url": "https://api.cometapi.com"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/v1/videos": {
      "post": {
        "summary": "Create a HappyHorse video task",
        "operationId": "happyhorse_create_video",
        "description": "Create a HappyHorse text-to-video, reference-to-video, or first-frame video task. Send fields as multipart/form-data. For reference-to-video, send 1–9 HTTPS image URLs or 1–9 uploaded image files by repeating input_reference once per image. Use only URLs or only files within input_reference. Use first_frame separately to set the opening frame.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/HappyHorseCreateRequest"
              },
              "encoding": {
                "input_reference": {
                  "contentType": "text/plain, image/jpeg, image/png, image/webp",
                  "style": "form",
                  "explode": true
                },
                "first_frame": {
                  "contentType": "text/plain, image/jpeg, image/png, image/webp"
                }
              },
              "examples": {
                "happyhorse_1_1_text_to_video": {
                  "summary": "HappyHorse 1.1 text-to-video",
                  "value": {
                    "model": "happyhorse-1.1",
                    "prompt": "A close-up cinematic shot of a ceramic coffee cup on a wooden table. Steam rises slowly while morning light moves across the background.",
                    "seconds": 3,
                    "size": "1920x1080"
                  }
                },
                "happyhorse_1_1_reference_to_video": {
                  "summary": "HappyHorse 1.1 reference-to-video",
                  "value": {
                    "model": "happyhorse-1.1",
                    "prompt": "Use the uploaded reference image as the visual guide. Create a short cinematic shot with gentle natural motion.",
                    "seconds": 3,
                    "size": "1280x720",
                    "input_reference": [
                      "@/path/to/reference.png"
                    ]
                  }
                },
                "happyhorse_1_0_text_to_video": {
                  "summary": "HappyHorse 1.0 text-to-video",
                  "value": {
                    "model": "happyhorse-1.0",
                    "prompt": "A person reads beside a tall window while soft daylight moves across the room.",
                    "seconds": 3,
                    "size": "1280x720"
                  }
                },
                "happyhorse_1_1_uploaded_references_to_video": {
                  "summary": "HappyHorse 1.1 multiple reference images",
                  "value": {
                    "model": "happyhorse-1.1",
                    "prompt": "Keep both reference subjects in gentle motion.",
                    "seconds": 3,
                    "size": "1280x720",
                    "input_reference": [
                      "@/path/to/reference-1.png",
                      "@/path/to/reference-2.png"
                    ]
                  }
                },
                "happyhorse_1_1_first_frame_url": {
                  "summary": "HappyHorse 1.1 first frame from URL",
                  "value": {
                    "model": "happyhorse-1.1",
                    "prompt": "Start from this image and slowly pan right.",
                    "seconds": 3,
                    "size": "1280x720",
                    "first_frame": "https://apidoc.cometapi.com/images/image/gemini/6100640_569429.png"
                  }
                },
                "happyhorse_1_1_first_frame_file": {
                  "summary": "HappyHorse 1.1 first frame from file",
                  "value": {
                    "model": "happyhorse-1.1",
                    "prompt": "Start from this image and slowly pan right.",
                    "seconds": 3,
                    "size": "1280x720",
                    "first_frame": "@/path/to/first-frame.png"
                  }
                },
                "happyhorse_1_0_uploaded_references_to_video": {
                  "summary": "HappyHorse 1.0 multiple reference images",
                  "value": {
                    "model": "happyhorse-1.0",
                    "prompt": "Keep both reference subjects in gentle motion.",
                    "seconds": 3,
                    "size": "1280x720",
                    "input_reference": [
                      "@/path/to/reference-1.png",
                      "@/path/to/reference-2.png"
                    ]
                  }
                },
                "happyhorse_1_0_first_frame_url": {
                  "summary": "HappyHorse 1.0 first frame from URL",
                  "value": {
                    "model": "happyhorse-1.0",
                    "prompt": "Start from this image and slowly pan right.",
                    "seconds": 3,
                    "size": "1280x720",
                    "first_frame": "https://apidoc.cometapi.com/images/image/gemini/6100640_569429.png"
                  }
                },
                "happyhorse_1_0_first_frame_file": {
                  "summary": "HappyHorse 1.0 first frame from file",
                  "value": {
                    "model": "happyhorse-1.0",
                    "prompt": "Start from this image and slowly pan right.",
                    "seconds": 3,
                    "size": "1280x720",
                    "first_frame": "@/path/to/first-frame.png"
                  }
                },
                "happyhorse_1_1_reference_image_url": {
                  "summary": "HappyHorse 1.1 reference image URLs",
                  "value": {
                    "model": "happyhorse-1.1",
                    "prompt": "Use both reference images as visual guides. Preserve their visual details with gentle natural motion.",
                    "seconds": 3,
                    "size": "1280x720",
                    "input_reference": [
                      "https://apidoc.cometapi.com/images/image/gemini/6100640_569429.png",
                      "https://apidoc.cometapi.com/images/image/gemini/6100640_569420.png"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Task created. Store the returned id and poll GET /v1/videos/{task_id}.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HappyHorseVideoTask"
                },
                "example": {
                  "id": "task_example",
                  "task_id": "task_example",
                  "object": "video",
                  "model": "happyhorse-1.1",
                  "status": "queued",
                  "progress": 0,
                  "created_at": 1779938152
                }
              }
            }
          },
          "400": {
            "description": "The request is missing a required field or contains a value that the selected model cannot use."
          },
          "401": {
            "description": "The API key is missing or invalid."
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "HappyHorse 1.1 text-to-video",
            "source": "curl https://api.cometapi.com/v1/videos \\\n  -H \"Authorization: Bearer $COMETAPI_KEY\" \\\n  -F model=happyhorse-1.1 \\\n  -F 'prompt=A close-up cinematic shot of a ceramic coffee cup on a wooden table. Steam rises slowly while morning light moves across the background.' \\\n  -F seconds=3 \\\n  -F size=1920x1080"
          },
          {
            "lang": "Python",
            "label": "HappyHorse 1.1 text-to-video",
            "source": "import os\nimport requests\n\nfields = [\n    (\"model\", (None, \"happyhorse-1.1\")),\n    (\"prompt\", (None, \"A close-up cinematic shot of a ceramic coffee cup on a wooden table. Steam rises slowly while morning light moves across the background.\")),\n    (\"seconds\", (None, \"3\")),\n    (\"size\", (None, \"1920x1080\")),\n]\n\nresponse = requests.post(\n    \"https://api.cometapi.com/v1/videos\",\n    headers={\"Authorization\": \"Bearer \" + os.environ[\"COMETAPI_KEY\"]},\n    files=fields,\n    timeout=120,\n)\n\nresponse.raise_for_status()\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "HappyHorse 1.1 text-to-video",
            "source": "const form = new FormData();\nform.append(\"model\", \"happyhorse-1.1\");\nform.append(\"prompt\", \"A close-up cinematic shot of a ceramic coffee cup on a wooden table. Steam rises slowly while morning light moves across the background.\");\nform.append(\"seconds\", \"3\");\nform.append(\"size\", \"1920x1080\");\n\nconst response = await fetch(\"https://api.cometapi.com/v1/videos\", {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.COMETAPI_KEY}` },\n  body: form,\n});\n\nconst result = await response.json();\nconsole.log(result);\n"
          },
          {
            "lang": "Shell",
            "label": "HappyHorse 1.1 reference-to-video",
            "source": "curl https://api.cometapi.com/v1/videos \\\n  -H \"Authorization: Bearer $COMETAPI_KEY\" \\\n  -F model=happyhorse-1.1 \\\n  -F 'prompt=Use the uploaded reference image as the visual guide. Create a short cinematic shot with gentle natural motion.' \\\n  -F seconds=3 \\\n  -F size=1280x720 \\\n  -F 'input_reference=@/path/to/reference.png'"
          },
          {
            "lang": "Python",
            "label": "HappyHorse 1.1 reference-to-video",
            "source": "import os\nimport requests\n\nprompt = \"Use the uploaded reference image as the visual guide. Create a short cinematic shot with gentle natural motion.\"\n\nwith open(\"/path/to/reference.png\", \"rb\") as reference:\n    response = requests.post(\n        \"https://api.cometapi.com/v1/videos\",\n        headers={\"Authorization\": \"Bearer \" + os.environ[\"COMETAPI_KEY\"]},\n        data={\n            \"model\": \"happyhorse-1.1\",\n            \"prompt\": prompt,\n            \"seconds\": \"3\",\n            \"size\": \"1280x720\",\n        },\n        files={\"input_reference\": (\"reference.png\", reference, \"image/png\")},\n        timeout=120,\n    )\n\nresponse.raise_for_status()\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "HappyHorse 1.1 reference-to-video",
            "source": "import { readFile } from \"node:fs/promises\";\n\nconst reference = await readFile(\"/path/to/reference.png\");\n\nconst form = new FormData();\nform.append(\"model\", \"happyhorse-1.1\");\nform.append(\"prompt\", \"Use the uploaded reference image as the visual guide. Create a short cinematic shot with gentle natural motion.\");\nform.append(\"seconds\", \"3\");\nform.append(\"size\", \"1280x720\");\nform.append(\"input_reference\", new Blob([reference], { type: \"image/png\" }), \"reference.png\");\n\nconst response = await fetch(\"https://api.cometapi.com/v1/videos\", {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.COMETAPI_KEY}` },\n  body: form,\n});\n\nconst result = await response.json();\nconsole.log(result);\n"
          },
          {
            "lang": "Shell",
            "label": "HappyHorse 1.0 text-to-video",
            "source": "curl https://api.cometapi.com/v1/videos \\\n  -H \"Authorization: Bearer $COMETAPI_KEY\" \\\n  -F model=happyhorse-1.0 \\\n  -F 'prompt=A person reads beside a tall window while soft daylight moves across the room.' \\\n  -F seconds=3 \\\n  -F size=1280x720"
          },
          {
            "lang": "Python",
            "label": "HappyHorse 1.0 text-to-video",
            "source": "import os\nimport requests\n\nfields = [\n    (\"model\", (None, \"happyhorse-1.0\")),\n    (\"prompt\", (None, \"A person reads beside a tall window while soft daylight moves across the room.\")),\n    (\"seconds\", (None, \"3\")),\n    (\"size\", (None, \"1280x720\")),\n]\n\nresponse = requests.post(\n    \"https://api.cometapi.com/v1/videos\",\n    headers={\"Authorization\": \"Bearer \" + os.environ[\"COMETAPI_KEY\"]},\n    files=fields,\n    timeout=120,\n)\n\nresponse.raise_for_status()\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "HappyHorse 1.0 text-to-video",
            "source": "const form = new FormData();\nform.append(\"model\", \"happyhorse-1.0\");\nform.append(\"prompt\", \"A person reads beside a tall window while soft daylight moves across the room.\");\nform.append(\"seconds\", \"3\");\nform.append(\"size\", \"1280x720\");\n\nconst response = await fetch(\"https://api.cometapi.com/v1/videos\", {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.COMETAPI_KEY}` },\n  body: form,\n});\n\nconst result = await response.json();\nconsole.log(result);\n"
          },
          {
            "lang": "Shell",
            "label": "HappyHorse 1.1 multiple reference images",
            "source": "curl \\\n  https://api.cometapi.com/v1/videos \\\n  -H \"Authorization: Bearer $COMETAPI_KEY\" \\\n  --form-string model=happyhorse-1.1 \\\n  --form-string 'prompt=Keep both reference subjects in gentle motion.' \\\n  --form-string seconds=3 \\\n  --form-string size=1280x720 \\\n  --form 'input_reference=@/path/to/reference-1.png;type=image/png' \\\n  --form 'input_reference=@/path/to/reference-2.png;type=image/png'\n"
          },
          {
            "lang": "Python",
            "label": "HappyHorse 1.1 multiple reference images",
            "source": "import os\nfrom contextlib import ExitStack\n\nimport requests\n\nwith ExitStack() as stack:\n    fields = [\n        (\"model\", (None, \"happyhorse-1.1\")),\n        (\"prompt\", (None, \"Keep both reference subjects in gentle motion.\")),\n        (\"seconds\", (None, \"3\")),\n        (\"size\", (None, \"1280x720\")),\n        (\n            \"input_reference\",\n            (\n                \"reference-1.png\",\n                stack.enter_context(open(\"/path/to/reference-1.png\", \"rb\")),\n                \"image/png\",\n            ),\n        ),\n        (\n            \"input_reference\",\n            (\n                \"reference-2.png\",\n                stack.enter_context(open(\"/path/to/reference-2.png\", \"rb\")),\n                \"image/png\",\n            ),\n        ),\n    ]\n\n    response = requests.post(\n        \"https://api.cometapi.com/v1/videos\",\n        headers={\n            \"Authorization\": \"Bearer \" + os.environ[\"COMETAPI_KEY\"]\n        },\n        files=fields,\n        timeout=120,\n    )\n\nresponse.raise_for_status()\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "HappyHorse 1.1 multiple reference images",
            "source": "import { readFile } from \"node:fs/promises\";\n\nconst form = new FormData();\nform.append(\"model\", \"happyhorse-1.1\");\nform.append(\"prompt\", \"Keep both reference subjects in gentle motion.\");\nform.append(\"seconds\", \"3\");\nform.append(\"size\", \"1280x720\");\nform.append(\n  \"input_reference\",\n  new Blob([await readFile(\"/path/to/reference-1.png\")], {\n    type: \"image/png\",\n  }),\n  \"reference-1.png\",\n);\nform.append(\n  \"input_reference\",\n  new Blob([await readFile(\"/path/to/reference-2.png\")], {\n    type: \"image/png\",\n  }),\n  \"reference-2.png\",\n);\n\nconst response = await fetch(\"https://api.cometapi.com/v1/videos\", {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.COMETAPI_KEY}` },\n  body: form,\n});\n\nif (!response.ok) {\n  throw new Error(await response.text());\n}\n\nconsole.log(await response.json());\n"
          },
          {
            "lang": "Shell",
            "label": "HappyHorse 1.1 first frame from URL",
            "source": "image1=https://apidoc.cometapi.com/images/image/gemini/6100640_569429.png\n\ncurl https://api.cometapi.com/v1/videos \\\n  -H \"Authorization: Bearer $COMETAPI_KEY\" \\\n  --form-string model=happyhorse-1.1 \\\n  --form-string 'prompt=Start from this image and slowly pan right.' \\\n  --form-string seconds=3 \\\n  --form-string size=1280x720 \\\n  --form-string \"first_frame=$image1\""
          },
          {
            "lang": "Python",
            "label": "HappyHorse 1.1 first frame from URL",
            "source": "import os\n\nimport requests\n\nurl1 = \"https://apidoc.cometapi.com/images/image/gemini/6100640_569429.png\"\n\nprompt = \"Start from this image and slowly pan right.\"\n\nfields = [\n    (\"model\", (None, \"happyhorse-1.1\")),\n    (\"prompt\", (None, prompt)),\n    (\"seconds\", (None, \"3\")),\n    (\"size\", (None, \"1280x720\")),\n    (\n        \"first_frame\",\n        (None, url1),\n    ),\n]\n\nresponse = requests.post(\n    \"https://api.cometapi.com/v1/videos\",\n    headers={\"Authorization\": \"Bearer \" + os.environ[\"COMETAPI_KEY\"]},\n    files=fields,\n    timeout=120,\n)\n\nresponse.raise_for_status()\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "HappyHorse 1.1 first frame from URL",
            "source": "const form = new FormData();\nform.append(\"model\", \"happyhorse-1.1\");\nform.append(\"prompt\", \"Start from this image and slowly pan right.\");\nform.append(\"seconds\", \"3\");\nform.append(\"size\", \"1280x720\");\nform.append(\n  \"first_frame\",\n  \"https://apidoc.cometapi.com/images/image/gemini/6100640_569429.png\",\n);\n\nconst response = await fetch(\"https://api.cometapi.com/v1/videos\", {\n  method: \"POST\",\n  headers: { Authorization: \"Bearer \" + process.env.COMETAPI_KEY },\n  body: form,\n});\n\nif (!response.ok) {\n  throw new Error(await response.text());\n}\n\nconsole.log(await response.json());\n"
          },
          {
            "lang": "Shell",
            "label": "HappyHorse 1.1 first frame from file",
            "source": "curl https://api.cometapi.com/v1/videos \\\n  -H \"Authorization: Bearer $COMETAPI_KEY\" \\\n  --form-string model=happyhorse-1.1 \\\n  --form-string 'prompt=Start from this image and slowly pan right.' \\\n  --form-string seconds=3 \\\n  --form-string size=1280x720 \\\n  --form 'first_frame=@/path/to/first-frame.png;type=image/png'"
          },
          {
            "lang": "Python",
            "label": "HappyHorse 1.1 first frame from file",
            "source": "import os\n\nimport requests\n\nprompt = (\n    \"Start from this image and slowly pan right.\"\n)\n\nwith open(\"/path/to/first-frame.png\", \"rb\") as image_1:\n    fields = [\n        (\"model\", (None, \"happyhorse-1.1\")),\n        (\"prompt\", (None, prompt)),\n        (\"seconds\", (None, \"3\")),\n        (\"size\", (None, \"1280x720\")),\n        (\"first_frame\", (\"first-frame.png\", image_1, \"image/png\")),\n    ]\n\n    response = requests.post(\n        \"https://api.cometapi.com/v1/videos\",\n        headers={\"Authorization\": \"Bearer \" + os.environ[\"COMETAPI_KEY\"]},\n        files=fields,\n        timeout=120,\n    )\n\nresponse.raise_for_status()\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "HappyHorse 1.1 first frame from file",
            "source": "import { readFile } from \"node:fs/promises\";\n\nconst image_1 = await readFile(\"/path/to/first-frame.png\");\n\nconst form = new FormData();\nform.append(\"model\", \"happyhorse-1.1\");\nform.append(\"prompt\", \"Start from this image and slowly pan right.\");\nform.append(\"seconds\", \"3\");\nform.append(\"size\", \"1280x720\");\nform.append(\n  \"first_frame\",\n  new Blob([image_1], { type: \"image/png\" }),\n  \"first-frame.png\",\n);\n\nconst response = await fetch(\"https://api.cometapi.com/v1/videos\", {\n  method: \"POST\",\n  headers: { Authorization: \"Bearer \" + process.env.COMETAPI_KEY },\n  body: form,\n});\n\nif (!response.ok) {\n  throw new Error(await response.text());\n}\n\nconsole.log(await response.json());\n"
          },
          {
            "lang": "Shell",
            "label": "HappyHorse 1.0 multiple reference images",
            "source": "curl \\\n  https://api.cometapi.com/v1/videos \\\n  -H \"Authorization: Bearer $COMETAPI_KEY\" \\\n  --form-string model=happyhorse-1.0 \\\n  --form-string 'prompt=Keep both reference subjects in gentle motion.' \\\n  --form-string seconds=3 \\\n  --form-string size=1280x720 \\\n  --form 'input_reference=@/path/to/reference-1.png;type=image/png' \\\n  --form 'input_reference=@/path/to/reference-2.png;type=image/png'\n"
          },
          {
            "lang": "Python",
            "label": "HappyHorse 1.0 multiple reference images",
            "source": "import os\nfrom contextlib import ExitStack\n\nimport requests\n\nwith ExitStack() as stack:\n    fields = [\n        (\"model\", (None, \"happyhorse-1.0\")),\n        (\"prompt\", (None, \"Keep both reference subjects in gentle motion.\")),\n        (\"seconds\", (None, \"3\")),\n        (\"size\", (None, \"1280x720\")),\n        (\n            \"input_reference\",\n            (\n                \"reference-1.png\",\n                stack.enter_context(open(\"/path/to/reference-1.png\", \"rb\")),\n                \"image/png\",\n            ),\n        ),\n        (\n            \"input_reference\",\n            (\n                \"reference-2.png\",\n                stack.enter_context(open(\"/path/to/reference-2.png\", \"rb\")),\n                \"image/png\",\n            ),\n        ),\n    ]\n\n    response = requests.post(\n        \"https://api.cometapi.com/v1/videos\",\n        headers={\n            \"Authorization\": \"Bearer \" + os.environ[\"COMETAPI_KEY\"]\n        },\n        files=fields,\n        timeout=120,\n    )\n\nresponse.raise_for_status()\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "HappyHorse 1.0 multiple reference images",
            "source": "import { readFile } from \"node:fs/promises\";\n\nconst form = new FormData();\nform.append(\"model\", \"happyhorse-1.0\");\nform.append(\"prompt\", \"Keep both reference subjects in gentle motion.\");\nform.append(\"seconds\", \"3\");\nform.append(\"size\", \"1280x720\");\nform.append(\n  \"input_reference\",\n  new Blob([await readFile(\"/path/to/reference-1.png\")], {\n    type: \"image/png\",\n  }),\n  \"reference-1.png\",\n);\nform.append(\n  \"input_reference\",\n  new Blob([await readFile(\"/path/to/reference-2.png\")], {\n    type: \"image/png\",\n  }),\n  \"reference-2.png\",\n);\n\nconst response = await fetch(\"https://api.cometapi.com/v1/videos\", {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.COMETAPI_KEY}` },\n  body: form,\n});\n\nif (!response.ok) {\n  throw new Error(await response.text());\n}\n\nconsole.log(await response.json());\n"
          },
          {
            "lang": "Shell",
            "label": "HappyHorse 1.0 first frame from URL",
            "source": "image1=https://apidoc.cometapi.com/images/image/gemini/6100640_569429.png\n\ncurl https://api.cometapi.com/v1/videos \\\n  -H \"Authorization: Bearer $COMETAPI_KEY\" \\\n  --form-string model=happyhorse-1.0 \\\n  --form-string 'prompt=Start from this image and slowly pan right.' \\\n  --form-string seconds=3 \\\n  --form-string size=1280x720 \\\n  --form-string \"first_frame=$image1\""
          },
          {
            "lang": "Python",
            "label": "HappyHorse 1.0 first frame from URL",
            "source": "import os\n\nimport requests\n\nurl1 = \"https://apidoc.cometapi.com/images/image/gemini/6100640_569429.png\"\n\nprompt = \"Start from this image and slowly pan right.\"\n\nfields = [\n    (\"model\", (None, \"happyhorse-1.0\")),\n    (\"prompt\", (None, prompt)),\n    (\"seconds\", (None, \"3\")),\n    (\"size\", (None, \"1280x720\")),\n    (\n        \"first_frame\",\n        (None, url1),\n    ),\n]\n\nresponse = requests.post(\n    \"https://api.cometapi.com/v1/videos\",\n    headers={\"Authorization\": \"Bearer \" + os.environ[\"COMETAPI_KEY\"]},\n    files=fields,\n    timeout=120,\n)\n\nresponse.raise_for_status()\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "HappyHorse 1.0 first frame from URL",
            "source": "const form = new FormData();\nform.append(\"model\", \"happyhorse-1.0\");\nform.append(\"prompt\", \"Start from this image and slowly pan right.\");\nform.append(\"seconds\", \"3\");\nform.append(\"size\", \"1280x720\");\nform.append(\n  \"first_frame\",\n  \"https://apidoc.cometapi.com/images/image/gemini/6100640_569429.png\",\n);\n\nconst response = await fetch(\"https://api.cometapi.com/v1/videos\", {\n  method: \"POST\",\n  headers: { Authorization: \"Bearer \" + process.env.COMETAPI_KEY },\n  body: form,\n});\n\nif (!response.ok) {\n  throw new Error(await response.text());\n}\n\nconsole.log(await response.json());\n"
          },
          {
            "lang": "Shell",
            "label": "HappyHorse 1.0 first frame from file",
            "source": "curl https://api.cometapi.com/v1/videos \\\n  -H \"Authorization: Bearer $COMETAPI_KEY\" \\\n  --form-string model=happyhorse-1.0 \\\n  --form-string 'prompt=Start from this image and slowly pan right.' \\\n  --form-string seconds=3 \\\n  --form-string size=1280x720 \\\n  --form 'first_frame=@/path/to/first-frame.png;type=image/png'"
          },
          {
            "lang": "Python",
            "label": "HappyHorse 1.0 first frame from file",
            "source": "import os\n\nimport requests\n\nprompt = (\n    \"Start from this image and slowly pan right.\"\n)\n\nwith open(\"/path/to/first-frame.png\", \"rb\") as image_1:\n    fields = [\n        (\"model\", (None, \"happyhorse-1.0\")),\n        (\"prompt\", (None, prompt)),\n        (\"seconds\", (None, \"3\")),\n        (\"size\", (None, \"1280x720\")),\n        (\"first_frame\", (\"first-frame.png\", image_1, \"image/png\")),\n    ]\n\n    response = requests.post(\n        \"https://api.cometapi.com/v1/videos\",\n        headers={\"Authorization\": \"Bearer \" + os.environ[\"COMETAPI_KEY\"]},\n        files=fields,\n        timeout=120,\n    )\n\nresponse.raise_for_status()\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "HappyHorse 1.0 first frame from file",
            "source": "import { readFile } from \"node:fs/promises\";\n\nconst image_1 = await readFile(\"/path/to/first-frame.png\");\n\nconst form = new FormData();\nform.append(\"model\", \"happyhorse-1.0\");\nform.append(\"prompt\", \"Start from this image and slowly pan right.\");\nform.append(\"seconds\", \"3\");\nform.append(\"size\", \"1280x720\");\nform.append(\n  \"first_frame\",\n  new Blob([image_1], { type: \"image/png\" }),\n  \"first-frame.png\",\n);\n\nconst response = await fetch(\"https://api.cometapi.com/v1/videos\", {\n  method: \"POST\",\n  headers: { Authorization: \"Bearer \" + process.env.COMETAPI_KEY },\n  body: form,\n});\n\nif (!response.ok) {\n  throw new Error(await response.text());\n}\n\nconsole.log(await response.json());\n"
          },
          {
            "lang": "Shell",
            "label": "HappyHorse 1.1 reference image URLs",
            "source": "curl \\\n  https://api.cometapi.com/v1/videos \\\n  -H \"Authorization: Bearer $COMETAPI_KEY\" \\\n  --form-string model=happyhorse-1.1 \\\n  --form-string 'prompt=Use both reference images as visual guides. Preserve their visual details with gentle natural motion.' \\\n  --form-string seconds=3 \\\n  --form-string size=1280x720 \\\n  --form-string input_reference=https://apidoc.cometapi.com/images/image/gemini/6100640_569429.png \\\n  --form-string input_reference=https://apidoc.cometapi.com/images/image/gemini/6100640_569420.png\n"
          },
          {
            "lang": "Python",
            "label": "HappyHorse 1.1 reference image URLs",
            "source": "import os\n\nimport requests\n\nfields = [\n    (\"model\", (None, \"happyhorse-1.1\")),\n    (\n        \"prompt\",\n        (\n            None,\n            \"Use both reference images as visual guides. Preserve their \"\n            \"visual details with gentle natural motion.\"\n        ),\n    ),\n    (\"seconds\", (None, \"3\")),\n    (\"size\", (None, \"1280x720\")),\n    (\n        \"input_reference\",\n        (\n            None,\n            \"https://apidoc.cometapi.com/images/image/gemini/6100640_569429.png\"\n        ),\n    ),\n    (\n        \"input_reference\",\n        (\n            None,\n            \"https://apidoc.cometapi.com/images/image/gemini/6100640_569420.png\"\n        ),\n    ),\n]\n\nresponse = requests.post(\n    \"https://api.cometapi.com/v1/videos\",\n    headers={\n        \"Authorization\": \"Bearer \" + os.environ[\"COMETAPI_KEY\"]\n    },\n    files=fields,\n    timeout=120,\n)\n\nresponse.raise_for_status()\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "HappyHorse 1.1 reference image URLs",
            "source": "const form = new FormData();\nform.append(\"model\", \"happyhorse-1.1\");\nform.append(\n  \"prompt\",\n  \"Use both reference images as visual guides. Preserve their visual \" +\n  \"details with gentle natural motion.\",\n);\nform.append(\"seconds\", \"3\");\nform.append(\"size\", \"1280x720\");\nform.append(\n  \"input_reference\",\n  \"https://apidoc.cometapi.com/images/image/gemini/6100640_569429.png\",\n);\nform.append(\n  \"input_reference\",\n  \"https://apidoc.cometapi.com/images/image/gemini/6100640_569420.png\",\n);\n\nconst response = await fetch(\"https://api.cometapi.com/v1/videos\", {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.COMETAPI_KEY}` },\n  body: form,\n});\n\nif (!response.ok) {\n  throw new Error(await response.text());\n}\n\nconsole.log(await response.json());\n"
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Bearer authentication. Use your CometAPI API key."
      }
    },
    "schemas": {
      "HappyHorseCreateRequest": {
        "type": "object",
        "required": [
          "model",
          "prompt"
        ],
        "properties": {
          "model": {
            "type": "string",
            "description": "HappyHorse model ID for this endpoint.",
            "enum": [
              "happyhorse-1.0",
              "happyhorse-1.1"
            ],
            "example": "happyhorse-1.1"
          },
          "prompt": {
            "type": "string",
            "description": "Text prompt that describes the video to generate. For image inputs, describe the motion and visual details to preserve.",
            "example": "Use the uploaded reference image as the visual guide. Create a short cinematic shot with gentle natural motion."
          },
          "seconds": {
            "type": "integer",
            "minimum": 3,
            "maximum": 15,
            "default": 5,
            "description": "Requested clip duration in whole seconds. Send an integer from 3 through 15 as a form field. The default is 5.",
            "example": 3
          },
          "size": {
            "type": "string",
            "description": "Output size as an exact WxH value. Use one of the documented size values for the selected HappyHorse model. For first-frame requests, size selects the resolution tier; the image determines the framing and aspect ratio.",
            "example": "1920x1080"
          },
          "input_reference": {
            "description": "Reference images for reference-to-video. Send 1–9 publicly accessible HTTPS image URLs or 1–9 uploaded image files by repeating input_reference once per image. Use only URLs or only files within this field; do not join URLs with commas. Reference images guide subjects and visual details. CometAPI preserves image order. Use JPEG, JPG, PNG, or WEBP images with a shortest side of at least 400 px. Each reference image must be at or below 10 MB for happyhorse-1.0 or 20 MB for happyhorse-1.1. These model limits apply to both image URLs and uploaded files. The input_reference file upload limit is 20 MiB (20 x 1024 x 1024 bytes) per file. Keep uploads within the model limit as well. Keep this field separate from first_frame.",
            "anyOf": [
              {
                "title": "Single image URL",
                "type": "string",
                "format": "uri",
                "pattern": "^https://",
                "description": "One publicly accessible HTTPS image URL."
              },
              {
                "title": "Image URLs",
                "type": "array",
                "minItems": 1,
                "maxItems": 9,
                "items": {
                  "type": "string",
                  "format": "uri",
                  "pattern": "^https://",
                  "description": "One publicly accessible HTTPS image URL."
                }
              },
              {
                "title": "Image files",
                "type": "array",
                "minItems": 1,
                "maxItems": 9,
                "items": {
                  "type": "string",
                  "format": "binary",
                  "description": "One uploaded reference image file."
                }
              }
            ]
          },
          "first_frame": {
            "description": "Opening-frame image as one publicly accessible HTTPS URL or one image file. Send this field once, using either a URL or a file. Use JPEG, JPG, PNG, or WEBP images up to 20 MB. Do not combine first_frame with input_reference.",
            "anyOf": [
              {
                "type": "string",
                "format": "uri",
                "pattern": "^https://"
              },
              {
                "type": "string",
                "format": "binary"
              }
            ]
          }
        },
        "additionalProperties": false,
        "not": {
          "required": [
            "first_frame",
            "input_reference"
          ]
        }
      },
      "HappyHorseVideoTask": {
        "type": "object",
        "required": [
          "id",
          "object",
          "model",
          "status",
          "progress",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Task ID. Use this value with retrieve and content endpoints.",
            "example": "task_example"
          },
          "task_id": {
            "type": "string",
            "description": "Compatibility alias for id when present.",
            "example": "task_example"
          },
          "object": {
            "type": "string",
            "description": "Object type. Video tasks return video.",
            "example": "video"
          },
          "model": {
            "type": "string",
            "description": "Model ID used for the task.",
            "example": "happyhorse-1.1"
          },
          "status": {
            "type": "string",
            "description": "Task lifecycle status. Poll until the value is completed, failed, or error.",
            "enum": [
              "queued",
              "in_progress",
              "completed",
              "failed",
              "error"
            ],
            "example": "queued"
          },
          "progress": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Task progress as a coarse percentage.",
            "example": 0
          },
          "created_at": {
            "type": "integer",
            "description": "Task creation time as a Unix timestamp in seconds.",
            "example": 1779938152
          },
          "completed_at": {
            "type": "integer",
            "description": "Task completion time as a Unix timestamp in seconds. This field appears on completed tasks.",
            "example": 1779938219
          },
          "video_url": {
            "type": "string",
            "description": "Temporary video delivery URL. This field appears on completed tasks.",
            "example": "<temporary-video-url>"
          },
          "error": {
            "type": "object",
            "description": "Failure details. This field appears when the task fails.",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      }
    }
  }
}
