# Generate a video

`POST https://api.vidmoat.com/v1/ai/videos`

- Scope: `ai.video`
- Cost: 80 to 320 credits per second

Start a generated clip with Grok, Alibaba HappyHorse or Wan 3.0. Returns a job to poll. Paid Studio only; trials and full-waiver promotions are excluded.

> **Note.** Priced per second, not flat. Grok: 80 credits a second (400 for the 5-second default, 1,200 for the 15-second maximum). HappyHorse 1.1 (`provider: "qwen"`): 112, 224 or 288 a second at 480p, 720p or 1080p, 3 to 15 seconds. Wan 3.0 (`provider: "wan"`): 80, 160 or 320 a second, 2 to 15 seconds. Use quoteOnly:true first, then pin the provider and maxCredits. One video job runs at a time per account. A HappyHorse first frame keeps the image's aspect ratio, so omit aspectRatio; HappyHorse has no audio control. Google video is not supported.

### Body

- `prompt` (string, required): Up to 800 characters.
- `durationSec` (integer, optional, default `5`): Whole seconds, from the provider's minimum (Grok 1, Wan 2, HappyHorse 3) to 15.
- `provider` (enum, optional, default `grok`): `qwen` is Alibaba HappyHorse 1.1. Auto picks the cheapest compatible route (and is the default when you ask for 1080p without a provider). One of `grok`, `qwen`, `wan`, `auto`.
- `resolution` (enum, optional, default `720p`): Grok does not do 1080p. One of `480p`, `720p`, `1080p`.
- `aspectRatio` (string, optional, default `16:9`): 16:9, 9:16, 1:1, 4:3, 3:4, 4:5, 5:4, 9:21 or 21:9 (Wan: 16:9, 9:16, 1:1, 4:3, 3:4, 21:9).
- `referenceUrls` (array of strings, optional): Up to 7 reference images for consistency: your uploads or public HTTPS images. Grok with references is limited to 720p. Not with `imageUrl`.
- `imageUrl` (string, optional): A starting frame. Not with `referenceUrls`.
- `withAudio` (boolean, optional, default `false`): Generate audio where the provider supports it (not HappyHorse).
- `projectId` (string, optional): Project to attach the job to.
- `maxCredits` (number, optional): Never spend more than this.
- `quoteOnly` (boolean, optional): `true` returns the route and price without starting a job.

## Response

Returns `202`.

### Response fields

- `id` (string): The job id. Poll it with Get a generation job.
- `status` (string): `PROCESSING`.
- `durationSec` (integer): Seconds billed.
- `credits` (object): `{ charged, remaining, basis }`.
- `poll` (string): The path to poll.

> **Tip: With a test key.** Test keys return a finished sample job at once (`status: "COMPLETED"`, a fixture `outputUrl`) and spend nothing. No validation or quote runs.

## Errors

Besides the errors any request can get ([authentication](https://developer.vidmoat.com/developer/docs/authentication#when-a-request-is-refused), [rate limits](https://developer.vidmoat.com/developer/docs/rate-limits)):

| Status | Code | When |
| --- | --- | --- |
| 400 | [`invalid_request`](https://developer.vidmoat.com/developer/docs/errors#invalid_request) | No prompt, or a refused reference. |
| 402 | [`plan_required`](https://developer.vidmoat.com/developer/docs/errors#plan_required) | The plan has no video generation. |
| 402 | [`insufficient_credits`](https://developer.vidmoat.com/developer/docs/errors#insufficient_credits) | Not enough credits, or the account is on a trial or a full-waiver promotion. |
| 402 | [`quota_exceeded`](https://developer.vidmoat.com/developer/docs/errors#quota_exceeded) | A video job is already running on the account. |
| 422 | [`prompt_rejected`](https://developer.vidmoat.com/developer/docs/errors#prompt_rejected) | The prompt failed the safety check. Nothing was charged. `field` names the field. |
| 502 | [`provider_error`](https://developer.vidmoat.com/developer/docs/errors#provider_error) | The generation provider failed. The charge is refunded. |

## Request examples

```bash curl
curl -X POST https://api.vidmoat.com/v1/ai/videos \
  -H "Authorization: Bearer $VIDMOAT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"drone over a harbour at dawn","durationSec":5}'
```

```js Node
const res = await fetch('https://api.vidmoat.com/v1/ai/videos', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.VIDMOAT_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    prompt: 'drone over a harbour at dawn',
    durationSec: 5,
  }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error?.message ?? `HTTP ${res.status}`);
console.log(data);
```

```python Python
import os
import requests

res = requests.post(
    "https://api.vidmoat.com/v1/ai/videos",
    headers={"Authorization": f"Bearer {os.environ['VIDMOAT_KEY']}"},
    json={
      "prompt": "drone over a harbour at dawn",
      "durationSec": 5,
    },
    timeout=60,
)
res.raise_for_status()
print(res.json())
```

## Example response

```json
{
  "id": "cm_job_1",
  "status": "PROCESSING",
  "durationSec": 5,
  "credits": { "charged": 400, "remaining": 5600, "basis": "80 credits/second of generated video (grok-imagine-video)" },
  "poll": "/api/v1/ai/jobs/cm_job_1"
}
```

---

Source: https://developer.vidmoat.com/developer/docs/api/generation/create-video
Previous: [Generate a sticker](https://developer.vidmoat.com/developer/docs/api/generation/create-sticker.md)
Next: [Get a generation job](https://developer.vidmoat.com/developer/docs/api/generation/get-generation-job.md)
All documentation: https://developer.vidmoat.com/llms-full.txt
