> ## Documentation Index
> Fetch the complete documentation index at: https://apixo.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# HappyHorse

> Alibaba HappyHorse video generation and editing API for text, image, reference, and video-edit workflows

## Overview

HappyHorse is an Alibaba video model for text-to-video, image-to-video, reference-guided video generation, and video editing. Use this page when you are ready to call the API after trying the model in the APIXO playground.

| Capability       | Value                                                                                                                     |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------- |
| Model ID         | `happyHorse`                                                                                                              |
| Modes            | `text-to-video`, `image-to-video`, `reference-to-video`, `video-edit`                                                     |
| Prompt           | Required for `text-to-video`, `reference-to-video`, and `video-edit`; optional for `image-to-video`                       |
| Prompt length    | Up to 2500 characters                                                                                                     |
| Input images     | Exactly 1 URL for `image-to-video`; 1-9 URLs for `reference-to-video`; 0-5 optional reference image URLs for `video-edit` |
| Input videos     | Exactly 1 URL for `video-edit`                                                                                            |
| Aspect ratios    | `16:9`, `9:16`, `1:1`, `4:3`, `3:4` for `text-to-video` and `reference-to-video`                                          |
| Resolution tiers | `720p`, `1080p`                                                                                                           |
| Duration         | 3-15 seconds for `text-to-video`, `image-to-video`, and `reference-to-video`                                              |

HappyHorse outputs video with audio by default. The public API does not expose a switch to fully disable generated audio. For `video-edit`, use `audio_setting` to choose automatic audio behavior or preserve the original input audio.

## Endpoint and authentication

Base URL:

```text theme={null}
https://api.apixo.ai/api/v1
```

| Method | Endpoint                                 | Purpose                               |
| ------ | ---------------------------------------- | ------------------------------------- |
| `POST` | `/generateTask/happyHorse`               | Submit a generation or edit task      |
| `GET`  | `/statusTask/happyHorse?taskId={taskId}` | Poll task status and retrieve results |

All requests require your APIXO API key:

```http theme={null}
Authorization: Bearer YOUR_API_KEY
```

Submit requests also require:

```http theme={null}
Content-Type: application/json
```

## Copy-paste async quickstart

This minimal request submits a text-to-video task and returns a `taskId`.

```bash theme={null}
curl -X POST "https://api.apixo.ai/api/v1/generateTask/happyHorse" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "request_type": "async",
    "input": {
      "mode": "text-to-video",
      "prompt": "a cinematic rainy night in tokyo, slow dolly shot, reflective streets",
      "resolution": "720p",
      "ratio": "16:9",
      "duration": 5
    }
  }'
```

Successful response:

```json theme={null}
{
  "code": 200,
  "message": "success",
  "data": {
    "taskId": "task_12345678"
  }
}
```

Save the `taskId`; you need it to poll for the final video.

## Poll for result

