Documentation Navigation
Getting Started
API Reference
Resources
Jobs API
Poll async generation jobs, list job history, cancel pending jobs, and handle webhook callbacks.
webhook_url when submitting the job. GET /v1/jobs/:id
Check the status of an async generation job. Poll this endpoint until status is "succeeded" or "failed".
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Job ID returned when you submitted the generation (e.g. job_abc123). |
Response fields
| Field | Type | Description |
|---|---|---|
job_id | string | Job ID. |
status | string | "queued", "running", "succeeded", "partial", or "failed". |
model | string | Model key used for generation. |
modality | string | "video", "music", or "voice". |
result | object | Present only when succeeded/partial. Contains url, duration_sec, width, height, cost (USD float), cost_micro (integer microdollars), currency ("USD"). |
asset_id | string | null | Asset ID for the saved output (when succeeded). |
tags | array | Asset tags as { key, value } pairs (when succeeded). |
error | string | Sanitized error message (only when failed). |
created_at | string | ISO 8601 timestamp of job creation. |
completed_at | string | ISO 8601 timestamp of completion (when succeeded or failed). |
Status values
Status Meaning Cost charged? queuedJob is waiting to start. No runningJob is actively running. No succeededGeneration finished. result.url and result.cost_micro available. Yes partialGeneration partially completed. result available. Yes failedGeneration failed. error available. No
Code examples
curl
curl https://api.fairstack.ai/v1/jobs/job_abc123 \
-H "Authorization: Bearer $FAIRSTACK_API_KEY"
Python (polling)
from fairstack import FairStack
client = FairStack(api_key="fs_live_YOUR_KEY")
# Submit a video generation job
job = client.generate.video(
model="wan-2-1-t2v",
prompt="A cat walking on a beach at sunset"
)
# Option 1: Block until complete
result = job.wait()
print(result.url)
# Option 2: Poll manually
import time
while True:
status = client.jobs.get(job.id)
if status.status == "succeeded":
print(status.result.url)
break
elif status.status == "failed":
print(status.error)
break
time.sleep(2)
Node.js (polling)
import { FairStack } from "fairstack";
const client = new FairStack({ apiKey: "fs_live_YOUR_KEY" });
// Submit a video generation job
const job = await client.generate.video({
model: "wan-2-1-t2v",
prompt: "A cat walking on a beach at sunset",
});
// Option 1: Block until complete
const result = await job.wait();
console.log(result.url);
// Option 2: Poll manually
const poll = async (jobId: string) => {
while (true) {
const status = await client.jobs.get(jobId);
if (status.status === "succeeded") return status;
if (status.status === "failed") throw new Error(status.error);
await new Promise((r) => setTimeout(r, 2000));
}
};
Queued response
{
"job_id": "job_abc123",
"status": "queued",
"model": "wan-2-1-t2v",
"modality": "video",
"created_at": "2026-03-10T14:30:00Z"
}
Completed response
{
"job_id": "job_abc123",
"status": "succeeded",
"model": "wan-2-1-t2v",
"modality": "video",
"created_at": "2026-03-10T14:30:00Z",
"completed_at": "2026-03-10T14:30:42Z",
"result": {
"url": "https://media.fairstack.ai/video/.../output.mp4",
"duration_sec": 5,
"width": 1280,
"height": 720,
"cost": 0.048,
"cost_micro": 48000,
"currency": "USD"
},
"asset_id": "asset_def456",
"tags": []
}
Failed response
{
"job_id": "job_abc123",
"status": "failed",
"model": "wan-2-1-t2v",
"modality": "video",
"created_at": "2026-03-10T14:30:00Z",
"completed_at": "2026-03-10T14:30:15Z",
"error": "Content moderation filter triggered"
}
Cost units. result.cost_micro is an integer in microdollars; result.cost is the same value as a USD float; result.currency is "USD". The conversion is 1 credit = 1 cent = 10,000 microdollars (1 USD = 1,000,000 microdollars). So cost_micro: 30000 = $0.03 = 3 credits, and the example above (48000) = $0.048 = 4.8 credits.
GET /v1/jobs
List your recent generation jobs with optional filters.
Query parameters
Parameter Type Description statusstring Filter by status: "queued", "running", "succeeded", "failed". modalitystring Filter by modality: "video", "music", "voice". limitinteger Max results to return (1-100). Default: 20. cursorstring Pagination cursor from a previous response.
curl "https://api.fairstack.ai/v1/jobs?status=completed&limit=10" \
-H "Authorization: Bearer $FAIRSTACK_API_KEY"
{
"jobs": [
{ "job_id": "job_abc123", "status": "succeeded", "model": "wan-2-1-t2v", "modality": "video", "created_at": "..." },
{ "job_id": "job_def456", "status": "succeeded", "model": "suno-v4-5", "modality": "music", "created_at": "..." }
],
"has_more": true,
"cursor": "cursor_xyz"
}
POST /v1/jobs/:id/cancel
Cancel a queued or processing job. No charge for cancelled jobs.
curl -X POST https://api.fairstack.ai/v1/jobs/job_abc123/cancel \
-H "Authorization: Bearer $FAIRSTACK_API_KEY"
Returns the job object with status: "cancelled". Jobs that have already completed or failed cannot be cancelled.
Webhooks
Instead of polling, provide a webhook_url when submitting a generation. FairStack will POST the result to your URL when the job completes or fails.
// POST to your webhook_url when the generation completes:
{
"event": "generation.completed",
"data": {
"id": "gen_abc123",
"type": "video",
"status": "succeeded",
"model": "wan-2-1-t2v",
"output": { "url": "https://media.fairstack.ai/video/.../output.mp4", "width": 1280, "height": 720, "duration_sec": 5 },
"cost": { "cost_micro": 48000, "cost_usd": 0.048, "currency": "USD" },
"error": null,
"created_at": "2026-03-10T14:30:00Z",
"completed_at": "2026-03-10T14:30:42Z"
},
"created_at": "2026-03-10T14:30:42Z"
}
Webhook requests include an X-FairStack-Signature header for verification. Respond with a 2xx status. Failed deliveries are retried up to 3 times with exponential backoff.
Polling best practices
- Start polling 2-3 seconds after submission.
- Use a 2-5 second interval between polls.
- Set a timeout (e.g. 5 minutes) to avoid infinite polling.
- For production: prefer webhooks over polling to reduce API calls.
- The SDK
.wait() method handles polling with automatic backoff.
Next steps
- Video API -- submit video generation jobs
- Music API -- submit music generation jobs
- Error Handling -- retries and idempotency