Webhooks
Get the result pushed to you, signed with your secret.
How it works
Pass a callback_urlwhen you start any job, and we’ll POST the result to it the moment the job succeeds or fails. The body carries exactly what GET /jobs/{id} returns, under data, so the code you wrote for polling handles it as-is.
{ "data": { "charged_usd": 0.06, "error": null, "id": "…", "output_url": "https://…", "status": "succeeded" }, "delivery_id": "…", "event": "job.succeeded", "sent_at": "2026-09-26T09:31:07Z"}event is job.succeeded or job.failed. Failures are delivered too. Live sessions don’t send webhooks.
Headers on every delivery
| Field | Type | Required | Description |
|---|---|---|---|
KreatorsFactory-Signature | string | No | t=<unix time>,v1=<hex>. Check this before trusting the body. |
KreatorsFactory-Event | string | No | Same as event in the body, so you can route without parsing. |
KreatorsFactory-Delivery | string | No | Same as delivery_id. Stays the same across retries of one delivery. |
Check every delivery
An unchecked webhook URL is an open door
The hex is an HMAC-SHA256 of <t>.<raw body>, keyed with your signing secret. Hash the raw bytes you received: parsing and re-serialising the JSON changes the spacing and the digest won’t match.
# Webhooks come TO you, so there is nothing to call.# Pass callback_url when you start a job:curl -X POST https://api.kreatorsfactory.com/api/v1/face-swap-image \ -H "Authorization: Bearer $KREATORSFACTORY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"image_key":"api/images/…","face_key":"api/images/…","callback_url":"https://yourapp.com/webhooks/kreatorsfactory"}'Your signing secret is on the Webhooks page in the console. One secret covers your whole account and keeps working when you rotate an API key; rotate it separately if it is ever exposed.
Delivery and retries
| Field | Type | Required | Description |
|---|---|---|---|
Success | 2xx | No | Any 2xx counts as delivered. Reply first and do the work after. |
Timeout | 10 seconds | No | We wait ten seconds for your reply before counting it as a failure. |
Retries | 6 attempts | No | Anything else is retried, up to six attempts in total, then given up. |
Duplicates | delivery_id | No | The same on every retry. Key on it to be sure you act once. |
Webhooks don't replace the job endpoint
GET /jobs/{id} is the source of truth.