```bash theme={null}
curl -X GET "https://api.apixo.ai/api/v1/statusTask/happyHorse?taskId=task_12345678" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Processing response:

```json theme={null}
{
  "code": 200,
  "message": "success",
  "data": {
    "taskId": "task_12345678",
    "state": "processing",
    "createTime": 1767965610929
  }
}
```

Success response:

```json theme={null}
{
  "code": 200,
  "message": "success",
  "data": {
    "taskId": "task_12345678",
    "state": "success",
    "resultJson": "{\"resultUrls\":[\"https://file.apixo.ai/video.mp4\"]}",
    "createTime": 1767965610929,
    "completeTime": 1767965652317,
    "costTime": 41388
  }
}
```

Failed response:

```json theme={null}
{
  "code": 200,
  "message": "success",
  "data": {
    "taskId": "task_12345678",
    "state": "failed",
    "failCode": "PromptInvalid",
    "failMsg": "Prompt is invalid or rejected by provider",
    "createTime": 1767965610929,
    "completeTime": 1767965620132
  }
}
```

Parse `resultJson` after `state` becomes `success`:

```javascript theme={null}
const payload = JSON.parse(data.resultJson);
const videoUrls = payload.resultUrls;
```

## Request body

### Text-to-video

```json theme={null}
{
  "request_type": "async",
  "input": {
    "mode": "text-to-video",
    "prompt": "a cinematic rainy night in tokyo, slow dolly shot, reflective streets",
    "resolution": "1080p",
    "ratio": "16:9",
    "duration": 5,
    "watermark": false
  }
}
```

### Image-to-video

```json theme={null}
{
  "request_type": "async",
  "input": {
    "mode": "image-to-video",
    "image_urls": [
      "https://example.com/first-frame.png"
    ],
    "prompt": "animate the scene with a gentle camera move",
    "resolution": "720p",
    "duration": 5,
    "watermark": false
  }
}
```

### Reference-to-video

```json theme={null}
{
  "request_type": "async",
  "input": {
    "mode": "reference-to-video",
    "prompt": "keep the character style consistent across all references",
    "image_urls": [
      "https://example.com/ref-1.png",
      "https://example.com/ref-2.png"
    ],
    "resolution": "1080p",
    "ratio": "16:9",
    "duration": 6,
    "watermark": false
  }
}
```

### Video edit

```json theme={null}
{
  "request_type": "async",
  "input": {
    "mode": "video-edit",
    "video_urls": [
      "https://example.com/input.mp4"
    ],
    "image_urls": [
      "https://example.com/reference.png"
    ],
    "prompt": "change the scene to watercolor style",
    "resolution": "1080p",
    "audio_setting": "origin",
    "watermark": false
  }
}
```

## Parameters

<ParamField body="request_type" type="string" required default="async">
  Result delivery mode. Use `async` for polling with `statusTask`, or `callback` for webhook delivery.
</ParamField>

<ParamField body="callback_url" type="string">
  Required when `request_type` is `callback`. Must be a public HTTPS URL that can receive the final task payload. See [Webhooks](/docs/api-reference/webhooks).
</ParamField>

<ParamField body="input" type="object" required>
  HappyHorse input parameters.

  <Expandable title="properties">
    <ParamField body="mode" type="string" required>
      Generation mode. Supported values: `text-to-video`, `image-to-video`, `reference-to-video`, `video-edit`.
    </ParamField>

    <ParamField body="prompt" type="string">
      Text prompt describing the video or edit. Required for `text-to-video`, `reference-to-video`, and `video-edit`; optional for `image-to-video`. Required prompts cannot be empty after trimming. Maximum 2500 characters.
    </ParamField>

    <ParamField body="image_urls" type="string[]">
      Public image URLs. Required with exactly 1 URL for `image-to-video`; required with 1-9 URLs for `reference-to-video`; optional with 0-5 reference image URLs for `video-edit`.
    </ParamField>

    <ParamField body="video_urls" type="string[]">
      Public video URLs. Required for `video-edit`; must contain exactly 1 URL.
    </ParamField>

    <ParamField body="resolution" type="string" default="1080p">
      Output resolution tier. Supported values: `720p`, `1080p`.
    </ParamField>

    <ParamField body="ratio" type="string" default="16:9">
      Output aspect ratio for `text-to-video` and `reference-to-video`. Supported values: `16:9`, `9:16`, `1:1`, `4:3`, `3:4`.
    </ParamField>

    <ParamField body="duration" type="integer" default="5">
      Output duration in seconds for `text-to-video`, `image-to-video`, and `reference-to-video`. Supports integers from 3 to 15. Not used for `video-edit`; the provider request for `video-edit` does not include `duration`.
    </ParamField>

    <ParamField body="audio_setting" type="string" default="auto">
      `video-edit` only. Supported values: `auto`, `origin`. Use `origin` when you want to preserve the original input audio.
    </ParamField>

    <ParamField body="watermark" type="boolean" default="false">
      Whether to add a watermark.
    </ParamField>

    <ParamField body="seed" type="integer">
      Optional random seed. Supports integers from 0 to 2147483647. If omitted, the backend automatically generates a seed and sends it to the provider.
    </ParamField>
  </Expandable>
</ParamField>

## Response format

### Submit task response

`POST /generateTask/happyHorse` returns a task ID when the task is accepted:

<ResponseField name="code" type="integer">
  API status code. `200` means the task was accepted.
</ResponseField>

<ResponseField name="message" type="string">
  Human-readable status message.
</ResponseField>

<ResponseField name="data.taskId" type="string">
  Unique task identifier used with the status endpoint.
</ResponseField>

### Status response fields

<ResponseField name="taskId" type="string">
  Unique task identifier.
</ResponseField>

<ResponseField name="state" type="string">
  Current task state: `processing`, `success`, or `failed`.
</ResponseField>

<ResponseField name="resultJson" type="string">
  JSON string containing generated video URLs in `resultUrls`. Present when `state` is `success`.
</ResponseField>

<ResponseField name="failCode" type="string">
  Machine-readable failure code. Present when `state` is `failed`.
</ResponseField>

<ResponseField name="failMsg" type="string">
  Human-readable failure message. Present when `state` is `failed`.
</ResponseField>

<ResponseField name="createTime" type="integer">
  Task creation timestamp in Unix milliseconds.
</ResponseField>

<ResponseField name="completeTime" type="integer">
  Task completion timestamp in Unix milliseconds. Present after completion.
</ResponseField>

<ResponseField name="costTime" type="integer">
  Processing duration in milliseconds. Present after successful completion when available.
</ResponseField>

## Webhook callback mode

Use callback mode when your backend should receive the final result automatically instead of polling.

```bash theme={null}
curl -X POST "https://api.apixo.ai/api/v1/generateTask/happyHorse" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "request_type": "callback",
    "callback_url": "https://your-server.com/webhooks/apixo",
    "input": {
      "mode": "video-edit",
      "video_urls": [
        "https://example.com/input.mp4"
      ],
      "image_urls": [
        "https://example.com/reference.png"
      ],
      "prompt": "change the scene to watercolor style",
      "resolution": "1080p",
      "audio_setting": "origin",
      "watermark": false
    }
  }'
