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

# POST /v1/videos/generations

> Create a video generation job (async)

## Request body

<ParamField body="model" type="string" required>
  The namespaced model ID, e.g. `fal/kling-2`. See [Video models](/en/models/videos).
</ParamField>

<ParamField body="prompt" type="string" required>
  Video description. Maximum 4000 characters.
</ParamField>

<ParamField body="duration" type="integer">
  Duration in seconds. If you don't send it, we use the model default. Per-model cap (see catalog).
</ParamField>

<ParamField body="aspect_ratio" type="string">
  Video ratio. Examples: `16:9`, `9:16`, `1:1`, `4:5`. Support depends on the model.
</ParamField>

## Response (immediate, \~100ms)

```json theme={null}
{
  "id": "e8c96506-72a1-429f-a7ed-4bb0a42541be",
  "object": "video.job",
  "status": "processing",
  "model": "fal/kling-2",
  "prompt": "an astronaut surfing a giant wave of green salsa",
  "video_url": null,
  "duration": 5,
  "error": null,
  "created": 1782415166,
  "completed": null
}
```

<ResponseField name="id" type="string">
  The job\_id. Use it for polling.
</ResponseField>

<ResponseField name="status" type="string">
  Usually `processing`. Rare but possible `failed` if the submission to the provider blew up.
</ResponseField>

<ResponseField name="model" type="string">
  The model id you requested.
</ResponseField>

## Examples

<CodeGroup>
  ```python Kling 2 theme={null}
  job = client.post("/videos/generations", body={
      "model": "fal/kling-2",
      "prompt": "An astronaut surfing a giant wave of green salsa, cinematic",
      "duration": 5,
      "aspect_ratio": "16:9",
  })
  print(job["id"])
  ```

  ```python Veo 3.1 with audio theme={null}
  job = client.post("/videos/generations", body={
      "model": "google/veo-3.1",
      "prompt": "A hummingbird drinking from a cempasúchil flower at dawn, naturalistic foley",
      "duration": 8,
  })
  ```

  ```bash curl theme={null}
  curl -X POST https://api.geekhub.mx/v1/videos/generations \
    -H "Authorization: Bearer ghub_sk_live_xxx" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "fal/kling-2",
      "prompt": "An astronaut surfing a giant wave of green salsa",
      "duration": 5,
      "aspect_ratio": "16:9"
    }'
  ```
</CodeGroup>

## ⚠️ About cost

When you create the job **you are NOT charged yet**. The charge happens when the job transitions to `completed`. If it fails, there's no charge.

Safety cap: your balance is validated at **submit** — if it's ≤ 0 we return `402 insufficient_balance` before creating the job.

<Tip>
  Before sending many jobs in parallel, compute your max cost: `duration × model_price × markup × FX`. Example: 10 Kling 5s videos = `10 × 5 × $0.04 × 1.05 × 20 = $42 MXN`.
</Tip>

## Next step

<Card title="GET /v1/videos/{id}" icon="rotate" href="/en/api-reference/videos/poll">
  Poll the job status until it reaches `completed`.
</Card>
