Webhook events
Signed events we send to your endpoint, following Standard Webhooks.
Verify the signature on the raw body, answer 2xx within 10 seconds and handle each webhook-id once. See Webhooks.
Every event has these fields:
| Field | Description |
|---|---|
id | The event id, the same as the webhook-id header. |
type | The event type. Ignore types you don't know. |
environment | live or test, set by the key. |
created_at | When the event happened. |
data | The event's object. |
generation.succeeded
Sent when a generation succeeds. data is the generation, with a fresh output.url.
{
"id": "evt_4Kq9xT2mVb7Zp1Ls8Hc3Rw",
"type": "generation.succeeded",
"environment": "live",
"created_at": "2026-10-18T10:42:42.901Z",
"data": {
"id": "gen_4Kq9xT2mVb7Zp1Ls8Hc3Rw",
"object": "generation",
"environment": "live",
"status": "succeeded",
"created_at": "2026-10-18T10:42:07.512Z",
"started_at": "2026-10-18T10:42:09.031Z",
"completed_at": "2026-10-18T10:42:42.870Z",
"style_id": "pure-shot",
"instruction": null,
"aspect_ratio": "1:1",
"resolution": "4k",
"format": "jpeg",
"metadata": {
"dish_id": "d_456",
"vendor_id": "v_1029"
},
"credits_charged": 1,
"output": {
"url": "https://api.foodshot.ai/v1/files/gen_4Kq9xT2mVb7Zp1Ls8Hc3Rw/image.jpg?exp=1792406563&sig=8fwqDeaHcFOU4b68TzesgCYKN8NG02QP3yMTmmVM9Pc",
"url_expires_at": "2026-10-19T10:42:43.000Z",
"available_until": "2026-11-17T10:42:42.870Z",
"content_type": "image/jpeg",
"width": 4096,
"height": 4096,
"bytes": 8734516
},
"error": null,
"delivery": {
"status": "pending",
"attempts": 0,
"last_status_code": null,
"last_attempt_at": null
}
}
}generation.failed
Sent when a generation fails. data.error.code says why, and the credit is refunded.
data is the generation, with the same fields as Get generation.
{
"id": "evt_rYSdrrqV4cHBg9RlVFImuf",
"type": "generation.failed",
"environment": "live",
"created_at": "2026-10-18T10:40:31.208Z",
"data": {
"id": "gen_rYSdrrqV4cHBg9RlVFImuf",
"object": "generation",
"environment": "live",
"status": "failed",
"created_at": "2026-10-18T10:40:02.117Z",
"started_at": "2026-10-18T10:40:03.540Z",
"completed_at": "2026-10-18T10:40:31.176Z",
"style_id": "white-hero",
"instruction": null,
"aspect_ratio": "4:5",
"resolution": "4k",
"format": "jpeg",
"metadata": {
"dish_id": "d_457"
},
"credits_charged": 0,
"output": null,
"error": {
"code": "content_refused",
"message": "The photo or the instruction was refused by the content checks."
},
"delivery": {
"status": "pending",
"attempts": 0,
"last_status_code": null,
"last_attempt_at": null
}
}
}account.low_balance
Sent when a job takes your live credits below your low-balance threshold, by default 20% of your last plan grant. It is sent again only after credits have been added.
data holds your account id, its environment and your live credits, the same credits object as in Get account.
{
"id": "evt_oCtt6VsHVKyRjFPgaJIBwK",
"type": "account.low_balance",
"environment": "live",
"created_at": "2026-10-25T14:03:11.452Z",
"data": {
"object": "account",
"id": "acme-eats",
"environment": "live",
"credits": {
"available": 199,
"low_balance": true,
"low_balance_threshold": 200,
"lots": [
{
"id": "lot_9iF8VdFw6H377trtTdF4OH",
"kind": "plan",
"remaining": 199,
"granted": 1000,
"expires_at": "2026-11-01T00:00:00.000Z"
}
]
}
}
}webhook.test
A test event, sent when you press "Send test event" in the dashboard.
data holds a test message.
{
"id": "evt_iBbnS3Z2WrxSId7M6F20KD",
"type": "webhook.test",
"environment": "test",
"created_at": "2026-10-18T09:12:30.104Z",
"data": {
"object": "webhook_test",
"message": "This is a test event from FoodShot."
}
}