Endpoints
Video (async jobs)
Create video generation jobs with POST /videos on api14, poll GET /videos/{id} until they finish and download the finished result.
Try it in the playgroundGenerate video with Veo 3.1, Sora 2 Pro, Kling, Seedance, Runway, Wan, Hailuo and more. Video generation takes from tens of seconds to several minutes, so it runs as an asynchronous job: you create a job, poll its status, then download the result.
| Step | Request |
|---|---|
| 1. Create | POST /api/v1/videos |
| 2. Poll | GET /api/v1/videos/{id} |
| 3. Download | GET /api/v1/videos/{id}/content?index=0 |
Create a job
POST https://api14.com/api/v1/videos
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | yes | A video model id, e.g. google/veo-3.1-fast. |
prompt | string | yes | What happens in the video. |
duration | number | no | Length in seconds. Defaults to the model's first supported duration. |
resolution | string | no | e.g. 720p, 1080p. Must be supported by the model. |
aspect_ratio | string | no | e.g. 16:9, 9:16. |
generate_audio | boolean | no | Generate a soundtrack where supported (default true). |
image | string | no | First frame as a URL or data: URI (image-to-video). |
Supported durations, resolutions and aspect ratios per model: GET /videos/models (public) or the model page.
Balance check
Before the job is submitted, the gateway estimates its price as duration × the per-second price for the requested resolution (and audio option). If your balance is lower than the estimate the request fails with 402 insufficient_balance and nothing is started.
Response
{
"id": "vid_01JABCDEF",
"status": "queued",
"polling_url": "/api/v1/videos/vid_01JABCDEF"
}
Poll the job
GET https://api14.com/api/v1/videos/{id}
{
"id": "vid_01JABCDEF",
"status": "completed",
"generation_id": "gen-1791100000-abc",
"unsigned_urls": ["/api/v1/videos/vid_01JABCDEF/content?index=0"],
"usage": { "cost": 1.2 }
}
status | Meaning |
|---|---|
queued | Waiting for the provider. |
in_progress | Rendering. |
completed | Done; unsigned_urls lists the outputs. |
failed, cancelled, expired | Finished without output; see error. You are not charged. |
Poll every 5–10 seconds. Only the account that created the job can read it; other ids return 404 not_found.
Download the result
GET https://api14.com/api/v1/videos/{id}/content?index=0
Returns the video bytes (usually video/mp4) with your API key. Output URLs always point to the gateway, never to the upstream provider. If the file is not ready or has expired you get content_unavailable.
Example
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api14.com/api/v1",
apiKey: process.env.API14_API_KEY,
});
// Video generation is asynchronous: submit, then poll until completed.
let job = await client.post("/videos", { body: {
"model": "google/veo-3.1-fast",
"prompt": "A drone shot over turquoise ocean waves at sunrise",
"duration": 8,
"resolution": "720p",
"aspect_ratio": "16:9"
} });
while (!["completed", "failed"].includes(job.status)) {
await new Promise((r) => setTimeout(r, 5000));
job = await client.get(`/videos/${job.id}`);
}
console.log(job.status, job.unsigned_urls);
Billing
You are charged once, when the job reaches completed, using the provider's actual cost. Failed, cancelled and expired jobs are free. Jobs also complete in the background, so a job you never poll is still settled and shows up in Usage.
Errors
| Status | Code | When |
|---|---|---|
| 402 | insufficient_balance | Balance is below the job's estimated price. |
| 403 | plan_required | Your plan does not include video models. |
| 404 | model_not_found / not_found | Unknown model, or job id not yours. |
| 502 | upstream_unavailable | Status could not be read; retry. |
See Errors.