Video Generation Guide
Create, poll, and webhook flow for video generation. Parameters, status transitions, and error handling.
This guide explains how video generation works end-to-end: creating a request, polling for status, receiving webhooks, and handling errors.
Flow overview
Video generation is asynchronous. The flow has three parts:
- Create — Submit a generation request with
POST /v1/video/generations. You receive anidand initialstatus: "pending". - Poll — Call
GET /v1/video/generations/{id}repeatedly untilstatusiscompletedorfailed. - Webhook (optional) — Configure a webhook endpoint to receive
video.generation.completedevents when generations finish, so you don't need to poll.
For a minimal walkthrough, see the Quickstart Guide. For webhook setup, see Webhooks.
Create: POST /v1/video/generations
Submit a video generation request. The API validates your model, provider, and balance, then queues the job.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Yes* | Pipevideo model slug (e.g. google/veo-3.1). Use GET /v1/models to list available models. |
models | string[] | Yes* | Array of model slugs in priority order. On error (downtime, rate-limit, moderation), the next model is tried automatically. Use instead of model for fallbacks. |
prompt | string | Yes | Text description of the video to generate. |
provider | object | No | Provider routing preferences. See Provider routing below. When omitted, Pipevideo selects the lowest-price eligible route. |
*Either model or models (non-empty array) is required.
| Parameter | Type | Required | Description |
|---|---|---|---|
aspectRatio | string | No | Output aspect ratio (e.g. "16:9", "9:16", "1:1"). Model-specific; defaults vary by provider. |
duration | number | No | Video duration in seconds. Model-specific; defaults vary by provider (typically 5s). |
resolution | string | No | Output resolution (e.g. "720p", "1080p"). Used for route selection — routes matching the requested resolution are preferred. |
imageUrl | string | No | Image URL for image-to-video models. Only supported by some models/providers. |
withAudio | boolean | No | Enable audio generation. Applies an audio multiplier to the cost (typically 1.5x). Alias: audio. |
Additional parameters may be passed and are forwarded to the provider when supported. Provider-specific parameter names (e.g. aspect_ratio vs aspectRatio) are normalized internally.
Example request
curl -X POST https://api.pipevideo.co/v1/video/generations \
-H "Authorization: Bearer pv_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"model": "google/veo-3.1",
"prompt": "A cat walking on a beach at sunset",
"aspectRatio": "16:9",
"duration": 5
}'Example response
{
"id": "gen_abc123xyz",
"status": "pending",
"model": "google/veo-3.1",
"created_at": 1709827200
}Save the id — you use it to poll for the result or correlate with webhook events. The model field shows the initial model (first in the list when using models). The final model used is returned in the poll response.
Model fallbacks
Pass models (array) instead of model to enable automatic failover. If the primary model errors (downtime, rate-limit, moderation, context length), Pipevideo tries the next model in the list until one succeeds or the list is exhausted.
curl -X POST https://api.pipevideo.co/v1/video/generations \
-H "Authorization: Bearer pv_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"models": ["google/veo-3.1", "kling/3.0-pro", "wan/2.5"],
"prompt": "A cat walking on a beach at sunset",
"aspectRatio": "16:9",
"duration": 5
}'Billing is based on the model actually used. The model field in the poll response indicates which model completed the generation.
Provider routing
Control which provider handles your request using the provider object. When omitted, Pipevideo selects the lowest-price eligible route automatically.
| Field | Type | Description |
|---|---|---|
provider.order | string[] | Provider slugs to try in preference order (e.g. ["fal", "replicate"]). First available match wins; falls back to other eligible providers if none are available. |
provider.max_price | object | Cost constraints to filter eligible routes. |
provider.max_price.per_request_cents | number | Maximum total estimated cost per request in cents. Routes exceeding this are excluded. |
provider.max_price.per_second_cents | number | Maximum per-second cost in cents. Routes with a higher per-second rate are excluded. |
Prefer a specific provider:
curl -X POST https://api.pipevideo.co/v1/video/generations \
-H "Authorization: Bearer pv_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"model": "google/veo-3.1",
"prompt": "A cat walking on a beach at sunset",
"provider": {
"order": ["fal"]
}
}'Set a cost cap:
curl -X POST https://api.pipevideo.co/v1/video/generations \
-H "Authorization: Bearer pv_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"model": "google/veo-3.1",
"prompt": "A cat walking on a beach at sunset",
"provider": {
"order": ["fal", "replicate"],
"max_price": {
"per_request_cents": 500
}
}
}'Available provider slugs: fal, replicate. The vercel-gateway provider is used internally and is not user-selectable.
Poll: GET /v1/video/generations/{id}
Retrieve the current status and result of a generation. Poll this endpoint until status is completed or failed.
Response fields
| Field | Type | Description |
|---|---|---|
id | string | Generation ID. |
status | string | One of pending, processing, completed, failed. |
model | string | null | Model slug actually used. Relevant when using models fallbacks. |
output_url | string | null | When completed, the URL to download the video. |
cost_cents | number | null | Cost in cents when completed. |
latency_ms | number | null | End-to-end latency in milliseconds when completed. |
error_message | string | null | When failed, a human-readable error message. |
created_at | number | Unix timestamp when the request was created. |
completed_at | number | null | Unix timestamp when the generation finished (if completed or failed). |
Polling recommendations
- Interval: Poll every 2–5 seconds. Video generation typically takes 30 seconds to several minutes.
- Timeout: Stop polling after 10–15 minutes. If still
pendingorprocessing, treat as timed out and checkerror_messageor webhook for final status. - Webhooks: For production, prefer webhooks over polling to avoid unnecessary requests and get immediate notifications.
Webhooks
When a generation finishes (success or failure), Pipevideo sends a video.generation.completed webhook to your configured endpoint. This lets you avoid polling.
| Payload field | Description |
|---|---|
generationId | Matches the id from the create response. |
status | "completed" or "failed". |
outputUrl | Video URL when completed. |
errorMessage | Error details when failed. |
See Webhooks for setup, payload schema, signature verification, and retry behavior.
Status transitions
Generations move through these states:
pending → processing → completed
→ failed| Status | Meaning |
|---|---|
pending | Request created; not yet submitted to the video provider. |
processing | Submitted to the provider; waiting for the video to be generated. |
completed | Success. output_url contains the video URL. |
failed | Error. error_message contains the reason. Credits are refunded. |
Transitions are one-way. A generation never moves from completed or failed back to an earlier state.
Error handling
API errors (create / get)
| HTTP status | ORPC code | When |
|---|---|---|
| 401 | UNAUTHORIZED | Invalid or missing API key. |
| 429 | TOO_MANY_REQUESTS | Rate limit exceeded (100 requests/minute per key). Response includes retry_after. |
| 400 | BAD_REQUEST | Model not found, provider not initialized, organization not found, or insufficient balance. |
| 404 | NOT_FOUND | Generation not found (wrong ID or belongs to another org). |
| 500 | INTERNAL_SERVER_ERROR | Failed to create generation request. |
Generation failures (status: "failed")
When a generation fails, error_message (or the webhook errorMessage) explains the cause. Common cases:
| Cause | Description |
|---|---|
| Reservation failed | Insufficient credits or reservation error. No provider call made. |
| Provider submission failed | Provider rejected the request or returned an error. Credits refunded. |
| Provider callback timed out | Webhook-based providers (e.g. fal, Replicate) did not call back within 15 minutes. Credits refunded. |
| Generation timed out | Poll-based providers did not complete within ~10 minutes. Credits refunded. |
| Provider returned failure | The provider completed but reported a failure (e.g. content policy). Credits refunded. |
Failed generations are automatically refunded. Your credit balance is restored.
Webhook verification errors (provider callbacks)
Pipevideo receives callbacks from providers (fal, Replicate) to know when jobs finish. These are internal; you do not call them. If verification fails, Pipevideo returns 401 or 503 to the provider. Your generation may eventually time out and be marked failed with a refund.
Parameters by provider
Parameters are passed through to the underlying provider. Naming may differ:
| Parameter | fal | Replicate | Vercel Gateway |
|---|---|---|---|
prompt | Required | Required | Required |
aspectRatio | aspect_ratio (e.g. "16:9") | aspect_ratio | aspectRatio |
duration | duration (seconds) | duration | duration |
imageUrl | image_url (image-to-video) | imageUrl | Not used |
Model capabilities (supported aspect ratios, max duration) vary. Check the model details via GET /v1/models.
Next steps
- Quickstart — Make your first video generation.
- Webhooks — Configure webhooks for real-time completion notifications.
- Models — Browse available models and pricing.