Skip to content

Async API

View markdown

The asynchronous polling-style API enables easy integration of long duration workflows, particularly video generation. Unlike the synchronous /v2/job endpoint which blocks until completion, the async API returns immediately with a job ID that you can poll to check progress and retrieve outputs.

Creates a new async job and returns immediately with the job metadata. The job will be processed in the background.

Request: Same as synchronous /v2/job - supports both application/json and multipart/form-data content types. The ?price=true query parameter is also supported (see Query Parameters).

Response: 201 Created with the full job JSON. The response includes the server-generated id field that you need for polling:

201 response
{
"type": "inference.veo.fast.txt2vid.v1",
"id": "c83d7027-240a-484a-aeba-96014e568711",
"created_at": "2025-01-01T00:00:14.885Z",
"updated_at": "2025-01-01T00:00:14.885Z",
"expires_at": "2025-01-01T00:01:14.885Z",
"state": {
"current": "processing"
},
"config": {
"prompt": "Running in the woods with a dog.",
"aspect_ratio": "16:9",
"resolution": "720p",
"generate_audio": true
}
}

GET /v2/job/async/:id/job.state.current Get Job State

Section titled “GET /v2/job/async/:id/job.state.current Get Job State”

Returns the current state of the job as plain text. Use this for efficient polling.

States:

  • processing - Job is currently being processed
  • processed - Job completed successfully
  • failed - Job encountered an error

GET /v2/job/async/:id/job.json Get Job Metadata

Section titled “GET /v2/job/async/:id/job.json Get Job Metadata”

Returns the full job JSON including configuration, timestamps, metrics, and error information (if failed).

GET /v2/job/async/:id/output List Output Files

Section titled “GET /v2/job/async/:id/output List Output Files”

Returns a list of output files produced by the job.

GET /v2/job/async/:id/output/:filename Download Output

Section titled “GET /v2/job/async/:id/output/:filename Download Output”

Downloads a specific output file (e.g., video.mp4).

DELETE /v2/job/async/:id Delete Job Resources

Section titled “DELETE /v2/job/async/:id Delete Job Resources”

Deletes the async job’s stored input files, output files, and job metadata. Use the same API token that created the job.

The job must be in the processed or failed state. A job that is still processing returns 409 Conflict; this endpoint does not cancel running jobs.

Response: 204 No Content with an empty body on success. The job’s metadata and outputs are no longer available after deletion. A missing, expired, or already deleted job returns 404 Not Found, as does a job created with a different token.

Download any outputs you want to keep before deleting, and delete before the job expires.

Terminal window
curl -sSf -X DELETE \
-H "Authorization: Bearer $PRODIA_TOKEN" \
"https://inference.prodia.com/v2/job/async/$job_id"

Async job results are stored temporarily and expire after 1 hour. After expiry, all GET endpoints for that job will return 404 Not Found. Clients should download outputs promptly after the job completes.

The expires_at field in the job result indicates the exact expiry time.

Code Description
201 Job created successfully (POST /v2/job/async)
200 Request successful (GET endpoints)
204 Job resources deleted successfully (DELETE)
400 Bad request - invalid job configuration or job type doesn’t support async
401 Unauthorized - missing or invalid authentication
404 Job not found, expired, deleted, or created with a different token
409 Job is still processing and cannot be deleted yet
429 Too many requests - exceeded async job limit or no capacity

Create the following main.py

main.py
import json
import os
import sys
import time
import requests
from requests.adapters import HTTPAdapter, Retry
prodia_token = os.getenv('PRODIA_TOKEN')
prodia_url = 'https://inference.prodia.com/v2/job/async'
session = requests.Session()
retries = Retry(allowed_methods=None, status_forcelist=Retry.RETRY_AFTER_STATUS_CODES)
session.mount('http://', HTTPAdapter(max_retries=retries))
session.mount('https://', HTTPAdapter(max_retries=retries))
session.headers.update({'Authorization': f"Bearer {prodia_token}"})
headers = {
'Accept': 'video/mp4',
}
job = json.loads('''{
"type": "inference.veo.fast.txt2vid.v1",
"config": {
"prompt": "Running in the woods with a dog.",
"aspect_ratio": "16:9",
"resolution": "720p",
"generate_audio": true
}
}''')
res = session.post(prodia_url, headers=headers, json=job)
print(f"Request ID: {res.headers['x-request-id']}")
print(f"Status: {res.status_code}")
if res.status_code != 201:
print(res.text)
sys.exit(1)
job = res.json()
job_id = job['id']
job_status = job['state']['current']
print(f"Job ID: {job_id}")
print(f"Job Status: {job_status}")
while job_status == 'processing':
time.sleep(1)
res = session.get(f"{prodia_url}/{job_id}/job.state.current")
if res.status_code != 200:
print(res.text)
sys.exit(1)
job_status = res.text
print(f"Job Status: {job_status}")
if job_status != 'processed':
res = session.get(f"{prodia_url}/{job_id}/job.json")
if res.status_code != 200:
print(res.text)
sys.exit(1)
print(res.json())
sys.exit(1)
res = session.get(f"{prodia_url}/{job_id}/output/video.mp4")
if res.status_code != 200:
print(res.text)
sys.exit(1)
with open('output.mp4', 'wb') as f:
f.write(res.content)
print('Output file: output.mp4')