Core Guides
Async jobs and polling
Create media tasks and wait for the finished result
Many media endpoints return a task instead of a finished file. Save the returned task ID and use poll_url until the status is completed or failed.
Async terminal task snapshots have a lifecycle separate from the 30-day request/response capture window. Generated image, video, or audio HTTP(S) result URLs may have their own 30-day media-copy window; check the response's media_retention fields for each item's current status and expires_at. A pending or failed copy is not guaranteed to remain available. See Data retention.
Fields to save
Create responses can include:
| Field | Meaning | What to do |
|---|---|---|
id | TokenLab task ID | Store it with your own job record |
task_id | Another name for the same task ID | Treat it as equivalent to id |
status | Current task status | Keep checking until it finishes or fails |
poll_url | Preferred status URL | Use this first when present |
model | Model used for the task | Store it with the task record |
Use poll_url when it is returned. If your client needs a fixed URL, use /v1/tasks/{id}.
Save the task and check its status
Save id or task_id as soon as the create request succeeds. Store poll_url, model, endpoint, and your own user or job ID with it. For long media jobs, checking every 5–10 seconds is usually enough.
Stop when the status becomes completed or failed. A completed task contains the media result; a failed task contains the error you can show or log. Retrying a failed generation creates a new task and may create a new charge.
{
"id": "ldtask_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"task_id": "ldtask_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"status": "pending",
"poll_url": "/v1/tasks/ldtask_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"model": "veo3.1"
}Polling Example
curl "https://api.tokenlab.sh/v1/tasks/ldtask_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
-H "Authorization: Bearer sk-your-api-key"Statuses are pending, processing, completed, and failed. A cancelled task uses failed together with cancelled: true and cancellation_status: "cancelled".
A successful status read returns HTTP 200 even when the task has failed. Use the task's status to decide whether generation succeeded. The error field retains its string or object shape. Failed tasks may also include error_details with status (the business error status), type, code, message, param, and retryable. For example, error_details.status: 400 with param: "size" means the request needs correction; it does not mean the status request itself failed. param is omitted when no specific field is known. When error_details.projection_version is 2, message is the final reason for the failure, usually the upstream service's own explanation, such as a parameter limit or a content policy decision. For a task that ran on an Official route, error_details.upstream also carries the upstream error as reported: message, plus code, param, and source (the upstream service name) when known. Keep branching on code and type; upstream.code values are defined by the upstream service and may change.
Errors that reject the create request before a task is accepted use the normal HTTP error status and structured error object. Repeating the same idempotent create request preserves that rejection. A failed status read does not change the task's terminal state.
Avoid duplicate tasks
Most duplicate generations come from retrying a create request after a timeout.
| Where timeout happens | Safer behavior |
|---|---|
| Before your server receives a create response | Check the request_id; retry only if no task was created |
| After a create response was stored | Resume polling the stored task_id |
| During polling | Retry the status request with backoff |
| After terminal status | Do not poll again unless the user explicitly refreshes the record |
Do not send a second create request just because the browser refreshed or a status poll failed.
Billing records
An async task may reserve its estimated cost when it is accepted. The final amount is recorded after the task finishes or fails. Status responses may include billing_transaction_id and the X-Billing-Transaction-ID header.
Keep these identifiers together:
request_idfrom the create request.task_id/idfrom the task.billing_transaction_idwhen present.- Your own user ID, project ID, or job ID.
Cancellation
DELETE /v1/tasks/{id} can cancel supported Seedance video tasks while they are still queued, including seedance-1.5-pro, seedance-2.0, and seedance-2.0-fast.
Unsupported tasks return 400 unsupported_task_cancel. A task that is already running or finished returns 409 task_not_cancellable. Cancellation is a request, not a guarantee that work already in progress will stop.
Troubleshooting
| Symptom | Likely cause | What to check |
|---|---|---|
404 async_task_not_found | The task has expired or is no longer available | Check the saved task_id and poll_url |
403 task_not_owned | Task ownership cannot be confirmed for the current workspace | Confirm the workspace or organization associated with the API key |
| Task never appears to finish | Client keeps polling the wrong URL or stopped before terminal status | Use poll_url or /v1/tasks/{id} and inspect the latest status |
| Final media URL missing | Task is not completed, or it finished without a usable file | Keep polling until it finishes, then treat a missing result as failed |
| User sees duplicates | Retry path created a new task after timeout or refresh | Deduplicate by your own job ID and stored task_id |
| Billing mismatch | Final billing is not recorded yet, or the wrong IDs are being compared | Compare request_id, task_id, and billing_transaction_id |
What to send support
Include request_id, task_id, billing_transaction_id when present, endpoint, model, time, and the names of fields you sent. Never send API keys, private media, signed URLs, or full prompts unless support specifically asks for a redacted example.
API Reference
| Topic | Reference |
|---|---|
| Get Task Status | Get Task Status |
| Cancel Task | Cancel Task |
| Image Generation | Image Generation |
| Video Generation | Video Generation |
| Music Generation | Music Generation |
| 3D Generation | 3D Generation |
| Billing & Pricing | Billing & Pricing |
Configure task notifications with the Webhook management API, authenticated with an mt-… Management Token. MCP full uses TOKENLAB_MANAGEMENT_TOKEN. Stop polling terminal tasks and on 401/403/404 or non-retryable errors.