DocsOperateWebhooks
Operate

Receive generation webhooks

Register an HTTPS endpoint, verify signed generation events, and handle retries without duplicate work.

On this page

Webhooks notify your integration when a generation changes state. Register only the generation events you need and continue to treat the generation resource as the current source of truth.

Register a public HTTPS endpoint

Create an endpoint with an organization API key. The URL must use public HTTPS and must not resolve to a private or local address. The response returns a whsec_... signing secret once; store it securely.

Verify before processing

Verify EntireFeed-Signature against the exact raw request body before parsing JSON. The signed message is the timestamp, a period, and the raw body using HMAC-SHA256. Also record EntireFeed-Event-ID and ignore duplicate event IDs.

Return success promptly

Return any 2xx response after durable receipt. Failed deliveries are retried with the same event ID. Make your handler idempotent and fetch the generation when your workflow needs the latest state.

Only the generation events listed in the webhook reference are currently supported.

01

Register an endpoint

Signing secret returned oncewhsec_...
curl https://api.entirefeed.com/v1/webhooks/endpoints \
  -X POST \
  -H "Authorization: Bearer $ENTIREFEED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com/webhooks/entirefeed",
  "events": [
    "generation.succeeded",
    "generation.failed",
    "generation.manual_review"
  ]
}'
200 Endpoint and secret
{
  "id": "f419d0cf-5d8e-4b4c-82bb-6042b17e68f8",
  "url": "https://example.com/webhooks/entirefeed",
  "events": [
    "generation.succeeded",
    "generation.failed",
    "generation.manual_review"
  ],
  "secret": "whsec_store_this_value_once"
}
02

List or deactivate endpoints

curl https://api.entirefeed.com/v1/webhooks/endpoints \
  -X GET \
  -H "Authorization: Bearer $ENTIREFEED_API_KEY"
curl https://api.entirefeed.com/v1/webhooks/endpoints/f419d0cf-5d8e-4b4c-82bb-6042b17e68f8 \
  -X DELETE \
  -H "Authorization: Bearer $ENTIREFEED_API_KEY"
03

Verify the signature

import { createHmac, timingSafeEqual } from "node:crypto";

const parts = Object.fromEntries(
  signatureHeader.split(",").map((part) => part.split("=", 2)),
);
const timestamp = Number(parts.t);
const received = Buffer.from(parts.v1 ?? "", "hex");
const expected = Buffer.from(
  createHmac("sha256", process.env.ENTIREFEED_WEBHOOK_SECRET!)
    .update(Buffer.concat([Buffer.from(String(timestamp) + "."), rawBody]))
    .digest("hex"),
  "hex",
);

const fresh = Math.abs(Date.now() / 1000 - timestamp) <= 300;
const valid =
  fresh &&
  received.length === expected.length &&
  timingSafeEqual(received, expected);
04

Process deliveries idempotently

Signed event payload
{
  "id": "evt_0123456789abcdef0123456789abcdef",
  "type": "generation.succeeded",
  "created_at": "2026-07-12T08:31:14Z",
  "data": {
    "object": {
      "id": "gen_0123456789abcdef0123456789abcdef",
      "object": "generation",
      "status": "succeeded",
      "model": "seedance-2",
      "task": "video.create",
      "created_at": "2026-07-12T08:30:00Z",
      "completed_at": "2026-07-12T08:31:14Z",
      "output": {
        "assets": [
          {
            "id": "asset_0123456789abcdef0123456789abcdef",
            "type": "video",
            "url": "https://cdn.entirefeed.com/examples/product-reveal.mp4",
            "mime_type": "video/mp4",
            "expires_at": null
          }
        ]
      },
      "usage": {
        "amount_usd": "1.20",
        "line_items": [],
        "billing_status": "settled"
      },
      "error": null,
      "metadata": null
    }
  }
}

Store the event ID before returning 2xx. Repeated delivery of that ID must not repeat customer-side effects.

Delivery scheduleRequests time out after 10 seconds. Failed deliveries retry after 1m, 5m, 30m, 2h, 12h.