Jobs

Monitor and retrieve results from image generation jobs.

GET/v1/jobs/{job_id}

Get the status and results of a generation job.

Headers

Authorization: Bearer YOUR_API_KEY

Path Parameters

ParameterTypeDescription
job_idstringThe job ID returned from the generate endpoint.

Example Request

curl "https://api.productai.photo/v1/jobs/job_abc123xyz" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response - Pending/Processing

{
  "job_id": "job_abc123xyz",
  "status": "processing",
  "progress": 45,
  "created_at": "2024-01-15T10:30:00Z",
  "started_at": "2024-01-15T10:30:05Z",
  "model": "nanobanana2",
  "num_images": 2
}

Response - Completed

{
  "job_id": "job_abc123xyz",
  "status": "completed",
  "progress": 100,
  "created_at": "2024-01-15T10:30:00Z",
  "started_at": "2024-01-15T10:30:05Z",
  "completed_at": "2024-01-15T10:30:35Z",
  "model": "nanobanana2",
  "num_images": 2,
  "images": [
    {
      "url": "https://cdn.productai.photo/generated/img_001.jpg",
      "width": 1024,
      "height": 1024
    },
    {
      "url": "https://cdn.productai.photo/generated/img_002.jpg",
      "width": 1024,
      "height": 1024
    }
  ],
  "tokens_used": 10
}

Response - Failed

{
  "job_id": "job_abc123xyz",
  "status": "failed",
  "created_at": "2024-01-15T10:30:00Z",
  "started_at": "2024-01-15T10:30:05Z",
  "failed_at": "2024-01-15T10:30:15Z",
  "error": {
    "code": "generation_failed",
    "message": "Unable to process the input image"
  }
}

Response Fields

FieldTypeDescription
job_idstringUnique job identifier.
statusstringOne of: pending, processing, completed, failed
progressintegerProgress percentage (0-100).
imagesarrayGenerated images (only present when completed).
images[].urlstringCDN URL of the generated image.
tokens_usedintegerNumber of credits consumed.
errorobjectError details (only present when failed).
GET/v1/jobs

List all jobs for the authenticated user.

Query Parameters

ParameterTypeDefaultDescription
limitinteger20Number of jobs to return. Max: 100.
offsetinteger0Number of jobs to skip.
statusstringallFilter by status.

Example Request

curl "https://api.productai.photo/v1/jobs?limit=10&status=completed" \
  -H "Authorization: Bearer YOUR_API_KEY"

Success Response (200 OK)

{
  "jobs": [
    {
      "job_id": "job_abc123xyz",
      "status": "completed",
      "model": "nanobanana2",
      "num_images": 2,
      "created_at": "2024-01-15T10:30:00Z",
      "completed_at": "2024-01-15T10:30:35Z"
    }
  ],
  "total": 156,
  "limit": 10,
  "offset": 0,
  "has_more": true
}

Polling Pattern

Poll the job status endpoint until the job completes. Recommended polling interval: 2-5 seconds.

Python

import requests
import time

def wait_for_job(job_id, api_key, timeout=120):
    url = f"https://api.productai.photo/v1/jobs/{job_id}"
    headers = {"Authorization": f"Bearer {api_key}"}
    
    start = time.time()
    while time.time() - start < timeout:
        response = requests.get(url, headers=headers)
        job = response.json()
        
        if job["status"] == "completed":
            return job["images"]
        elif job["status"] == "failed":
            raise Exception(job["error"]["message"])
        
        time.sleep(3)
    
    raise TimeoutError("Job did not complete in time")

# Usage
images = wait_for_job("job_abc123xyz", "YOUR_API_KEY")
for img in images:
    print(img["url"])

JavaScript

async function waitForJob(jobId, apiKey, timeout = 120000) {
  const url = `https://api.productai.photo/v1/jobs/${jobId}`;
  const start = Date.now();
  
  while (Date.now() - start < timeout) {
    const response = await fetch(url, {
      headers: { "Authorization": `Bearer ${apiKey}` }
    });
    const job = await response.json();
    
    if (job.status === "completed") return job.images;
    if (job.status === "failed") throw new Error(job.error.message);
    
    await new Promise(r => setTimeout(r, 3000));
  }
  throw new Error("Job timed out");
}

// Usage
const images = await waitForJob("job_abc123xyz", "YOUR_API_KEY");
images.forEach(img => console.log(img.url));

Webhooks

Instead of polling, you can provide a webhook_url when creating a job. We'll POST the completed job to your endpoint.

Webhook Payload

POST https://your-server.com/webhook
Content-Type: application/json
X-ProductAI-Signature: sha256=...

{
  "event": "job.completed",
  "job_id": "job_abc123xyz",
  "status": "completed",
  "images": [
    {"url": "https://cdn.productai.photo/generated/img_001.jpg", "width": 1024, "height": 1024}
  ],
  "tokens_used": 5,
  "completed_at": "2024-01-15T10:30:35Z"
}

Related