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

# Muse Video Ext Video Generation

> Generate one MP4 video from text or up to 9 reference images: approximately 10 seconds, 720p, with sound.

> [!NOTE]
>
> This API is asynchronous. Save the task ID after submission and query `GET /v1/tasks/{task_id}` for status and results. The default submission response contains the ID at `data[0].task_id`.

```bash cURL theme={null}
curl --request POST \
  --url https://api.apimart.ai/v1/videos/generations \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --header 'Idempotency-Key: <unique-operation-key>' \
  --data '{
    "model": "muse-video-ext",
    "prompt": "Waves gently wash a beach at sunset, slow camera pan, natural ocean sounds, no text",
    "aspect_ratio": "16:9",
    "duration": 10,
    "resolution": "720p"
  }'
```

```python Python theme={null}
import requests

response = requests.post(
    "https://api.apimart.ai/v1/videos/generations",
    headers={
        "Authorization": "Bearer <token>",
        "Accept": "application/json",
        "Idempotency-Key": "<unique-operation-key>"
    },
    json={
        "model": "muse-video-ext",
        "prompt": "Waves gently wash a beach at sunset, slow camera pan, natural ocean sounds, no text",
        "aspect_ratio": "16:9",
        "duration": 10,
        "resolution": "720p"
    }
)
response.raise_for_status()
print(response.json())
```

```javascript JavaScript theme={null}
const response = await fetch("https://api.apimart.ai/v1/videos/generations", {
  method: "POST",
  headers: {
    Authorization: "Bearer <token>",
    "Content-Type": "application/json",
    Accept: "application/json",
    "Idempotency-Key": "<unique-operation-key>"
  },
  body: JSON.stringify({
    "model": "muse-video-ext",
    "prompt": "Waves gently wash a beach at sunset, slow camera pan, natural ocean sounds, no text",
    "aspect_ratio": "16:9",
    "duration": 10,
    "resolution": "720p"
  })
});
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());
```

```json 200 theme={null}
{
  "code": 200,
  "data": [
    {
      "status": "submitted",
      "task_id": "task_01K..."
    }
  ]
}
```

## Request headers

**Authorization** `string` *required*

Use an APIMart API Key as `Bearer <token>`. Both submission and polling require authentication under the same user identity.

**Idempotency-Key** `string`

Strongly recommended. Use a new key for each independent generation (1–191 visible ASCII characters; a UUID is recommended). Replace `<unique-operation-key>` in the examples. After a submission timeout or network failure, retry with the same endpoint, body, response version, and key. Once you have a task ID, only query that task.

## Request parameters

**model** `string` *required*

Must be `muse-video-ext`.

**prompt** `string` *required*

A text description of the requested content. Chinese and English are supported. It must not be empty after trimming whitespace, including when reference images are provided.

**image\_urls** `string[]`

Up to 9 nonempty reference image inputs. Accepts public URLs, Data URIs (such as `data:image/png;base64,...`), or raw base64. Omit or send `[]` for text-only generation. PNG, JPEG, and WebP are recommended. Remote URLs must be directly accessible by the server without browser login cookies.

The combined original size of all reference images must not exceed **11 MiB (11,534,336 bytes)**. This is a total limit, not a per-image limit. Base64 adds request-body overhead. Do not send `blob:` URLs, local file paths, or `File` objects.

**aspect\_ratio** `string`

Supports the seven ratios below. If omitted, text-to-video defaults to `16:9`; generation with references follows their composition. An explicit ratio overrides this behavior. For automatic selection, omit this field; do not send `"auto"`.

`1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `3:2`, `2:3`

**size** `string`

Compatibility field accepting the seven ratios above or `auto`; pixel sizes such as `1024x1024` are unsupported. Sending only `size: "auto"` is equivalent to not specifying a ratio. Prefer `aspect_ratio`. If both are valid, `aspect_ratio` takes precedence, but each field is validated independently: a valid ratio cannot override an invalid `size`.

**n** `integer` (default: 1)

Only one result per request. The only accepted value is the number `1`. Explicit `0`, negative values, or values above `1` cause an error.

**duration** `integer | string` (default: 10)

Fixed at approximately 10 seconds. Accepts the number `10` or strings `"10"` and `"10s"`; the number `10` is recommended. Compatibility aliases: `seconds` and `duration_seconds`. Use only one duration field; every supplied field is validated independently.

**resolution** `string` (default: 720p)

Only `720p` is supported, not `1080p` or `4k`. Actual dimensions and playback duration are determined by the returned media metadata.

**audio** `boolean`

Videos include sound by default; omit this field. `true` does not change this behavior, and `false` is rejected.

> [!NOTE]
>
> Returns an MP4 URL: approximately 10 seconds, 720p, with sound. Reference images guide generation but are not guaranteed to appear as a pixel-identical first frame.

### Other optional parameters

**webhook** `string`

Backend base URL for task notifications. The platform removes trailing slashes and appends `/callback`: for example, `https://your-backend.example/muse` becomes `https://your-backend.example/muse/callback`. Omit when using polling only.