```

See [Webhooks](/docs/api-reference/webhooks) for delivery requirements and retry behavior.

## Billing

HappyHorse is billed per second. The selected `resolution` determines the unit price.

| Resolution | APIXO official price | Market reference   |
| ---------- | -------------------- | ------------------ |
| `720p`     | `$0.125 / second`    | `$0.1625 / second` |
| `1080p`    | `$0.225 / second`    | `$0.2875 / second` |

Billing formulas:

| Mode                 | Formula                                                    |
| -------------------- | ---------------------------------------------------------- |
| `text-to-video`      | `duration * unitPrice`                                     |
| `image-to-video`     | `duration * unitPrice`                                     |
| `reference-to-video` | `duration * unitPrice`                                     |
| `video-edit`         | `(input video seconds + output video seconds) * unitPrice` |

For `video-edit`, the backend probes the input video duration and does not send a public `duration` parameter to the provider. Billing uses the input video seconds plus the generated output video seconds; APIXO caps the billable input side at 15 seconds, and the generated output side is billed at the same capped duration.

For current route and market comparison pricing, see [Pricing](https://apixo.ai/pricing).

## Latency and polling

HappyHorse tasks are asynchronous. The backend does not enforce a fixed public latency SLA; actual time varies by mode, resolution, duration, prompt complexity, media fetch speed, and provider queue load.

| Workflow             | What affects latency                                                 | Recommended first poll  | Poll interval |
| -------------------- | -------------------------------------------------------------------- | ----------------------- | ------------- |
| `text-to-video`      | Resolution, duration, prompt complexity, queue load                  | 30s after task creation | 10s           |
| `image-to-video`     | Image fetch time, resolution, duration, queue load                   | 30s after task creation | 10s           |
| `reference-to-video` | Number of references, resolution, duration, queue load               | 45s after task creation | 10s-15s       |
| `video-edit`         | Input video fetch/probe time, input duration, references, queue load | 60s after task creation | 10s-15s       |

<Tip>
  For production workloads, use callback mode to avoid frequent polling for long-running video jobs.
</Tip>

Rate limits and concurrency can vary by account, API key, and route. If you receive `429`, slow down requests and retry with backoff. For account-level details, see [System APIs](/docs/api-reference/system).

## Errors and troubleshooting

### HTTP errors

| Code  | Meaning                                                                       | What to do                                       |
| ----- | ----------------------------------------------------------------------------- | ------------------------------------------------ |
| `400` | Invalid request body, mode, parameter, media URL shape, or provider rejection | Fix the request before retrying                  |
| `401` | Missing or invalid API key                                                    | Check the `Authorization` header                 |
| `402` | Insufficient balance or quota                                                 | Add balance or switch account/key                |
| `403` | Key or route cannot access the model                                          | Check permissions and route strategy             |
| `429` | Rate limit or concurrency limit reached                                       | Retry with exponential backoff                   |
| `500` | Server error                                                                  | Retry with backoff                               |
| `502` | Upstream provider error                                                       | Retry with backoff                               |
| `504` | Upstream timeout                                                              | Retry or use callback mode for long-running jobs |

### Task failure codes

| Fail code                                       | Meaning                                                  | What to do                                                                                |
| ----------------------------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `PromptInvalid`                                 | Prompt was invalid or rejected by the provider           | Rewrite the prompt with clearer, policy-safe instructions                                 |
| `SensitiveContent` / `SensitiveContentDetected` | Prompt, input media, or output failed safety checks      | Change the prompt or media                                                                |
| `MissingParameter` / `BadRequest`               | Required mode-specific fields are missing or malformed   | Check `mode`, `prompt`, `image_urls`, `video_urls`, `resolution`, `ratio`, and `duration` |
| `RateLimited` / `RateLimitExceeded`             | Provider or APIXO rate limit was reached                 | Retry with exponential backoff                                                            |
| `Timeout` / `Task TimeOut`                      | The provider did not finish in time                      | Retry, reduce input complexity, or use callback mode                                      |
| `Unknown error`                                 | Upstream failure could not be mapped to a known category | Retry with backoff or contact support with the `taskId`                                   |

### Troubleshooting tips

* Use public, direct, fetchable URLs for `image_urls` and `video_urls`.
* For `image-to-video`, send exactly one image URL.
* For `reference-to-video`, send 1-9 image URLs and include a non-empty prompt.
* For `video-edit`, send exactly one video URL. Optional reference images are limited to 5.
* Use `ratio` only with `text-to-video` and `reference-to-video`.
* Use `duration` only with `text-to-video`, `image-to-video`, and `reference-to-video`; `video-edit` duration is determined from the input video and billed as input video seconds plus output video seconds.
* Store result URLs promptly if your application needs long-term access.

See [Error Codes](/docs/api-reference/errors) for the full error reference.

## Related links

* [Generation API Overview](/docs/models)
* [Generate Task](/docs/api-reference/generate-task)
* [Status Task](/docs/api-reference/status-task)
* [Webhooks](/docs/api-reference/webhooks)
* [Error Codes](/docs/api-reference/errors)
* [Parameter Specification](/docs/api-reference/parameters)
* [Routing Strategies](/docs/concepts/routing-strategies)
* [Pricing](https://apixo.ai/pricing)
