Jobs
Track and manage async generation jobs
Jobs
Track and manage async generation jobs. Use jobs for long-running operations like video and music generation.
Overview
When you use ?async=true on any generation endpoint, the API returns a job ID instead of waiting for completion. You can then poll the Jobs API to check status and retrieve results.
List Jobs
Get a list of your generation jobs.
GET /jobs
GET /jobs?tool=image&pending=true&limit=10Required scope: usage
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
tool | string | - | Filter by tool type |
pending | boolean | false | Only return pending/processing jobs |
limit | number | 20 | Maximum results (1-100) |
Tool Types
image- Image generationimage_edit- Image editingvideo- Video generationmusic- Music generationtts- Text-to-speechstt- Speech-to-text
Response
{
"jobs": [
{
"id": "job_abc123",
"orgId": "org_xyz",
"userId": "api",
"tool": "image",
"status": "completed",
"progress": 100,
"inputParams": {"prompt": "A sunset over mountains"},
"outputData": {
"images": [
{"url": "https://fal.media/files/img123.png", "width": 1024, "height": 1024}
]
},
"estimatedCredits": 15,
"actualCredits": 15,
"createdAt": "2025-01-01T00:00:00Z",
"completedAt": "2025-01-01T00:00:05Z",
"model": "fal-ai/flux/dev",
"modelTier": "standard"
}
]
}Get Job Status
Get the status of a specific job.
GET /jobs/{jobId}
GET /jobs/{jobId}?poll=trueRequired scope: usage
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
poll | boolean | false | Long-poll for up to 30s until completion |
Use poll=true for efficient polling. The request will wait up to 30 seconds for the job to complete before returning, reducing the number of API calls needed.
Job Statuses
| Status | Description |
|---|---|
pending | Job is queued |
processing | Job is being processed |
completed | Job finished successfully |
failed | Job failed with an error |
cancelled | Job was cancelled |
Response
{
"id": "job_abc123",
"orgId": "org_xyz",
"userId": "api",
"tool": "video",
"status": "processing",
"progress": 45,
"inputParams": {
"prompt": "A timelapse of clouds",
"duration_seconds": 5
},
"outputData": null,
"estimatedCredits": 500,
"actualCredits": null,
"errorMessage": null,
"createdAt": "2025-01-01T00:00:00Z",
"startedAt": "2025-01-01T00:00:01Z",
"completedAt": null,
"model": "fal-ai/minimax/video-01",
"modelTier": "standard"
}Completed Job Response
{
"id": "job_abc123",
"status": "completed",
"progress": 100,
"outputData": {
"video": {
"url": "https://fal.media/files/video123.mp4",
"duration": 5.0
}
},
"actualCredits": 500,
"completedAt": "2025-01-01T00:01:30Z"
}Failed Job Response
{
"id": "job_abc123",
"status": "failed",
"progress": 0,
"errorMessage": "Content policy violation detected",
"completedAt": "2025-01-01T00:00:10Z"
}Cancel Job
Cancel a pending or processing job.
DELETE /jobs/{jobId}Required scope: usage
Response
{
"success": true
}Only jobs with status pending or processing can be cancelled. Completed or failed jobs cannot be cancelled. Cancelled jobs do not consume quota.
Examples
import requests
import time
API_KEY = "sk_your_api_key"
BASE_URL = "https://www.novakit.ai/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}
# Create an async job
response = requests.post(
f"{BASE_URL}/videos/generations?async=true",
headers=headers,
json={
"prompt": "A serene lake at sunrise",
"duration_seconds": 5
}
)
job_id = response.json()["id"]
print(f"Job created: {job_id}")
# Poll for completion with long-polling
while True:
status = requests.get(
f"{BASE_URL}/jobs/{job_id}?poll=true",
headers=headers
).json()
print(f"Status: {status['status']}, Progress: {status.get('progress', 0)}%")
if status["status"] == "completed":
print(f"Video URL: {status['outputData']['video']['url']}")
break
elif status["status"] == "failed":
print(f"Error: {status.get('errorMessage')}")
break
# With poll=true, we don't need to sleep as long
time.sleep(1)# List all pending jobs
curl "https://www.novakit.ai/api/v1/jobs?pending=true" \
-H "Authorization: Bearer sk_your_api_key"
# List recent video jobs
curl "https://www.novakit.ai/api/v1/jobs?tool=video&limit=5" \
-H "Authorization: Bearer sk_your_api_key"import requests
response = requests.delete(
"https://www.novakit.ai/api/v1/jobs/job_abc123",
headers={"Authorization": "Bearer sk_your_api_key"}
)
if response.json().get("success"):
print("Job cancelled successfully")
else:
print("Failed to cancel job")Polling Best Practices
Recommended polling strategy:
- Always use
poll=truefor efficient long-polling - Implement exponential backoff as a fallback
- Set reasonable timeouts (5-10 minutes for video/music)
Recommended Intervals
| Job Type | Initial Delay | Max Delay |
|---|---|---|
| Image | 2s | 10s |
| Image Edit | 3s | 15s |
| Video | 5s | 30s |
| Music | 5s | 30s |
| TTS | 2s | 10s |
| STT | 3s | 15s |
Exponential Backoff Example
import time
def poll_job(job_id, max_attempts=60):
base_delay = 2
max_delay = 30
for attempt in range(max_attempts):
# Try long-polling first
status = get_job_status(job_id, poll=True)
if status["status"] in ["completed", "failed", "cancelled"]:
return status
# Calculate delay with exponential backoff
delay = min(base_delay * (1.5 ** attempt), max_delay)
time.sleep(delay)
raise TimeoutError("Job polling timed out")
def get_job_status(job_id, poll=False):
import requests
url = f"https://www.novakit.ai/api/v1/jobs/{job_id}"
if poll:
url += "?poll=true"
return requests.get(
url,
headers={"Authorization": "Bearer sk_your_api_key"}
).json()Output Data Formats
Image Generation
{
"outputData": {
"images": [
{"url": "https://...", "width": 1024, "height": 1024}
]
}
}Video Generation
{
"outputData": {
"video": {
"url": "https://...",
"duration": 5.0
}
}
}Music Generation
{
"outputData": {
"audio": {
"url": "https://...",
"duration_seconds": 30
}
}
}Text-to-Speech
{
"outputData": {
"audio_url": "https://...",
"duration_seconds": 3.5
}
}Speech-to-Text
{
"outputData": {
"text": "Transcribed text...",
"segments": [...],
"duration": 60.0
}
}Error Handling
| Status | Error | Description |
|---|---|---|
| 404 | Job not found | Invalid job ID or job expired |
| 400 | Cannot cancel completed job | Job already finished |
| 500 | Job processing error | Internal error during generation |