Skip to main content
Many media endpoints are asynchronous. A create request starts work and returns a public TokenLab task identity; your application polls until that task reaches a terminal status. Do not build customer workflows around upstream task URLs, routing IDs, or provider callback behavior.

Public Task Contract

Create responses can include:
FieldMeaningWhat to do
idPublic TokenLab task IDStore it with your own job record
task_idCompatibility alias for the same public task identityTreat it as equivalent to id
statusCurrent public task statusStart polling when it is not terminal
poll_urlPreferred status URLUse this first when present
modelModel requested or resolved by the endpointStore it for support and billing reconciliation
/v1/tasks/{id} is the canonical fixed status endpoint for public async media jobs. Media-specific status routes may exist for compatibility, but new integrations should prefer poll_url or /v1/tasks/{id}.
  1. Validate the user request and send the create call with an explicit model.
  2. Persist id / task_id, poll_url, endpoint, model, user ID, and your own job ID before returning control to the UI.
  3. Poll every 5-10s for long-running media tasks.
  4. Stop only when the task is completed or failed.
  5. On completed, read the media-specific result fields and store final URLs or metadata.
  6. On failed, store the public error and offer retry only as a new user-visible job.
{
  "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"
Expected public statuses are pending, processing, completed, and failed. Cancelled tasks are represented as failed with cancelled: true and cancellation_status: "cancelled" so older status handling keeps working.

Client Retry Rules

Network timeouts are the most common source of duplicate jobs. Use this rule:
Where timeout happensSafer behavior
Before your server receives a create responseCheck server logs for request_id; retry only if no task was created
After a create response was storedResume polling the stored task_id
During pollingRetry the status request with backoff
After terminal statusDo 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 And Settlement

Async jobs can reserve an estimated amount when the create request is accepted. Final settlement happens after terminal status. When available, task status responses can expose billing_transaction_id and the X-Billing-Transaction-ID header. For reconciliation, join these identifiers in your logs:
  • request_id from the create request.
  • task_id / id from the task.
  • billing_transaction_id when present.
  • Your own user ID, project ID, or job ID.

Cancellation

DELETE /v1/tasks/{id} is intentionally narrow. It currently supports queued Volcengine Seedance video tasks such as seedance-1.5-pro, seedance-2.0, and seedance-2.0-fast. Unsupported tasks return 400 unsupported_task_cancel. Tasks that are already running or terminal return 409 task_not_cancellable. Build cancellation UI as “request cancellation” rather than a guaranteed stop button.

Troubleshooting

SymptomLikely causeWhat to check
async_task_not_foundTask is unknown, expired, inaccessible to this API key, or not a public async taskConfirm API key ownership and the stored public task_id
Task never appears to finishClient keeps polling the wrong URL or stopped before terminal statusUse poll_url or /v1/tasks/{id} and inspect the latest status
Final media URL missingTask is not completed, or the upstream job completed without usable outputKeep polling until terminal, then handle missing output as failed
User sees duplicatesRetry path created a new task after timeout or refreshDeduplicate by your own job ID and stored task_id
Billing mismatchSettlement is async or client is comparing provider IDsCompare request_id, task_id, and billing_transaction_id

Support Packet

When contacting support, include request_id, task_id, billing_transaction_id when present, endpoint, model, timestamp, and a sanitized request shape. Do not include API keys, private media, signed URLs, or full prompts unless support asks for a redacted sample.

API Reference

TopicReference
Get Task StatusGet Task Status
Cancel TaskCancel Task
Image GenerationImage Generation
Video GenerationVideo Generation
Music GenerationMusic Generation
3D Generation3D Generation
Billing & PricingBilling & Pricing