Get Video
Retrieve the real-time processing status, progress percentage, and execution metadata for an asynchronous video generation job across supported providers.
Last updated
The /v1/videos/{id} endpoint retrieves the real-time processing status, progress metrics, and execution metadata for an asynchronous video generation job. Use this endpoint to poll the rendering lifecycle after submitting a generation job to POST /v1/videos.
GET https://api.nrouter.ai/v1/videos/{id}Tracks queued, processing, completed, and failed execution states accurately.
Status polling queries carry zero inference cost and deduct no credits.
Provides numeric rendering percentage for rich client-side progress bars.
Job handles are cryptographically isolated and accessible only to owning organizations.
Architectural Role & Polling Best Practices
Video generation pipelines take between 15 seconds and several minutes depending on provider cloud availability, resolution, and clip duration. nRouter recommends an exponential backoff or 3–5 second interval polling pattern:
- Phase 1: In-Memory Key Auth & Tenancy Check: Authenticates the virtual key (
sk-nrouter-...) and checks job ownership. If a key attempts to query another organization's job handle, the gateway returns HTTP 404 Not Found (model_not_found/ resource not found) to prevent unauthorized enumeration. - Provider State Synchronization: Queries upstream provider status and normalizes external state strings into standardized nRouter lifecycle states:
queued: Job accepted and waiting for GPU capacity.processing: Rendering is actively underway.completed: Video rendering is finished; ready for binary download.failed: Upstream generation encountered an error or policy refusal.
- Credit Hold Settlement: When status transitions to
completed, nRouter commits final billing against the organization's account at raw provider duration list prices. If the job entersfailed, the credit reservation hold is released immediately ($0 charged).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The unique video generation job identifier (e.g. nrouter_video_01j89azxckm3287). |
Request & Response Headers
Inbound Request Headers
| Header | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer authentication format: Bearer sk-nrouter-.... |
Outbound Response Headers
| Header | Type | Description |
|---|---|---|
x-nr-request-id | string | Unique UUID correlation identifier for tracing. |
x-nr-latency-ms | integer | Gateway turnaround time in milliseconds. |
x-nr-model | string | Upstream physical video model rendering the asset. |
Response Payloads
Processing State Response
{
"id": "nrouter_video_01j89azxckm3287",
"object": "video",
"status": "processing",
"progress": 65,
"created_at": 1709251200
}Completed State Response
{
"id": "nrouter_video_01j89azxckm3287",
"object": "video",
"status": "completed",
"progress": 100,
"created_at": 1709251200,
"completed_at": 1709251245,
"model": "veo-2.0"
}SDK Code Examples with Polling Loop
import { nRouter } from "@nrouter_ai/sdk";
const client = new nRouter({
apiKey: process.env.NROUTER_API_KEY,
});
async function pollVideoUntilReady(jobId: string): Promise<void> {
let isDone = false;
while (!isDone) {
const video = await client.videos.retrieve(jobId);
console.log(`Job ${jobId} status: ${video.status} (${video.progress ?? 0}%)`);
if (video.status === "completed") {
isDone = true;
console.log("Video is ready for download!");
} else if (video.status === "failed") {
throw new Error(`Video rendering failed: ${JSON.stringify(video.error)}`);
} else {
// Wait 4 seconds before next poll
await new Promise((res) => setTimeout(res, 4000));
}
}
}
await pollVideoUntilReady("nrouter_video_01j89azxckm3287");Error Handling & Failure Diagnoses
{
"error": {
"type": "gateway_error",
"message": "Video job nrouter_video_01j89azxckm3287 not found.",
"code": "model_not_found"
}
}| HTTP Status | Error Code | Root Cause | Recommended Action |
|---|---|---|---|
| 401 Unauthorized | invalid_api_key | Virtual key missing, expired, or invalid. | Check Authorization: Bearer sk-nrouter-... key in dashboard. |
| 404 Not Found | model_not_found | Job ID does not exist or belongs to another tenant organization. | Verify the job identifier returned by POST /v1/videos. |
| 429 Too Many Requests | rate_limit_exceeded | Polling frequency exceeded RPM rate limit. | Increase client-side polling interval (recommend 3–5 seconds). |
Production Polling Architecture
Asynchronous video generation jobs progress through discrete lifecycle states: queued, processing, completed, or failed. Because video generation requires substantial compute resources spanning 15 to 90 seconds, status polling is deliberately unmetered and free of token charges.
State Transition Lifecycle
[ POST /v1/videos ] ──► ( queued ) ──► ( processing ) ──► ( completed ) ──► [ GET /v1/videos/{id}/content ]
│ │
▼ ▼
( failed ) ( rejected )- Queued: The generation prompt has been validated against safety guardrails, funds reserved against organization balance, and dispatched to the upstream rendering cluster.
- Processing: Active GPU rendering and encoding are underway. Progress percentages may be returned if supported by the provider.
- Completed: The binary MP4 asset is encoded and uploaded to low-latency edge CDN caches. Ready for download via
GET /v1/videos/{id}/content. - Failed: Rendering encountered an upstream provider exception or reached maximum render timeout. Reserved credits are automatically refunded.
- Rejected: Prompt or generated frames triggered content policy violations. Detailed violation categories are included in the error payload.
Best Practices for Client-Side Polling
- Initial Delay: Video synthesis takes a minimum of 8–10 seconds. We strongly recommend delaying your first poll request until 8 seconds after job dispatch.
- Adaptive Polling Intervals: Increase your polling interval gradually: 4s, 5s, 6s, up to 10s. This minimizes unnecessary network roundtrips.
- Circuit Breakers & Hard Timeouts: Implement a client-side hard ceiling (e.g. 5 minutes). If a job does not complete within this window, trigger your application's failover handler.
- Zero-Cost Guarantees: Polling
GET /v1/videos/{id}never decrements your organization token balance. Credits are only committed upon verified job success.
Production Resiliency & Asynchronous Orchestration
In enterprise rendering workloads, polling architectures should pair with automated fallback pipelines. When rendering large batch generations:
- Store the returned
idin your persistent datastore (PostgreSQL, Redis) alongside your tenant or user ID. - Use a background job queue (BullMQ, Celery, Temporal) rather than keeping frontend HTTP connections alive.
- If a generation fails with provider-specific capacity constraints, nRouter automatically attempts fallback to secondary regional rendering clusters without requiring client intervention.
- Audit trails for all video dispatch and polling transactions are retained in your organization compliance logs for 90 days.
Authorization
NRouterApiKey Your nRouter virtual key (sk-nrouter-…). Sent as Authorization: Bearer sk-nrouter-….
In: header
Path Parameters
Header Parameters
Target MCP server ID when routing MCP tool calls or prompts through the gateway
Response Body
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/videos/string"{ "id": "nrouter_video_01", "object": "video", "status": "completed"}