# Hailuo 2.3 Video API Reference

Create Hailuo 2.3 text-to-video and image-to-video tasks from your app, backend, or automation workflow.

> Production Beta: the v1 endpoint is callable. Keep task polling and failure handling in your integration because video generation is asynchronous.

## Base URL

```text
https://imya.ai
```

## Authentication and idempotency

Create an API key in your imya account and pass it as a Bearer token. Every generation POST also requires an idempotency key.

```http
Authorization: Bearer imya_xxxxxxxxx
Content-Type: application/json
Idempotency-Key: your-unique-request-id
```

Use a new idempotency key for each logical generation request. Retrying the same request with the same key returns the original task instead of creating and charging for another task. Keys may contain 1-128 ASCII letters, numbers, dots, colons, underscores, or hyphens.

## Create a video generation task

```http
POST /v1/videos/generations
```

### Supported workflows

| Model | Workflow | Image input |
| --- | --- | --- |
| `hailuo-2.3` | Text-to-video or image-to-video | Omit `image_url` for text-to-video; include it for image-to-video. |
| `hailuo-2.3-fast` | Image-to-video | `image_url` is required. |

### Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| model | string | Yes | `hailuo-2.3` or `hailuo-2.3-fast`. |
| prompt | string | Yes | Generation instructions, up to 5,000 characters. |
| image_url | string | Conditional | Public HTTPS first-frame image. Required for `hailuo-2.3-fast`; optional for `hailuo-2.3`. |
| duration | number | No | `6` or `10` seconds. Default is `6`. |
| resolution | string | No | `768p` or `1080p`. Default is `768p`. `1080p` supports only 6 seconds. |
| prompt_optimizer | boolean | No | Let the model optimize the prompt. Default is `true`. |

### Text-to-video example

```bash
curl https://imya.ai/v1/videos/generations \
  -H "Authorization: Bearer YOUR_IMYA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: hailuo-t2v-order-001" \
  -d '{
    "model": "hailuo-2.3",
    "prompt": "A paper boat crossing a rain-soaked neon street, cinematic camera movement",
    "duration": 6,
    "resolution": "768p",
    "prompt_optimizer": true
  }'
```

### Image-to-video example

```bash
curl https://imya.ai/v1/videos/generations \
  -H "Authorization: Bearer YOUR_IMYA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: hailuo-i2v-order-001" \
  -d '{
    "model": "hailuo-2.3-fast",
    "prompt": "The camera slowly pushes in as warm light moves across the scene",
    "image_url": "https://cdn.example.com/input/first-frame.jpg",
    "duration": 6,
    "resolution": "1080p"
  }'
```

### Accepted response

```json
{
  "id": "task_0123456789abcdef0123456789abcdef",
  "status": "pending",
  "model": "hailuo-2.3",
  "credits_reserved": 225
}
```

The example number illustrates the response shape only. `credits_reserved` is calculated for the current request and account at submission time; do not calculate or cache the charge in your client.

## Retrieve a task

```http
GET /v1/tasks/{task_id}
```

Poll no faster than once every 5 seconds.

### Example request

```bash
curl https://imya.ai/v1/tasks/task_0123456789abcdef0123456789abcdef \
  -H "Authorization: Bearer YOUR_IMYA_API_KEY"
```

### Completed response

```json
{
  "id": "task_0123456789abcdef0123456789abcdef",
  "status": "succeeded",
  "model": "hailuo-2.3",
  "credits_used": 225,
  "data": [
    {
      "url": "https://media.example.com/generated/example.mp4"
    }
  ]
}
```

Video result URLs may be temporary. Download successful results promptly. Production Beta does not yet guarantee 7-day or 30-day retention for API video results.

## Status values

| Status | Meaning |
| --- | --- |
| pending | The task has been accepted. |
| processing | The model is generating. |
| succeeded | The result is ready. |
| failed | The task failed. Inspect the sanitized `error` object. |

New tasks return HTTP `202`. Replaying the same request and idempotency key returns HTTP `200` with `Idempotent-Replayed: true`. Task retrieval returns HTTP `200`; a failed task may report `generation_failed`, `refund_pending`, or `media_deleted` in `error.code`.

## Credit billing

The server calculates the live charge from the selected workflow, model variant, resolution, duration, and the API key owner's current plan. The POST response returns that charge as `credits_reserved`. A successful task reports the final debit as `credits_used`.

Do not hard-code a Hailuo credit price in your application. Failed tasks release or refund eligible reserved credits once without extending the original expiration date of promotional or reward credits.

## Legacy Hailuo Beta compatibility

Existing Hailuo integrations may continue to call the older Beta endpoint with `x-api-key`. Generation POSTs on that endpoint now also require `Idempotency-Key` for safe retries. New integrations should use the v1 endpoint above.

```bash
curl https://imya.ai/api/video/generate \
  -H "x-api-key: YOUR_IMYA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: legacy-hailuo-order-001" \
  -d '{
    "modelKey": "hailuo-2-3-standard-t2v",
    "prompt": "A paper boat crossing a rain-soaked neon street",
    "resolution": "720p",
    "outputDurationSec": 6,
    "promptExtend": true
  }'
```

The legacy endpoint returns `taskId` and its calculated credit cost. Poll legacy tasks at `GET /api/video/task/{taskId}` with the same `x-api-key`. Legacy field names, resolution values, response shape, and retry behavior differ from v1.

## Errors

| Code | Meaning |
| --- | --- |
| 400 | Missing or invalid idempotency key, malformed JSON, or an invalid legacy request. |
| 401 | Missing or invalid API key. |
| 402 | Not enough credits. |
| 403 | The API account is disabled. |
| 409 | The idempotency key was already used with a different request body. |
| 413 | The request body exceeds 64 KiB. |
| 422 | Invalid model, workflow, duration, resolution, prompt, or image URL. |
| 429 | Rate or concurrent-task limit reached. |
| 5xx | The request could not be completed or submitted. |