**language** `string`

Controls Webhook error-message language, not generated content. Supported values: `zh`, `en`, `ja`, `ko`, `ru`, `fr`, `de`, `id`, `pt`, `es`. Regional tags such as `zh-CN` are not accepted. For polling, pass the language separately in the GET query string.

## Generation with reference images

```json theme={null}
{
  "model": "muse-video-ext",
  "prompt": "The fox in the reference image slowly raises its head, wind moves its fur, gentle camera push-in",
  "image_urls": [
    "https://your-cdn.example/fox.png"
  ],
  "duration": 10,
  "resolution": "720p"
}
```

Replace the example URL with an accessible image URL. This example omits the ratio to follow the reference composition; add `aspect_ratio` for a fixed ratio. For multiple references, add inputs to `image_urls`, up to 9 total.

## Submission response

The default response is HTTP `200`, with `data` as an array. `submitted` means the task was accepted, not completed. Save `data[0].task_id`, then query the task.

> **Optional response version: 2026-07-27**
>
> With the header `X-APIMart-Response-Version: 2026-07-27`, submission returns HTTP `202`. Read the task ID from `data.id` and the polling path from `data.poll_url`.
>
> ```json theme={null}
> {
>   "code": 202,
>   "request_id": "req_example",
>   "data": {
>     "id": "task_01K...",
>     "object": "generation.task",
>     "type": "video",
>     "status": "pending",
>     "progress": 0,
>     "poll_url": "/v1/tasks/task_01K..."
>   }
> }
> ```
>
> This version does not change the GET response structure. Do not add this header while continuing to parse submission responses as `data[0].task_id`.

## Query task status and results

Use the complete task ID returned on submission and the same user identity. `language` is optional and controls error-message language. See [Task status](https://docs.apimart.ai/en/api-reference/tasks/status.md) for all fields.

```bash theme={null}
curl --request GET \
  --url 'https://api.apimart.ai/v1/tasks/<task_id>?language=en' \
  --header 'Authorization: Bearer <token>'
```

Poll every 5–10 seconds, with at most one query in flight per task. A client timeout or stopped polling does not cancel the server task. Save the task ID and resume GET queries later; do not automatically submit a new generation.

| `data.status` | Action |
| - | - |
| `pending` / `processing` | Queued or processing; continue polling. |
| `completed` | Generation succeeded; stop polling and read the result URL. |
| `failed` | Generation failed; stop polling and read `data.error.message`. |
| `unknown` / … | Status is uncertain. Keep the task ID and retry queries within a bounded limit; do not treat it as success or automatically regenerate. |

Use `data.status` to determine completion. HTTP `200` or `progress: 100` alone does not mean generation succeeded. A `polling_error` during processing is not a terminal failure.

Example completed query response (result URL is a placeholder):

```json theme={null}
{
  "code": 200,
  "data": {
    "id": "task_01K...",
    "status": "completed",
    "progress": 100,
    "result": {
      "videos": [
        {
          "url": [
            "https://cdn.example/generated-video.mp4"
          ]
        }
      ]
    }
  }
}
```

In query responses, `data` is an object and `url` is an array of strings. The first result is at `data.result.videos[0].url[0]`. If present, `expires_at` is an expiration timestamp in Unix seconds; save required files before expiry. `actual_time` measures task processing time, not video playback duration.

## Limitations and error handling

Reference videos, reference audio, masks, first/last-frame controls, extension, and remix are unsupported. `quality` has no effect. Omit `seed`, `negative_prompt`, `width`, `height`, `response_format`, and `output_format`; they are outside this model's generation contract. `async: false` does not enable synchronous generation, and `stream` does not provide an SSE generation stream.

| HTTP / `error.code` | Action |
| - | - |
| `400 / invalid_request_error` | Check the prompt, reference count, aspect ratio, output count, and fixed output settings. |
| `409 / idempotency_in_progress` | Wait as directed by `Retry-After`, then retry the original request with the same idempotency key. |
| `409 / idempotency_key_reused` | The same key was used for different requests. Correct key handling; use a new key for each independent generation. |
| `409 / idempotency_result_indeterminate` | Stop automatic resubmission and retain the key and task details for investigation. |
| `429` | Back off according to `Retry-After` before retrying. |

Failed tasks may still return HTTP `200`; inspect `data.status` and `data.error.message`. A network error or `5xx` during submission may occur after acceptance, so do not immediately resubmit with a new key.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.