# Happy Horse Video Edit API

> Bewerkt een bestaande video met een prompt in natuurlijke taal en maximaal 5 referentieafbeeldingen

Bewerkt een bronvideo van 3 tot 60 seconden (MP4 of MOV, maximaal 100 MB) volgens een `prompt`. Maximaal 5 referentieafbeeldingen kunnen in de prompt worden aangeduid als @Image1 tot en met @Image5. `resolution` is 720p of 1080p, en `audio_setting` laat het model kiezen ('auto') of behoudt de oorspronkelijke audio ('origin').

- Model id: `alibaba/happy-horse/video-edit`
- Made by: Alibaba
- Category: Video to Video
- Output: video
- Price per second of your input video: from $0.28 / second of input video (cheapest run $0.28 (280 API credits))
- Run: `POST https://api.doitong.ru/v1/run/alibaba/happy-horse/video-edit`
- Quote: `POST https://api.doitong.ru/v1/quote/alibaba/happy-horse/video-edit`
- Docs page: https://doitong.com/nl/developers/models/alibaba/happy-horse/video-edit

## Pricing

Price: **from $0.28 / second of input video** (the lowest tier; the quote prices your exact input). Price per second of your input video: the input files are measured before the run (length, resolution, frame rate). The quote measures the same files and is exactly what the run charges.

Price by tier:

- base rate: $0.28 / second of input video
- 1080p: $0.56 / second of input video

The full example input below costs $5.60 = 5600 API credits (10 s input video × $0.28 × 2 (1080p)).

Prices are the upstream price in USD, paid from the API balance in API credits (1000 API credits = 1 USD). `POST https://api.doitong.ru/v1/quote/alibaba/happy-horse/video-edit` with the same JSON body returns the exact price for that input; the quote is exactly what a run charges. Invalid input is never charged and failed or canceled requests are refunded automatically.

## Input parameters

Send either the canonical name or the native field name (not both). Canonical names are the same across models.

| Parameter | Canonical name | Type | Required | Default | Allowed values / range | Description |
|---|---|---|---|---|---|---|
| `video_url` | `video` | string (video URL) | yes |  |  | URL van de bronvideo voor bewerking; de uitvoer behoudt de beeldverhouding en komt qua duur overeen tot 15 s, waarbij voor langere invoer alleen het begin wordt behouden. Gebruik MP4 of MOV (bij voorkeur H.264), met een duur van 3–60 s en maximaal 100 MB, een framesnelheid hoger dan 8 fps, een beeldverhouding binnen 1:2.5–2.5:1, een lange zijde van maximaal 2160 px en een korte zijde van minimaal 320 px. De time-out is 30.0 s. |
| `prompt` |  | string | yes |  | ≥ 1 characters | Tekst die de uit te voeren bewerking beschrijft, beperkt tot 2500 tekens. Verwijs naar opgegeven afbeeldingen met @Image1, @Image2 tot en met @Image5. |
| `reference_image_urls` | `images` | array of image URL \| null | no |  |  | Optionele afbeeldingen voor bewerkingsguidance, elk beperkt tot 10 MB en met beide dimensies van minimaal 300px. Geef maximaal 5 afbeeldingen op in JPEG-, JPG-, PNG- of WEBP-indeling, met beeldverhoudingen binnen 1:2.5–2.5:1. |
| `resolution` |  | enum (string) | no | `1080p` | `720p`, `1080p` | Resolutieniveau voor de resulterende video. |
| `audio_setting` |  | enum (string) | no | `auto` | `auto`, `origin` | Kies 'origin' om de audio van de invoervideo ongewijzigd over te nemen, of 'auto' om het model te laten bepalen of de audio opnieuw moet worden gegenereerd. |
| `seed` |  | integer \| null | no |  |  | Willekeurige seed voor reproduceerbare resultaten, van 0 tot 2147483647. |
| `enable_safety_checker` |  | boolean | no | `true` |  | Moderatie van zowel invoer als uitvoer, afgedwongen bij elke request tenzij het account is geautoriseerd om dit uit te schakelen en de optie is uitgeschakeld. |

File parameters (`video`, `images`) take a public `https://` URL, a `data:` URI up to 10 MB, or the `file_url` of an upload from `POST /files`.

