# Create a video from a text prompt with Vimmerse's API

Vimmerse's text-to-video API turns a prompt into a short video clip. One paid `POST https://agents.vimmerse.net/zcj/i0avc4ah0yq9/v2/media` call starts the job, and polls of `GET https://agents.vimmerse.net/zcj/i0avc4ah0yq9/v2/media/{media_id}` return the file URL when the clip is ready. Each job costs the credits its estimate route returns, at $0.03: a 5-second clip on `Auto` is quoted 40 credits, or $1.20. You send the request with your access token, pay the 402 price quote over x402 or MPP, and retry. No API key is needed.

## At a glance

- **Endpoints:** `POST https://agents.vimmerse.net/zcj/i0avc4ah0yq9/v2/media` starts a job. `GET https://agents.vimmerse.net/zcj/i0avc4ah0yq9/v2/media/{media_id}` polls it.
- **Body:** `prompt` and `duration` in seconds. Optional fields are `video_tool` (default `Auto`), `aspect_ratio`, `quantity`, `media_items`, `audio_option` and `webhook_url`.
- **Price:** the `total_credits` from `POST https://agents.vimmerse.net/zcj/i0avc4ah0yq9/v2/media/estimate-credits`, at $0.03.
- **Payment:** a 402 price quote, which you pay over x402 or MPP (wallet rails settling in USDC) and then retry. Send `ZC-Agent-Authorization: Bearer <access_token>` on the same request.
- **Response:** `id` and `processing_status`. On `success`, `result` holds `url`, `thumbnail_url`, `thumbnail_video_url` and `size`.
- **Estimate and poll:** both draw nothing.
- **Full purchase flow:** [the buyer skill](https://agents.vimmerse.net/zcj/i0avc4ah0yq9/SKILL.md)

## Create the clip

1. **Get an access token.** A bearer credential is the agent identity the storefront issues. You register it once, and an anonymous registration needs no email. You then exchange it for a short-lived `access_token`. [The identity guide](https://agents.vimmerse.net/zcj/i0avc4ah0yq9/auth.md) has the steps.

2. **Estimate the credits.** This call draws nothing and starts no job.

   ```bash
   curl -s -X POST https://agents.vimmerse.net/zcj/i0avc4ah0yq9/v2/media/estimate-credits \
     -H "Authorization: Bearer $ACCESS_TOKEN" \
     -H 'Content-Type: application/json' \
     -d '{"video_tool": "Auto", "duration": 5}'
   ```

   The response is `{"total_credits": <credits>, "breakdown": {...}}`.
   - On `Auto`, 5 seconds is quoted 40 credits.
   - On `Auto`, 10 seconds is quoted 80 credits, and the breakdown includes a `duration_over_5s_multiplier`.

   At pay-as-you-go rates, those quotes are $1.20 and $2.40.

3. **Send the create request with your token.**

   ```bash
   curl -s -X POST https://agents.vimmerse.net/zcj/i0avc4ah0yq9/v2/media \
     -H "ZC-Agent-Authorization: Bearer $ACCESS_TOKEN" \
     -H 'Content-Type: application/json' \
     -d '{"prompt": "a lighthouse on a rocky coast at dusk, waves rolling in, slow camera push", "duration": 5, "title": "Lighthouse at dusk"}'
   ```

   The storefront answers with a 402 price quote for the estimate's credits at $0.03. A 402 carries its challenge in a response header:
   - `payment-required` for x402
   - `www-authenticate` for MPP

   Sign it and retry the identical request with the proof attached, keeping the token header:
   - **x402:** add `-H "x-payment: <signed payload>"`.
   - **MPP:** add `-H "Authorization: Payment <credential>"`.

   An automatic MPP client keeps `ZC-Agent-Authorization` when you set it on the first request. This example was quoted 40 credits and paid $1.20. The paid response is the media object:

   ```json
   {"id": "<media_id>", "video_tool": "Auto", "processing_status": "processing", "result": []}
   ```

   The token goes on the paid call so that the job belongs to the identity that polls it. A job paid with no identity belongs to the wallet, and a poll with your token then answers 404.

4. **Poll until the job finishes.** Polling draws nothing.

   ```bash
   curl -s https://agents.vimmerse.net/zcj/i0avc4ah0yq9/v2/media/<media_id> \
     -H "Authorization: Bearer $ACCESS_TOKEN"
   ```

   - Poll at intervals of tens of seconds, not in a tight loop.
   - Stop on a terminal status. `success` means the clip is ready.
   - Add `?fields=processing_status,result` to return only those keys.

   In the 5-second example, `processing_status` reached `success` 2 minutes 44 seconds after `created_at`.

5. **Read the result.**

   ```json
   {
     "id": "<media_id>",
     "processing_status": "success",
     "used_credits": <credits>,
     "resolution": [<width>, <height>],
     "result": [
       {"url": "<video_url>", "thumbnail_url": "<image_url>", "thumbnail_video_url": "<preview_url>", "size": <bytes>}
     ]
   }
   ```

   - `url` is the video file. Download it to keep a copy.
   - `thumbnail_url` is a still image.
   - `thumbnail_video_url` is returned alongside it.
   - `size` is the file size in bytes.
   - `resolution` is an array of two numbers.
   - `used_credits` is the credits the job was charged.

## Choose the request fields

`video_tool`, `duration`, `quantity` and `audio_option` change the credits. `prompt`, `aspect_ratio`, `loop` and `pipeline_mode` do not. Send the same pricing fields to the estimate route before you pay.

| Need | Field | Value |
| --- | --- | --- |
| A specific model | `video_tool` | `Auto` (default), or a named tool such as `Veo`, `VeoFast`, `KlingAI`, `KlingPro`, `Seedance` or `RunwayML` |
| A frame shape | `aspect_ratio` | A ratio string such as `16:9` |
| Several outputs from one job | `quantity` | `1` to `4` |
| A start or end frame from an image | `media_items` | `[{"type": "image", "url": "https://…", "position": "First"}]`, plus a second object with `"position": "Last"` for the end frame |
| Narration or background music | `audio_option` | `{"narrator": "AutoV", "narration": "…", "bg_music_prompt": "…"}` |
| Sound generated by the video tool | `audio_option` | `{"native_audio": true}`, on tools that support it |
| Status updates without polling | `webhook_url` | Your callback URL |

## Limits

- One create call starts one job. `quantity` sets the number of outputs within that job.
- `media_items` takes public https URLs only. The server fetches each one with no cookies and no `Authorization` header.
- `media_items` does not accept file uploads, local paths, data URIs or audio. Audio goes in `audio_option`.
- The estimate route prices `duration` from 1 to 15 seconds.
- Nothing is charged until you pay the 402, so it is safe to stop at the quote. The paid create call is the only charge. A response with no `zc-billing` header billed nothing.
- A timeout after paying is an uncertain result. If you have the `id`, poll it. Do not pay again before you reconcile.

## Errors

| Response | Meaning | Action |
| --- | --- | --- |
| `402` with a `payment` block | The price quote. Nothing is charged yet. | Pay and retry the same request, or stop |
| `404` `MEDIA_NOT_FOUND` on a poll | This token cannot see the job: the id is wrong, or the paid call carried no token | Check the id. Send the token on every paid create call |
| `401` `invalid_token` | The token expired or did not verify | Exchange the stored assertion for a fresh token and retry |
| `invalid_token` with reason `combined_authorization_unsupported` | `Authorization` held both a payment credential and a bearer | Move the bearer to `ZC-Agent-Authorization` |
| `422` | The body failed validation, for example `media_items` sent as a string | Send `media_items` as a JSON array and `audio_option` as an object |
| `settlement_failed` | The payment did not settle | Fix the wallet, then send the request again for a fresh 402 |
| `payment_consumed` | That payment was already spent | Poll the job by id. Do not pay again |

## Frequently asked questions

### How much does a text to video clip cost with Vimmerse's API?

A clip costs the estimate's `total_credits` times $0.03. On `Auto`, the estimate route quotes 40 credits for 5 seconds. It quotes 80 credits for 10 seconds. At pay-as-you-go rates, that is $1.20 and $2.40. The 402 states the exact amount before you pay.

### Can I choose Veo or Kling for video generation?

Yes. Set `video_tool` to one of the values the spec lists, such as `Veo`, `VeoFast`, `KlingAI` or `KlingPro`, or leave it as `Auto`. Credits depend on the tool tier, so estimate with the same `video_tool` before you pay.

### Does the video generation API need an API key?

No. Each job is paid per call through a 402 quote. The only credential is the free access token the storefront issues. It ties the job to your identity, so the polls can find it.

### Why does polling my media id return 404?

The poll can only find jobs owned by the identity that sends it. Send `ZC-Agent-Authorization: Bearer <access_token>` on the paid create call, then poll with `Authorization: Bearer` and the same token.

### Can I prepay credits instead of paying per clip?

Yes. Prepaid plans let calls draw down a balance:

| Plan | Price | Minimum purchase |
| --- | --- | --- |
| Credits | $28 per thousand credits | $14 |
| Pro credits | $24 per thousand credits | $120 |
| Business credits | $20 per thousand credits | $1000 |

Buy a plan with `POST /plans/{planId}/purchase` and your bearer, using a plan id from the manifest. A card can also pay a single pay-as-you-go call of $0.50 or more.

## Keep reading

- [The buyer skill](https://agents.vimmerse.net/zcj/i0avc4ah0yq9/SKILL.md): the full purchase flow
- [Identity](https://agents.vimmerse.net/zcj/i0avc4ah0yq9/auth.md): register a credential and get an access token
- [How to pay](https://agents.vimmerse.net/zcj/i0avc4ah0yq9/payment.md): x402, MPP, card and prepaid credits
- [Error reference](https://agents.vimmerse.net/zcj/i0avc4ah0yq9/errors.md): every storefront error code
- [AI Video service](https://agents.vimmerse.net/zcj/i0avc4ah0yq9/services/media): prices for this service on every plan

---

Updated 2026-11-06. All Vimmerse guides: https://agents.vimmerse.net/guides.md. Storefront: https://agents.vimmerse.net/zcj/i0avc4ah0yq9/llms.txt.
