Skip to main content
Note for users in mainland China: Please use https://toapis.cn as the API endpoint (Base URL). Replace https://toapis.com with https://toapis.cn in the examples in this document.
ToAPIs sends one final event when an asynchronous image or video task completes or permanently fails. Delivery is at least once; deduplicate by event id.

Configure a Token

In the ToAPIs console, edit the Token, set an HTTPS default callback URL, generate a signing secret, enable Task Webhooks, save, and send a test event. The 32-byte secret is shown only when generated or rotated. If a task request omits callback_url, ToAPIs uses the Token default. A request-level URL may only change the path and query while keeping the same scheme, hostname, and port. If Webhooks are disabled or the Token lacks a default URL or secret, sending callback_url returns 400 webhook_not_configured.

Events

  • generation.completed
  • generation.failed
  • endpoint.test
Failed events are sent only after internal retries and refund or billing finalization have completed. Temporary failures do not emit an event. See the error reference for meanings and handling guidance. Webhook data.error does not guarantee the reason field available on some task queries.
Test deliveries use the same signed contract:
task_type is image or video. Results match the public task-status representation and never contain channel IDs, upstream task IDs or keys, internal credentials, or private task data.

Usage, billing, and query differences

Successful image and video events may contain data.usage, including billing quantities, available model-token details, and tool counts. Definitions match task queries; see Task usage fields. Video events may also contain data.generation; see Video task queries for Seedance metadata and compatibility usage. data.billing may contain status, credits, and cost_usd. Amounts are decimal strings, omitted for pending; refunded means the confirmed net charge is zero. An unconfirmed object is omitted and does not imply free usage. Webhooks and task queries use the same confirmation rules: when a charge is confirmed, including fixed-price tasks charged once at submission, both return settled with the actual amount. Whenever data.usage contains billing quantities such as charge_type, data.billing is also settled.

data.billing field values

Successful events are settled, or refunded when settlement returns the full reservation. Failed events are sent after the refund completes and are refunded. When the amount cannot be confirmed, the whole data.billing object is omitted.

data.usage field values

charge_type through input_images are billing quantities and are returned only together with data.billing.status=settled. Token details and tool counts are returned independently, as provided by the upstream model. Fields that are not returned are omitted, not filled with zeros. A Webhook is a snapshot taken when the event is created; a task query reads the latest confirmed state. Delivery does not wait for missing usage or amounts and retry rules do not change. Existing events are not backfilled; retries reuse the original event payload. The event envelope and api_version: "v1" remain unchanged. Webhooks use data.task_id, SUCCESS / FAILURE, and string progress "100%"; queries use id, lowercase statuses, and integer progress. Time fields share names and semantics with the public generation.task query, all in Unix seconds: data.created_at is the task submission time, data.finished_at is the finish time, and successful events also include data.completed_at and data.expires_at (result expiry, finish time plus 24 hours). Fields without a value are omitted. The former data.submitted_at has been replaced by data.created_at and is no longer sent. Top-level event created_at is the event creation time, not the task submission time. Media URLs can differ between the two because access policies differ.

Seedance video completion example

Examples illustrate the fields, not current model prices or a fixed billing mode. Use the fields and amounts returned for the actual task. Seedance completion events may also include fallback_url and fallback_last_frame_url in data.result.data[]. Prefer url and last_frame_url; use the corresponding fallback only if the original URL cannot be accessed. Missing fallback fields do not mean the task failed. Events retain their URL snapshot at creation: later changes to copies do not rewrite an existing event or its retry payload. See Video task status for field definitions and usage.

Headers and signature

The signed bytes are:
Compute HMAC-SHA256 with the Token secret and compare signatures in constant time. Reject a first delivery whose timestamp differs from local time by more than five minutes. Retries use the actual resend timestamp and keep the same event ID. During the 24 hours after secret rotation, ToAPIs sends signatures from both the current and previous secret; accept any valid v1 value.

Python

Node.js

Go

Persist the event ID before processing side effects so duplicate deliveries return 2xx without repeating work.

Delivery and security

Only 2xx is successful. ToAPIs does not follow redirects, times out after 10 seconds, and retries after approximately 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, and 24 hours. Use the task-status API if delivery is delayed or exhausted. Callback endpoints must use HTTPS and cannot contain userinfo or fragments. Private, loopback, link-local, reserved, or disallowed DNS/IP destinations and illegal ports are rejected. DNS and SSRF checks run again for every delivery. Result URLs may expire. Download and store required assets promptly. Real-avatar verification callbacks, payment Webhooks, and OAuth callbacks keep their existing contracts and are not task Webhooks. See Async task rate limits.