Retrieve Job Status
April 6, 2026
Table of contents
Retrieve the status and result of a video or image generation job by its job ID. Fetches fresh status directly from the Luma API.
Use this endpoint to poll for completion after submitting a video via POST /videos or images via POST /images.
https://api.useapi.net/v1/luma/jobs/
jobid
Request Headers
Authorization: Bearer {API token}
API tokenis required, see Setup useapi.net for details.
Path Parameters
jobidis required, the unique job identifier returned from POST /videos or POST /images.
Responses
-
Returns the job record with current status and details.
Pending/Processing (video):
{ "jobid": "j0326140530123456789v-u12345-email:[email protected]:a1b2c3d4-e5f6-7890-abcd-ef1234567890-bot:luma", "type": "video", "status": "pending", "created": "2026-03-26T14:05:30.123Z", "updated": null, "response": null, "credits": null }Completed (video):
{ "jobid": "j0326140530123456789v-u12345-email:[email protected]:a1b2c3d4-e5f6-7890-abcd-ef1234567890-bot:luma", "type": "video", "status": "completed", "created": "2026-03-26T14:05:30.123Z", "updated": "2026-03-26T14:08:45.678Z", "response": { "video": { "media_type": "video", "url": "https://storage.cdn-luma.com/...", "width": 1280, "height": 720, "duration": 5.04 }, "video_hdr_exr": null, "thumbnail": { "media_type": "image", "url": "https://storage.cdn-luma.com/.../thumbnail.jpg", "width": 1280, "height": 720 }, "last_frame": { "media_type": "image", "url": "https://storage.cdn-luma.com/.../last_frame.jpg", "width": 1280, "height": 720 } }, "credits": { "dm_usage": 20, "dm_relaxed_usage": null } }Note on HDR video: When
dynamic_rangeishdrorhdr_exr, theresponse.videoURL points to a HEVC (H.265) Main 10, BT.2020, HDR10 (PQ) MP4 file. This format is not playable in web browsers — use VLC, mpv, or a native HDR-capable player. Whenhdr_exr,response.video_hdr_exrcontains a ZIP with EXR frames.Completed (image):
{ "jobid": "j0326140530123456789i-u12345-email:[email protected]:c3d4e5f6-a7b8-9012-cdef-345678901234-bot:luma", "type": "image", "status": "completed", "created": "2026-03-26T14:05:30.123Z", "updated": "2026-03-26T14:06:15.234Z", "response": { "image": { "media_type": "image", "url": "https://storage.cdn-luma.com/...", "width": 1024, "height": 1024 } }, "credits": { "dm_usage": 5, "dm_relaxed_usage": null } }Failed:
{ "jobid": "j0326140530123456789v-u12345-email:[email protected]:a1b2c3d4-e5f6-7890-abcd-ef1234567890-bot:luma", "type": "video", "status": "failed", "created": "2026-03-26T14:05:30.123Z", "updated": "2026-03-26T14:08:00.000Z", "response": null, "credits": null } -
Invalid job ID format.
{ "error": "Invalid jobid" } -
Invalid API token.
{ "error": "Unauthorized" } -
Job does not belong to this user.
{ "error": "Job does not belong to this user" } -
Job not found. The generation ID may be invalid or the account may have been removed.
{ "error": "Job not found" } -
596 Session Error
Account session expired and could not be refreshed. Re-add the account using POST /accounts.
{ "error": "Luma account has an error. Please check your account configuration via GET /v1/luma/accounts or re-add the account via POST /v1/luma/accounts", "code": 596 }
Model
-
Video generation completed. Includes video URL and metadata.
{ jobid: string // Unique job identifier type: 'video' // Job type status: 'completed' created: string // ISO 8601 timestamp updated: string // ISO 8601 timestamp response: { video: { media_type: 'video' // Media type url: string // Direct video URL (MP4) width: number // Video width in pixels height: number // Video height in pixels duration: number // Video duration in seconds } | null video_hdr_exr: { // HDR EXR version (if dynamic_range is "hdr_exr") media_type: 'video' url: string width: number height: number duration: number } | null thumbnail: { media_type: 'image' // Media type url: string // Thumbnail image URL width: number height: number } | null last_frame: { media_type: 'image' // Media type url: string // Last frame image URL width: number height: number } | null } credits: { dm_usage: number | null // Credit cost dm_relaxed_usage?: number | null } } -
Image generation completed. Includes image URL and metadata.
{ jobid: string // Unique job identifier type: 'image' // Job type status: 'completed' created: string // ISO 8601 timestamp updated: string // ISO 8601 timestamp response: { image: { media_type: 'image' // Media type url: string // Direct image URL width: number // Image width in pixels height: number // Image height in pixels } | null } credits: { dm_usage: number | null // Credit cost dm_relaxed_usage?: number | null } } -
Generation failed. Includes error details.
{ jobid: string // Unique job identifier type: 'video' | 'image' status: 'failed' created: string // ISO 8601 timestamp updated: string // ISO 8601 timestamp response: null credits: null }
Webhook Callbacks
The replyUrl webhook callbacks from POST /videos and POST /images use the same response shape as this endpoint, with an additional replyRef field.
Video callback: single job result (same shape as above) + replyRef.
Image callback: wraps multiple job results in an images array:
{
jobid: string // Primary job ID
type: 'image'
status: 'completed' | 'failed' // 'completed' if any image in batch succeeded
images: Array</* same shape as single job result above */>
replyRef?: string
}
Error callback (on exception):
{
jobid?: string
status: 'failed'
error: string
replyRef?: string
}
Examples
-
# Get job status curl "https://api.useapi.net/v1/luma/jobs/j0326140530123456789v-u12345-email:[email protected]:a1b2c3d4-e5f6-7890-abcd-ef1234567890-bot:luma" \ -H "Authorization: Bearer YOUR_API_TOKEN" # Poll for completion (check every 10 seconds) while true; do RESULT=$(curl -s "https://api.useapi.net/v1/luma/jobs/$JOBID" \ -H "Authorization: Bearer YOUR_API_TOKEN") STATUS=$(echo "$RESULT" | jq -r '.status') echo "Status: $STATUS" if [[ "$STATUS" == "completed" ]]; then echo "$RESULT" | jq -r '.response.video.url' break fi if [[ "$STATUS" == "failed" ]]; then echo "$RESULT" | jq -r '.error' break fi sleep 10 done -
const apiToken = 'YOUR_API_TOKEN' const jobId = 'j0326140530123456789v-u12345-email:[email protected]:a1b2c3d4-e5f6-7890-abcd-ef1234567890-bot:luma' const getJobStatus = async (jobId) => { const response = await fetch(`https://api.useapi.net/v1/luma/jobs/${jobId}`, { headers: { 'Authorization': `Bearer ${apiToken}` } }) return await response.json() } // Poll until completion const waitForCompletion = async (jobId, intervalMs = 10000) => { while (true) { const job = await getJobStatus(jobId) console.log(`Status: ${job.status}`) if (job.status === 'completed') { if (job.type === 'video') { console.log('Video URL:', job.response.video.url) console.log('Dimensions:', `${job.response.video.width}x${job.response.video.height}`) } else { console.log('Image URL:', job.response.image.url) console.log('Dimensions:', `${job.response.image.width}x${job.response.image.height}`) } return job } if (job.status === 'failed') { console.error('Job failed:', job.error) throw new Error(job.error) } await new Promise(resolve => setTimeout(resolve, intervalMs)) } } const job = await waitForCompletion(jobId) -
import requests import time api_token = 'YOUR_API_TOKEN' job_id = 'j0326140530123456789v-u12345-email:[email protected]:a1b2c3d4-e5f6-7890-abcd-ef1234567890-bot:luma' def get_job_status(job_id: str) -> dict: response = requests.get( f'https://api.useapi.net/v1/luma/jobs/{job_id}', headers={'Authorization': f'Bearer {api_token}'} ) response.raise_for_status() return response.json() def wait_for_completion(job_id: str, interval_sec: int = 10) -> dict: while True: job = get_job_status(job_id) print(f"Status: {job['status']}") if job['status'] == 'completed': if job['type'] == 'video': print(f"Video URL: {job['response']['video']['url']}") print(f"Dimensions: {job['response']['video']['width']}x{job['response']['video']['height']}") # Download video video_response = requests.get(job['response']['video']['url']) with open('output.mp4', 'wb') as f: f.write(video_response.content) print('Video saved to output.mp4') else: print(f"Image URL: {job['response']['image']['url']}") return job if job['status'] == 'failed': raise Exception(f"Job failed: {job.get('error')}") time.sleep(interval_sec) job = wait_for_completion(job_id)