# Webhook events

Source: https://docs.foodshot.ai/reference/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](https://docs.foodshot.ai/guides/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`.

```json
{
  "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](https://docs.foodshot.ai/reference/get-generation).

```json
{
  "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](https://docs.foodshot.ai/reference/get-account).

```json
{
  "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.

```json
{
  "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."
  }
}
```
