Get video status
GET https://api.ofox.ai/v1/videos/{id}Query the status and result of a task. After you create a task, poll this endpoint until status reaches a terminal state — completed, failed, cancelled, or expired.
curl https://api.ofox.ai/v1/videos/9bcf3c60-7db2-4e1a-a1b2-c3d4e5f60718 \
-H "Authorization: Bearer $OFOX_API_KEY"Rate limiting
This endpoint is rate-limited per API key (default 5 req/s with a burst of 20). Requests over the limit return 429 rate_limited with a Retry-After: 1 header. Creating (POST) and cancelling (DELETE) are not subject to this limit.
Poll no faster than once per second, or supply a callback_url when you create the task to receive a webhook instead of polling.
Response
Completed
{
"id": "9bcf3c60-7db2-4e1a-a1b2-c3d4e5f60718",
"status": "completed",
"model": "google/veo-3.1",
"prompt": "A golden retriever running on the beach at sunset",
"unsigned_urls": ["https://upstream.example/out.mp4"],
"mirror_urls": ["https://cdn.ofox.ai/videos/vgen_xxx.mp4?sig=..."],
"usage": {
"video_seconds": 5,
"video_cost": "0.4000000000"
},
"created_at": 1776211362,
"updated_at": 1776211400
}A timeout is reported as status: "failed" with error.code set to expired. For the full list of error codes, see Error codes.
The Video object
| Field | Type | Description |
|---|---|---|
id | string | Unique task identifier (UUID) |
status | enum | See State machine |
model | string | Model slug |
prompt | string | Original prompt |
unsigned_urls | string[] | Present when completed. Upstream original video URL (temporary, may expire in 24h) |
mirror_urls | string[] | Present when completed and the model’s provider has CDN mirroring enabled. Persistent signed URL — see Video URLs |
error | object | Present when failed: {code, message} |
usage | object | Present when completed: {video_seconds, video_cost}. video_seconds is the billed seconds (includes v2v input seconds); video_cost is the actual charge at the platform tier price, a fixed-point 10-decimal string (avoids precision loss) |
created_at / updated_at | integer | Unix seconds |
State machine
Seven states, built on the OpenRouter naming and extended with cancelled / expired.
| Status | Terminal | Description |
|---|---|---|
pending | — | Accepted, not yet submitted upstream |
queued | — | Submitted upstream, waiting in queue |
in_progress | — | Generating upstream |
completed | ✓ | Success, video URLs available |
failed | ✓ | Failed (including timeout, error.code=expired) |
cancelled | ✓ | Cancelled |
expired | ✓ | Expired |
Transitions: pending → queued → in_progress → completed is the success path. Any non-terminal state can move to failed, cancelled, or expired.
Video URLs
A successful task may return two sets of URLs, depending on whether the model’s provider has CDN mirroring enabled.
| Field | Source | Characteristics |
|---|---|---|
unsigned_urls | Upstream provider’s original address | Temporary — always present · may expire in 24h · unsigned |
mirror_urls | ofox CDN mirror | Persistent — only for CDN-enabled providers · signed on each request · has a TTL |
Prefer mirror_urls (persistent and stable). When a model returns only unsigned_urls, download or re-host the file promptly before the upstream temporary address expires.