## Example input

Required parameters only:

```json
{
  "video": "https://content.doitong.com/video/showcase/v3/gen_fox_cartoon.mp4",
  "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
}
```

A fuller example:

```json
{
  "video_url": "https://content.doitong.com/video/showcase/v3/gen_fox_cartoon.mp4",
  "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
}
```

## Run it

Set `DOITONG_API_KEY` to a key from https://doitong.com/developers/dashboard#keys. `?wait=20` returns the finished request in the same call when it is ready within 20 seconds; otherwise poll `GET /requests/{id}` (it also accepts `?wait=`), or pass `webhook_url`.

### curl

```bash
# Run the model; wait up to 20 s for the finished result in the same call
curl -X POST "https://api.doitong.ru/v1/run/alibaba/happy-horse/video-edit?wait=20" \
  -H "Authorization: Bearer $DOITONG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "video_url": "https://content.doitong.com/video/showcase/v3/gen_fox_cartoon.mp4",
    "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
  }'

# Still "queued" or "running"? Poll with the id from the response:
curl "https://api.doitong.ru/v1/requests/REQUEST_ID?wait=20" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

### JavaScript

```javascript
const API = "https://api.doitong.ru/v1";
const headers = {
  "Authorization": "Bearer " + process.env.DOITONG_API_KEY,
  "Content-Type": "application/json",
};

// Run the model; wait up to 20 s for the finished result in the same call
let res = await fetch(API + "/run/alibaba/happy-horse/video-edit?wait=20", {
  method: "POST",
  headers,
  body: JSON.stringify({
    "video_url": "https://content.doitong.com/video/showcase/v3/gen_fox_cartoon.mp4",
    "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
  }),
});
let request = await res.json();
if (!res.ok) throw new Error(request.error.code + ": " + request.error.message);

// Not finished yet: long-poll until it is
while (request.status === "queued" || request.status === "running") {
  res = await fetch(API + "/requests/" + request.id + "?wait=20", { headers });
  request = await res.json();
}
if (request.status !== "succeeded") throw new Error(JSON.stringify(request.error));
console.log(request.outputs.map((o) => o.url), request.cost.credits + " API credits ($" + request.cost.usd + ")");
```

### Python

```python
import os
import requests

API = "https://api.doitong.ru/v1"
headers = {"Authorization": "Bearer " + os.environ["DOITONG_API_KEY"]}

payload = {
    "video_url": "https://content.doitong.com/video/showcase/v3/gen_fox_cartoon.mp4",
    "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field",
}

# Run the model; wait up to 20 s for the finished result in the same call
r = requests.post(API + "/run/alibaba/happy-horse/video-edit", params={"wait": 20}, json=payload, headers=headers)
request = r.json()
if not r.ok:
    raise RuntimeError(request["error"]["code"] + ": " + request["error"]["message"])

# Not finished yet: long-poll until it is
while request["status"] in ("queued", "running"):
    request = requests.get(API + "/requests/" + request["id"], params={"wait": 20}, headers=headers).json()
if request["status"] != "succeeded":
    raise RuntimeError(request["error"])
