New: Audio API, Embeddings & Realtime WebSocket now available!
osmAPI LogoosmAPI

Video Generation

Generate video with Google Veo through the async /v1/videos API

Video Generation

osmAPI generates video with Google Veo through a dedicated, asynchronous /v1/videos API. Because a single clip can take from ~15 seconds to several minutes to render, generation is a long-running job: you create a job, poll it until it finishes, then download the resulting MP4.

Video generation is currently Google Veo only. It is a separate flow from chat — video models do not appear in the chat model selector.

Available models

You can find all video models on the models page.

Model IDNotes
veo-3.1-generate-previewFlagship. 720p/1080p/4k, audio, all input modes
veo-3.1-fast-generate-previewSpeed-optimized 3.1
veo-3.1-lite-generate-previewMost cost-effective (no 4k)
veo-3.0-generate-001Veo 3 (GA)
veo-3.0-fast-generate-001Veo 3 Fast (GA)
veo-2.0-generate-001Veo 2 (GA), durations 5/6/8s

Capabilities by model

Not every input mode works on every model. Capabilities come from the model catalogue, so the playground and API enforce them automatically.

CapabilityVeo 3.1Veo 3.1 FastVeo 3.1 LiteVeo 3Veo 3 FastVeo 2
Text-to-video
Image-to-video
First/last frame
Reference images (≤3)
Extend / continue
Resolutions720/1080/4k720/1080/4k720/1080720/1080720/1080/4k720
Durations (s)4/6/84/6/84/6/84/6/84/6/85/6/8
Audio

Lifecycle

1. Create a job

curl -X POST "https://api.osmapi.com/v1/videos" \
  -H "Authorization: Bearer $OSM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "veo-3.0-fast-generate-001",
    "prompt": "A cinematic shot of a mango tree swaying at dusk",
    "aspect_ratio": "16:9",
    "resolution": "720p",
    "duration": 8
  }'

Returns 202 Accepted:

{
	"id": "abc123…",
	"object": "video.generation",
	"status": "in_progress",
	"polling_url": "/v1/videos/abc123…",
	"metadata": {
		"used_model": "veo-3.0-fast-generate-001",
		"resolution": "720p",
		"duration_seconds": 8,
		"estimated_cost_usd": 0.8
	}
}

2. Poll for completion

curl "https://api.osmapi.com/v1/videos/abc123…" \
  -H "Authorization: Bearer $OSM_API_KEY"
{
	"id": "abc123…",
	"status": "completed",
	"video": { "url": "/v1/videos/abc123…/content", "mime_type": "video/mp4" },
	"usage": {
		"duration_seconds": 8,
		"resolution": "720p",
		"cost_usd": 0.8,
		"cost_inr": 75.2
	}
}

status is one of queued, in_progress, completed, or failed. Poll every few seconds; osmAPI does the upstream polling for you, so this read is cheap and never calls Google directly.

3. Download the video

curl -L "https://api.osmapi.com/v1/videos/abc123…/content" \
  -H "Authorization: Bearer $OSM_API_KEY" -o video.mp4

If object storage is configured, this proxy-streams the MP4 from the private storage bucket through the gateway; otherwise it proxy-streams from Google. Either way the underlying storage URL is never exposed to the browser.

Generated videos are retained on Google's servers for ~2 days, and on osmAPI's object storage for 30 days (then auto-deleted). See Storage & retention below.

Storage & retention

  • Default: every completed video is uploaded to object storage and videoUrl / storageKind="s3" are stored on the job row. The file lives for 30 days, then a background worker deletes it. GET /v1/videos/:id/content proxy-streams it from the private bucket (with Range support for seeking); the bucket is never exposed publicly.
  • retention=none (org-level setting): osmAPI does not upload to object storage. GET /v1/videos/:id/content proxy-streams the MP4 directly from Google for the ~48-hour window that the upstream signed URL is valid, then the video becomes unavailable.
  • No S3 configured: same behavior as retention=none.

The retention sweep runs every ~5 minutes. It deletes the S3 object first, then clears the row's storage pointers — so a failed S3 delete is retried, and crashed workers never leave orphan objects.

List recent videos (history)

GET /v1/videos returns the most recent video jobs for the bearer's organization. Useful for showing a history list in your UI.

curl "https://api.osmapi.com/v1/videos?limit=30" \
  -H "Authorization: Bearer $OSM_API_KEY"
{
	"object": "list",
	"data": [
		{
			"id": "abc123…",
			"object": "video.generation",
			"status": "completed",
			"prompt": "A cinematic shot of a mango tree swaying at dusk",
			"created": 1748505600,
			"completed_at": 1748505720,
			"video": {
				"url": "/v1/videos/abc123…/content",
				"mime_type": "video/mp4",
				"storage": "s3"
			},
			"usage": {
				"duration_seconds": 8,
				"resolution": "720p",
				"cost_usd": 0.8,
				"cost_inr": 75.2
			},
			"error": null,
			"metadata": {
				"used_model": "veo-3.0-fast-generate-001",
				"used_provider": "google-ai-studio"
			}
		}
	]
}

