# Receive a billing settlement notification `POST task.billing_settled` Chenvoya sends task.billing_settled after task.completed is delivered or abandoned and settlement reaches settled or settled_with_receivable. This event has its own seven-day delivery window. No billing notification is created if settlement is still pending thirty days after completion. The final charge matches the task query; it is zero for settled failed or cancelled tasks. - Any 2xx response confirms receipt; other answers and timeouts are retried on schedule. - Signature, deduplication and retry rules are those of `task.completed`. - Sent after `task.completed` is delivered or abandoned and settlement is final. - A task still unsettled thirty days after completion gets no such event. ## Headers | Field | Type | Requirement | Description | | --- | --- | --- | --- | | `Chenvoya-Event-Id` | string | Required | A convenience copy of the event ID. This header is not covered by the signature. After verifying the signature, deduplicate using event_id inside the signed body. Format: uuid. | | `Chenvoya-Signature` | string | Required | The notification signature contains t and v1. Check the timestamp as described in Callbacks, calculate HMAC-SHA256 over the original body bytes and compare in constant time. | ## Request body · application/json · Required | Field | Type | Requirement | Description | | --- | --- | --- | --- | | `event_id` | string | Required | The unique event ID inside the signed body. Deduplicate on this field after successful signature verification. Format: uuid. | | `object` | string | Required | The notification object type, always event. Always: event. | | `type` | string | Required | Whether this notification reports task completion or billing settlement. `task.completed`: The task reached a final state; `task.billing_settled`: The task billing has been settled; | | `schema_version` | integer | Required | The notification format version, currently the integer 1. Always: 1. | | `created_at` | integer | Required | Event creation time in whole Unix seconds. Check it separately from each delivery attempt's signature timestamp. Range: ≥ 0. | | `data` | object | Required | The customer task snapshot saved when this event was created. | | `data.task_id` | string | Required | The platform Task ID belonging to your team. Length: 4–128. Characters: A–Z a–z 0–9 _ -. | | `data.request_id` | string | Required | The Request ID associated with task creation. Length: 4–128. Characters: A–Z a–z 0–9 _ -. | | `data.billing_correlation_id` | string | Required | The billing correlation ID associated with task creation. Length: 4–128. Characters: A–Z a–z 0–9 _ -. | | `data.model` | string | Required | The public model ID used for this task. `dreamina-seedance-2-0-260128`: Seedance 2.0; `dreamina-seedance-2-0-fast-260128`: Seedance 2.0 Fast; `dreamina-seedance-2-0-mini-260615`: Seedance 2.0 Mini; | | `data.status` | string | Required | The final task status: succeeded, failed or cancelled. `succeeded`: Succeeded; `failed`: Failed; `cancelled`: Cancelled; | | `data.delivery_status` | string | Required | Result delivery status when the event snapshot was saved. `pending`: Not yet delivered; `materializing`: Preparing the download; `available`: Ready to download; `output_unavailable`: Result unavailable; | | `data.error` | object | Required, nullable | The task error object, or null when there is no error. | | `data.error.code` | string | Required | A code your application can use to handle the error. `no_common_asset_route`: Assets temporarily unavailable; `asset_not_ready`: A referenced asset is still processing; `asset_review_timeout`: Asset review timed out; `route_misconfigured`: Service configuration error; `route_temporarily_unavailable`: Temporarily unavailable; `generation_expired`: Generation expired; `generation_failed`: Generation failed; `input_fetch_failed`: An input could not be downloaded from its URL; `input_url_not_allowed`: An input URL is not allowed; `input_too_large`: An input exceeds its size limit; `input_unsupported`: An input format, dimensions or duration is unsupported; `input_rejected`: An input did not pass content review; `input_preparation_failed`: The inputs could not be prepared in time; `input_duration_exceeded`: The combined input duration exceeds the model limit; | | `data.error.message` | string | Required | A readable explanation of the error. Length: 1–1024. | | `data.error.details` | object | Optional | Optional fields with more information about the error. | | `data.error.details.content_index` | integer | Optional | Zero-based position of the failed input in the original content array, including text items. Range: 0–50. | | `data.settlement_status` | string | Required | The billing settlement status when the event snapshot was saved. `reserved`: Reserved; `pending`: Pending; `reconciliation_required`: Under review; `settled`: Settled; `settled_with_receivable`: Settled - amount due; | | `data.final_actual_cost` | string | Required, nullable | The final charge as a USD string with six decimal places, or null until determined. Format: 6 decimal places. | ## Your response The notification was received. Any 2xx response confirms delivery; other responses and timeouts cause scheduled retries. ### Retry schedule - after 10 seconds - after 1 minute - after 5 minutes - then every hour - for up to 7 days ### Verify the signature The full signature, deduplication and age rules are on [Verify callback signatures](./api-docs-en-callbacks-verify.md). ```python import base64 import hashlib import hmac import time def verify(signing_secret, header, body): fields = {} for item in header.split(","): name, _, value = item.strip().partition("=") fields[name] = value t, v1 = fields.get("t", ""), fields.get("v1", "") if not t.isdigit() or abs(time.time() - int(t)) > 300: return False key = base64.urlsafe_b64decode(signing_secret + "=" * (-len(signing_secret) % 4)) signed = b"chenvoya.v1." + t.encode() + b"." + body expected = hmac.new(key, signed, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, v1) ``` ## Related guides - [Receive callbacks](./api-docs-en-callbacks.md) - [How billing works](./api-docs-en-billing.md) ## Example body ```json { "event_id": "7f9c2ba4-e88f-4d2b-9a2f-0c3e5b8d1a64", "object": "event", "type": "task.billing_settled", "schema_version": 1, "created_at": 1793167400, "data": { "task_id": "task_32ae2a5177b310d3bc1ec83a98f63889", "request_id": "req_6acd96894df9798feb0ddb21e5a52d70", "billing_correlation_id": "billcorr_2f6c57065a4404b27fb9b6b24ea9a0d0", "model": "dreamina-seedance-2-0-260128", "status": "succeeded", "delivery_status": "available", "error": null, "settlement_status": "settled", "final_actual_cost": "0.361564" } } ```