> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fanifyai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Receive status changes for Fanify Hub generations.

Webhooks avoid polling every generation. Fanify Hub sends `generation.running` when execution actually starts. It sends `generation.completed` for every final state: success, failure, or cancellation.

A generation canceled or failed while waiting in the queue does not emit `generation.running`.

## Register an endpoint

```bash theme={null}
curl https://fanifyai.com/api/v1/hub/webhooks \
  -H "Authorization: Bearer $FANIFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/fanify/webhook","events":["generation.running","generation.completed"]}'
```

The `201` response contains a `secret` only once. The URL must use HTTPS and be publicly reachable. An account can register up to **5 active endpoints**.

## Verify a delivery

Each request includes:

```text theme={null}
X-Fanify-Event: generation.completed
X-Fanify-Delivery: 0193f2c1-8f4a-7c31-9a02-6f5b1d0e77aa
X-Fanify-Signature: sha256=<lowercase hexadecimal signature>
```

The JSON body uses this envelope:

```json theme={null}
{
  "id": "0193f2c1-8f4a-7c31-9a02-6f5b1d0e77aa",
  "event": "generation.completed",
  "created_at": "2026-09-07T10:00:31Z",
  "data": {
    "id": "0192f3a4-8c1e-7b2a-9f10-2b6d4e0c9a11",
    "model": "nano-banana-2",
    "is_llm": false,
    "status": "succeeded",
    "input": { "prompt": "a cat", "resolution": "2K" },
    "estimated_cost": 0.040000,
    "billed_cost": 0.040000,
    "currency": "EUR",
    "outputs": [
      {
        "index": 0,
        "media_type": "image/png",
        "url": "https://fanifyai.com/api/v1/hub/files/8Jd2kQ7pR1sT4uV6wX9yZ0aB2cD4eF6gH8iJ0kL2mN4",
        "size": 812345,
        "expires_at": "2026-09-14T10:00:31Z"
      }
    ],
    "error": null,
    "missing": [],
    "created_at": "2026-09-07T10:00:00Z",
    "started_at": "2026-09-07T10:00:01Z",
    "completed_at": "2026-09-07T10:00:31Z"
  }
}
```

`data` contains the complete [generation object](/en/hub/generations). The envelope `id` is identical to the `X-Fanify-Delivery` header.

Compute `HMAC-SHA256(secret, raw body)` and compare the result with `X-Fanify-Signature` in constant time.

<Warning>
  Verify the signature against the raw bytes before parsing JSON. Re-serializing the body changes the signature.
</Warning>

A successful delivery can be repeated and ordering is not guaranteed. Deduplicate requests with `X-Fanify-Delivery`.

Fanify Hub retries after a `429` response, a `5xx` response, a timeout, or a connection failure. Other `4xx` responses immediately abandon the delivery. A retried delivery makes at most **8 attempts**, delayed by 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 24 hours, then 72 hours. The final failure is exposed as `last_error` by `GET /api/v1/hub/webhooks`.

`GET /api/v1/hub/webhooks` lists endpoints without their secrets. `DELETE /api/v1/hub/webhooks/{id}` revokes an endpoint.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.