Query params:

  • limit — max 100, default 30.

The history endpoint sets Cache-Control: no-store so newly completed videos always appear on the next fetch. Videos whose media has been retention-swept come back with video: null (the job row still exists for audit / cost history).

Request parameters

FieldTypeDescription
modelstringA Veo model ID (required).
promptstringText description; supports audio cues (required).
aspect_ratio16:9 | 9:16Default 16:9.
resolution720p | 1080p | 4kDefault 720p. 1080p/4k require an 8s clip; Lite has no 4k.
durationnumberSeconds. 4/6/8 (Veo 2: 5/6/8).
negative_promptstringWhat to avoid.
seednumberImproves repeatability (Veo 3+).
person_generationallow_all | allow_adultAuto-selected per input mode if omitted.
imagedata URL | { data, mime_type }Init frame for image-to-video.
last_framedata URL | { data, mime_type }Closing frame for interpolation (requires image).
reference_imagesarray (≤3)Asset images to preserve a subject (Veo 3.1 / 3.1 Fast).
source_video_idstringExtend a prior osmAPI video job (Veo 3.1 / 3.1 Fast, 720p).

Only one advanced input mode may be used at a time: image-to-video, reference images, or extension.

Input modes

Image-to-video

{
	"model": "veo-3.0-fast-generate-001",
	"prompt": "Animate this scene with a slow zoom",
	"image": { "data": "<base64>", "mime_type": "image/png" },
}

First / last frame interpolation

Provide an image (first frame) and a last_frame (closing frame) to control how the shot begins and ends.

Reference images (Veo 3.1 / 3.1 Fast)

Up to three asset images keep a subject (person, character, or product) consistent across the clip. Reference images force an 8-second clip.

{
	"model": "veo-3.1-fast-generate-preview",
	"prompt": "She walks confidently through a sunlit lagoon",
	"reference_images": [
		{ "data": "<base64>", "mime_type": "image/png" },
		{ "data": "<base64>", "mime_type": "image/png" },
	],
}

Video extension (Veo 3.1 / 3.1 Fast)

Extend a previously generated 720p clip by ~7 seconds. Reference an earlier job by id:

{
	"model": "veo-3.1-fast-generate-preview",
	"prompt": "Continue the scene as the camera pulls back",
	"source_video_id": "abc123…",
}

Pricing

Veo is metered per second of generated video, by resolution tier:

Model720p / sec1080p / sec4k / sec
Veo 3.1$0.40$0.40$0.60
Veo 3.1 Fast$0.10$0.12$0.30
Veo 3.1 Lite$0.05$0.08
Veo 3$0.40$0.40
Veo 3 Fast$0.10$0.12$0.30
Veo 2$0.35

Cost is computed as per-second rate × duration. Blocked or failed generations are not charged.

Safety & limits

  • Safety filters. Veo blocks prompts/outputs that violate Google's policies — including recreating real, identifiable people (e.g. public figures). A blocked generation finishes with no video and is not charged; osmAPI surfaces it as Blocked by safety filters.
  • Watermarking. All Veo output is watermarked with SynthID.
  • Retention. Generated videos live on Google's servers for ~2 days. If object storage (S3) is configured, osmAPI persists a durable copy; otherwise download within the window.
  • Input formats. Images: PNG / JPEG / WEBP, ≤ ~12 MB. Extension input must be a Veo-generated 720p MP4 (16:9 or 9:16), ≤ 141 s, within 2 days.
  • Latency. ~15 s to ~6 minutes depending on model, resolution, and length.

Video Studio (Playground)

The Video Studio is a chat-style interface for the API above. Pick a Veo model and the available controls (resolutions, durations, reference images, extension) adapt automatically, with a live ₹ cost estimate before you generate.

One window = one video

Veo has no conversational memory — each generation is an independent API call. To build a longer, coherent video the Studio uses Veo's extension:

  • Your first prompt generates a clip.
  • Each following prompt in the same window continues that video (+~7s), on extension-capable models (Veo 3.1 / 3.1 Fast, 720p). The composer shows "Continuing your video".
  • New video (top bar) clears everything and starts a fresh, unrelated clip.
  • Continue from here on an earlier clip branches the next prompt off of it.

This mirrors Google Flow's Scene Builder: independent shots chained through extension, rather than a chat that "remembers" context.

Extension is prompt-only — when continuing a video, image / last-frame / reference inputs don't apply (Veo takes just a prompt plus the prior clip). Start a New video to use those inputs again.

Other actions

  • Regenerate re-runs a result with the exact same request.
  • Download MP4 saves the clip.
  • Org is chosen in the header; the project is the org's default (the playground key is project-scoped), matching the chat playground.

How is this guide?