Jobs and polling
Every generation creates a job. Poll it, long-poll until it finishes, or get notified with webhooks.
generation_context, input_data and output_data are receipts saved when the job ran, and keep their original field names.
Job lifecycle
A job is pending when accepted and processing once a worker picks it up, then ends completed with asset URLs or failed with an error.
pending --> processing --> completed
\--> failedList jobs
# List all jobs
curl https://api.masko.ai/v1/jobs \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Masko-API-Version: 2026-09-26"
# Filter by status and mascot
curl "https://api.masko.ai/v1/jobs?status=completed&mascot_id=MASCOT_ID" \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Masko-API-Version: 2026-09-26"
# Filter by type
curl "https://api.masko.ai/v1/jobs?type=animation" \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Masko-API-Version: 2026-09-26"Filters: status (pending, processing, completed, failed), mascot_id, and type (item_generation, image_generation, logo, animation, reverse, size_variant, size_variant_batch, export_animation, background_generation). Variant filters are in trace the variant used.
Get job detail
Completed jobs include output asset IDs and CDN URLs, and in file_sizes each file's size in bytes, under the same key as its link in urls (null when the file cannot be read).
curl https://api.masko.ai/v1/jobs/JOB_ID \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Masko-API-Version: 2026-09-26"
# Completed job response:
# {
# "data": {
# "id": "0818df65-d092-5901-a506-3b2e64fb88ef",
# "status": "completed",
# "type": "item_generation",
# "mascot_id": "c244e7b1-5655-5540-89a8-516b09bd4985",
# "cost_credits": 21,
# "created_at": "2026-03-28T10:00:00Z",
# "updated_at": "2026-03-28T10:01:32Z",
# "item_id": "e1a868c7-82b1-5d17-947b-ab4eeebd6fc3",
# "item_name": "Wave",
# "urls": {
# "image": "https://assets.masko.ai/c244e7b1-5655-5540-89a8-516b09bd4985/image.png",
# "webm": "https://assets.masko.ai/c244e7b1-5655-5540-89a8-516b09bd4985/video.webm"
# },
# "file_sizes": {
# "image": 412833,
# "webm": 1370412
# }
# }
# }Long polling
Add ?wait=true to hold the request open until the job finishes or timeout (default 120 seconds) passes. A timeout returns the current status and does not cancel the job.
# Wait up to 120 seconds for the job to complete
curl "https://api.masko.ai/v1/jobs/JOB_ID?wait=true&timeout=120" \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Masko-API-Version: 2026-09-26"
# Returns immediately if already completed.
# Returns the job object when it completes.
# Returns with current status if timeout is reached.When to poll and when to use webhooks
- Long-polling: simplest, for scripts, CLI tools and prototypes.
- Webhooks: for production. Your server is notified, with no open connections.
- Both: webhooks for background work, long-polling where a user waits for the result.
Media readiness
A job and its derived formats can finish at different times, and a returned CDN URL may still serve a placeholder. Check the required asset type and size_variants before playback. For a canvas use status.media.preview.ready; for a developer run, wait for its runtime readiness and version reference.
Trace the variant used
GET /v1/jobs/{id} returns variant_id and, when recorded, generation_context: the frozen context the job used (variant ID and name, engine hash, mascot prompt and style, resolved reference asset IDs and asset inputs). It never reflects the currently active variant, and internal execution details are never returned. Original-context jobs, cross-variant transitions and older untagged jobs have a null variant_id.
GET /v1/jobs?mascot_id=MASCOT_UUID&variant_id=VARIANT_UUIDlists work for one variant. Generated assets keep theirjob_id, so you can trace them back.from_variant_idandto_variant_idfilter transitions by role and accept named variant UUIDs. Original endpoints have null IDs, so find them by inspecting the mascot's jobs.
GET /v1/jobs?mascot_id=MASCOT_UUID&to_variant_id=VARIANT_UUIDFor transitions, generation_context.transition.before and .after each record asset_id, collection_id, variant_id, variant_name, context_source and the saved generation context. A reverse job swaps the roles without a new writer receipt. Older jobs without a recorded transition are not backfilled.
A video edit creates a video_edit job. For a transition edit, it keeps transition.before and .after and adds generation_context.transition_edit with the source video ID and requested edit. Repeated edits keep the endpoint identities.
Cursor followers create interactive_generation jobs; get their nine image URLs from GET /v1/mascots/{id}/cdn-export.
