Job Polling
Long-running image and video generations run asynchronously. You create a job through POST /v1/images/generations, then poll GET /v1/images/generations/:id until it finishes. This page covers the full lifecycle: when async kicks in, how to start a job, how to poll, every response shape, and the errors you can hit.
When a job is created
NavyAI returns a job ID instead of an immediate result in two situations:
- Video models — Models like
veo-3.1,gemini-omni,sora-2,sora-2-pro,kling-2.6,cogvideox-flash,seedance-2.0,wan-2.7, andgrok-imagine-videodefault to async and almost always return a job. - `"sync": false` on an image request — Useful when the model is slow, your HTTP client times out, your platform (serverless, browser) cannot hold a long-lived connection, or you want a queue-style background workflow.
Image models default to sync: true and return the image inline. Video models default to async even without sync: false; you can force inline behavior with sync: true only if the upstream provider supports it.
Step 1 — Create the job with sync false
Send a normal image generation request and include "sync": false. The response contains a job ID — store it so you can poll later.
1curl -X POST https://api.navy/v1/images/generations \
2 -H "Authorization: Bearer sk-navy-YOUR_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "model": "veo-3.1",
6 "prompt": "A drone shot of a coastal city at sunrise, cinematic",
7 "sync": false,
8 "seconds": 6
9 }'Create-job response
A successful create returns the job in queued state. Persist id — you'll need it to poll.
1{
2 "id": "job_a1b2c3d4e5f6...",
3 "object": "job",
4 "created_at": 1716112000,
5 "status": "queued",
6 "model": "veo-3.1"
7}Step 2 — Poll the job
Call GET /v1/images/generations/:id repeatedly with the same API key until status becomes completed or failed. Poll every 3–5 seconds; polling does not count against your token quota.
1curl https://api.navy/v1/images/generations/job_a1b2c3d4e5f6 \
2 -H "Authorization: Bearer sk-navy-YOUR_KEY"Poll response shapes
While the job is running, the response only contains lifecycle fields:
1{
2 "id": "job_a1b2c3d4e5f6",
3 "object": "job",
4 "created_at": 1716112000,
5 "status": "in_progress",
6 "model": "veo-3.1"
7}Once status is completed, result is added. Its shape matches the normal /v1/images/generations response, so the same handler code works for both sync and async images and videos.
1{
2 "id": "job_a1b2c3d4e5f6",
3 "object": "job",
4 "created_at": 1716112000,
5 "completed_at": 1716112182,
6 "status": "completed",
7 "model": "veo-3.1",
8 "result": {
9 "created": 1716112182,
10 "data": [
11 { "url": "https://s3.api.navy/.../output.mp4" }
12 ]
13 }
14}If the job fails, error is added and result is omitted.
1{
2 "id": "job_a1b2c3d4e5f6",
3 "object": "job",
4 "created_at": 1716112000,
5 "status": "failed",
6 "model": "veo-3.1",
7 "error": {
8 "message": "Provider returned an unrecoverable error",
9 "code": "job_failed"
10 }
11}Status values
queued— Accepted and waiting for an available provider slotin_progress— A provider is actively generatingcompleted— Generation finished, output is inresultfailed— Generation failed, details inerror
Errors when polling
404 job_not_found— The job ID does not exist or has expired (jobs are retained for 10 minutes after creation).403 unauthorized_job_access— The job exists, but you are polling it with a different API key than the one that created it. Jobs are scoped to their creator.
Notes and best practices
- Persist the job ID immediately. If your client crashes or the user refreshes mid-generation, you can resume polling as long as the job has not expired.
- Use exponential or fixed-interval polling. 3–5 seconds is a sensible default. Video generation can take up to 10 minutes; image jobs typically finish in 10–60 seconds.
- Jobs expire 10 minutes after creation. Completed results are not stored long-term — copy
result.data[].urlto your own storage if you need it past that window. - Polling is free. It does not consume tokens or count against your daily quota.
- Same key only. A job can only be polled by the API key that created it. Server-side proxies must keep the same key for create and poll.
- No webhooks. NavyAI does not currently push job completion. Polling is the only completion signal.