print([o["url"] for o in request["outputs"]], request["cost"]["credits"], "API credits", "$" + request["cost"]["usd"])
```

### MCP

The MCP server at `https://api.doitong.ru/v1/mcp` exposes the tools `search_models`, `get_model`, `quote`, `run`, `get_request`, `cancel_request`, `list_requests`, `create_upload` and `get_account`. A `run` call for this model:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "run",
    "arguments": {
      "model_id": "alibaba/happy-horse/video-edit",
      "input": {
        "video_url": "https://content.doitong.com/video/showcase/v3/gen_fox_cartoon.mp4",
        "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
      },
      "wait_seconds": 20
    }
  }
}
```

## Response

Every call returns a request object. `status` is one of `queued`, `running`, `succeeded`, `failed`, `canceled`. `outputs` lists the generated files with URLs on our storage (kept forever, or 7 days with `?storage=temporary`; `storage` says which); `output` is the model's own result object with the same URLs.

```json
{
  "id": "req_8k2m4q7x1z9c3v5b6n0p2r4t",
  "object": "request",
  "model": "alibaba/happy-horse/video-edit",
  "status": "succeeded",
  "created_at": "2026-10-20T12:00:00Z",
  "started_at": "2026-10-20T12:00:02Z",
  "completed_at": "2026-10-20T12:00:09Z",
  "queue_position": null,
  "cost": {
    "credits": 5600,
    "usd": "5.60",
    "charged": 5600,
    "refunded": 0
  },
  "input": {
    "video_url": "https://content.doitong.com/video/showcase/v3/gen_fox_cartoon.mp4",
    "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
  },
  "output": {
    "video": {
      "url": "https://content.doitong.com/dev-api/2026/10/20/req_8k2m4q7x1z9c3v5b6n0p2r4t/0-output.mp4",
      "content_type": "video/mp4",
      "file_name": "0-output.mp4",
      "file_size": 1843200,
      "width": 1024,
      "height": 768,
      "fps": 1.0,
      "duration": 5,
      "num_frames": 1
    },
    "seed": 42
  },
  "outputs": [
    {
      "type": "video",
      "url": "https://content.doitong.com/dev-api/2026/10/20/req_8k2m4q7x1z9c3v5b6n0p2r4t/0-output.mp4",
      "content_type": "video/mp4",
      "file_size": 1843200,
      "width": 1280,
      "height": 720,
      "duration": 5,
      "stored": true
    }
  ],
  "error": null,
  "metrics": {
    "inference_seconds": 6.8
  },
  "urls": {
    "self": "https://api.doitong.ru/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t",
    "cancel": "https://api.doitong.ru/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/cancel"
  }
}
```

### Output fields (`output`)

| Field | Type | Description |
|---|---|---|
| `video` | object {url, content_type, file_name, file_size, width, height, fps, duration, num_frames} | Videobestand dat door de generatie is geproduceerd. |
| `seed` | integer | Seedwaarde die tijdens de generatie wordt toegepast. |

## Related models

- [Happy Horse · Text to Video](https://doitong.com/developers/models/alibaba/happy-horse/text-to-video.md) (`alibaba/happy-horse/text-to-video`): from $0.14 / second
- [Happy Horse · Image to Video](https://doitong.com/developers/models/alibaba/happy-horse/image-to-video.md) (`alibaba/happy-horse/image-to-video`): from $0.14 / second
- [Happy Horse · Reference to Video](https://doitong.com/developers/models/alibaba/happy-horse/reference-to-video.md) (`alibaba/happy-horse/reference-to-video`): from $0.14 / second
- [Wan 2.1 VACE Long Reframe](https://doitong.com/developers/models/wan-vace-apps/long-reframe.md) (`wan-vace-apps/long-reframe`): from $0.04 / 2 seconds of input video
- [Wan 2.2 VACE Fun A14B · Depth](https://doitong.com/developers/models/wan-22-vace-fun-a14b/depth.md) (`wan-22-vace-fun-a14b/depth`): from $0.05 / second of output video
- [Wan 2.2 VACE Fun A14B · Inpainting](https://doitong.com/developers/models/wan-22-vace-fun-a14b/inpainting.md) (`wan-22-vace-fun-a14b/inpainting`): from $0.05 / second of output video
- [Wan 2.2 VACE Fun A14B · Outpainting](https://doitong.com/developers/models/wan-22-vace-fun-a14b/outpainting.md) (`wan-22-vace-fun-a14b/outpainting`): from $0.05 / second of output video
- [Wan 2.2 VACE Fun A14B · Reframe](https://doitong.com/developers/models/wan-22-vace-fun-a14b/reframe.md) (`wan-22-vace-fun-a14b/reframe`): from $0.05 / second of output video

## Links

- HTML page: https://doitong.com/developers/models/alibaba/happy-horse/video-edit
- All models and guides for AI agents: https://doitong.com/developers/llms.txt
- OpenAPI 3.1 with this model's typed request body: https://doitong.com/developers/openapi.json?model=alibaba/happy-horse/video-edit
- Errors: https://doitong.com/developers/docs/errors
- Model details as JSON: https://api.doitong.ru/v1/models/alibaba/happy-horse/video-edit
