NovaKitv1.0

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=10

Required scope: usage

Query Parameters

ParameterTypeDefaultDescription
toolstring-Filter by tool type
pendingbooleanfalseOnly return pending/processing jobs
limitnumber20Maximum results (1-100)

Tool Types

  • image - Image generation
  • image_edit - Image editing
  • video - Video generation
  • music - Music generation
  • tts - Text-to-speech
  • stt - 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=true

Required scope: usage

Query Parameters

ParameterTypeDefaultDescription
pollbooleanfalseLong-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

StatusDescription
pendingJob is queued
processingJob is being processed
completedJob finished successfully
failedJob failed with an error
cancelledJob 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=true for efficient long-polling
  • Implement exponential backoff as a fallback
  • Set reasonable timeouts (5-10 minutes for video/music)
Job TypeInitial DelayMax Delay
Image2s10s
Image Edit3s15s
Video5s30s
Music5s30s
TTS2s10s
STT3s15s

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

StatusErrorDescription
404Job not foundInvalid job ID or job expired
400Cannot cancel completed jobJob already finished
500Job processing errorInternal error during generation

On this page