Generation event
Signed per the Standard Webhooks specification. Verify with an official Standard Webhooks library and the endpoint's whsec_ signing secret: it checks Base64(HMAC-SHA256(Base64-decoded secret, webhook-id + '.' + webhook-timestamp + '.' + raw_body)) against each v1 entry in webhook-signature in constant time and rejects timestamps more than five minutes from now. Deduplicate by webhook-id. Redelivery preserves the body and webhook-id and signs again with a new timestamp.
VizoAPI sends this request to the webhook endpoint you create in the console.
Request headers
| Field | Description |
|---|---|
| webhook-idstringRequired | Unique event ID, equal to event_id in the body. Unchanged on retries and redelivery; use it to deduplicate. |
| webhook-timestampstringRequired | Unix time in seconds when this attempt was sent. |
| webhook-signaturestringRequired | Space-delimited list of v1 signatures. Two are sent for 24 hours after a secret rotation; accept the request if any one matches. |
Request body
A JSON object. Fields that are not listed are rejected.
| Field | Description | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| billing_statusstringRequired | Pending awaits funding; unfunded closed without a hold; held means Credits are held for the task; settled charges verified delivery; released returns the hold; refunded reverses previously consumed generation Credits. pendingunfundedheldsettledreleasedrefunded | ||||||||||
| closed_statusstringRequired | Immutable customer closure. Unresolved means the resolution deadline passed without confirmed delivery. succeededfailedcanceledunresolved | ||||||||||
| created_atdate-timeRequired | |||||||||||
| delivery_statusstringRequired | Managed output delivery state, independent of supplier execution. pendingcopyingreadyfailed | ||||||||||
| error_codestringOptional | Stable accepted-task failure code, matching generation error.code. Omitted when no failure code applies. Funding or recovery refusals, provider capacity, content policy, media validity, draft expiry and other execution failures remain distinct. insufficient_balancebalance_negativebudget_exceededspending_blockedrecovery_reviewprovider_unavailableinput_moderatedoutput_moderatedinput_media_invalidinput_media_unreachabledraft_expiredinput_rejectedgeneration_failed | ||||||||||
| event_idstringRequired | |||||||||||
| execution_statusstringRequired | Supplier execution state: processing until execution ends. Succeeded can precede verified media delivery. processingsucceededfailedcanceledunresolved | ||||||||||
| freebooleanRequired | |||||||||||
| late_result_availablebooleanRequired | A result that arrived after closing is provided at no charge. | ||||||||||
| priceobjectRequired | Credits for this task: estimated (the estimate, which is the amount held; the charge follows actual usage and may differ slightly), reserved (held right now), charged (actual usage at the fixed rate, 0.000 until settlement) and refunded (returned by a refund). Fields of price
| ||||||||||
| resultobject, can be nullRequired | Delivered assets, once available. Fields of result
| ||||||||||
| task_idstringRequired | |||||||||||
| typestringRequired | generation.succeededgeneration.failedgeneration.canceledgeneration.unresolvedgeneration.refundedgeneration.late_result_available | ||||||||||
| versionintegerRequired |
Responses
2XX Delivery accepted
Request example
cURL
# Your endpoint receives a POST signed per Standard Webhooks. Replay one locally to test your handler:
curl -X POST "$YOUR_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-H "webhook-id: $EVENT_ID" \
-H "webhook-timestamp: $TIMESTAMP" \
-H "webhook-signature: v1,$SIGNATURE" \
--data-binary @event.jsonPython
# pip install standardwebhooks
from standardwebhooks import Webhook, WebhookVerificationError
wh = Webhook("whsec_...") # your endpoint's signing secret
def verify(headers, raw_body: bytes):
try:
return wh.verify(raw_body, headers) # returns the parsed event
except WebhookVerificationError:
return NoneNode.js
// npm install standardwebhooks
import { Webhook } from "standardwebhooks";
const wh = new Webhook(process.env.WEBHOOK_SECRET); // whsec_...
// rawBody is a Buffer of the request body as received, e.g. express.raw({ type: "application/json" }).
export function verify(headers, rawBody) {
try {
return wh.verify(rawBody, headers); // returns the parsed event
} catch {
return null;
}
}{
"billing_status": "held",
"closed_status": "succeeded",
"created_at": "2026-11-02T08:01:43Z",
"delivery_status": "pending",
"error_code": "insufficient_balance",
"event_id": "string",
"execution_status": "processing",
"free": false,
"late_result_available": false,
"price": {
"charged": "0.000",
"estimated": "157.000",
"refunded": "0.000",
"reserved": "157.000",
"unit": "credit"
},
"result": null,
"task_id": "gen_01JD8Z5QW3XR",
"type": "generation.succeeded",
"version": 1
}