Developers

Webhooks

Receive signed notifications when generations finish, Credits change or payments succeed, and verify every delivery.

Webhooks send an HTTPS POST to your server when something happens in your account, so you don't have to poll. Endpoints are managed under Account › Webhooks or with the REST API.

Events

EventSent whendata fields
generation.queuedA generation startsjob_id, creation_id, status, model_id
generation.completedA generation succeedsjob_id, creation_id, status, model_id
generation.failedA generation failsjob_id, creation_id, status, model_id, failure_code
credits.updatedYour Credit balance changesbalance, credit_sequence
billing.payment_succeededA payment succeedsinvoice_no, amount (minor units), currency, purchase_kind
subscription.updatedYour subscription changessubscription_no, status, plan_id, current_period_end
support_request.updatedA support request is updatedrequest_id, kind, status

Payloads carry identifiers and statuses only, never prompts, file URLs or contact details. Fetch the full resource with the API when you need it, for example GET /creations/{creationId} after generation.completed.

Every delivery has the same envelope:

{
  "event_id": "…",
  "type": "generation.completed",
  "created_at": "2026-11-13T10:24:05.000Z",
  "schema_version": 1,
  "data": {
    "job_id": "…",
    "creation_id": "…",
    "status": "succeeded",
    "model_id": "seedream-5-5"
  }
}

Add an endpoint

Register the URL

In Account › Webhooks, select Add endpoint, enter the Endpoint URL and choose the Events to send. The URL must be a public https address.

Save the signing secret

The endpoint's signing secret (whsec_…) is shown once, under Copy your signing secret. Store it with your server's secrets.

Verify the endpoint

A new endpoint is Not verified and receives nothing until you verify it. Select Verify now: we send a signed webhook.verification event whose data holds a challenge. Your endpoint must answer with status 2xx and the same value as JSON:

{ "challenge": "<the value you received>" }

The challenge expires after a few minutes. On success the endpoint shows Verified and starts receiving events.

Verify signatures

Deliveries follow the Standard Webhooks specification. Each request has three headers:

  • webhook-id: the event's event_id;
  • webhook-timestamp: when this attempt was signed, in Unix seconds;
  • webhook-signature: the signature of the raw body with your endpoint's secret.

Verify every delivery against the raw request body before trusting it. Any Standard Webhooks library does this, and also rejects old timestamps:

import { Webhook } from 'standardwebhooks';

const webhook = new Webhook(process.env.WEBHOOK_SECRET); // whsec_…

export async function handleWebhook(request: Request) {
  const body = await request.text();
  const event = webhook.verify(body, {
    'webhook-id': request.headers.get('webhook-id') ?? '',
    'webhook-timestamp': request.headers.get('webhook-timestamp') ?? '',
    'webhook-signature': request.headers.get('webhook-signature') ?? '',
  }); // throws if the signature is invalid

  if (event.type === 'webhook.verification') {
    return Response.json({ challenge: event.data.challenge });
  }
  // Process the event, then answer quickly.
  return new Response(null, { status: 204 });
}

Delivery behavior

  • Return status 2xx promptly: any 4xx/5xx status, redirect, connection timeout, or network error is recorded as a failed delivery. Defer long-running work to asynchronous background queues after sending the HTTP response.
  • Retry schedule: failed deliveries retry exponentially across predefined intervals (~5s, 5m, 30m, 2h, 5h, 10h). If the final attempt fails, delivery status transitions to Failed.
  • At-least-once delivery: events may be delivered more than once with identical event_id. Maintain an idempotency store of processed event_id records to discard duplicates.
  • Ordering: event arrival order is not strictly guaranteed. Rely on created_at timestamps, and for credits.updated, the monotonically increasing credit_sequence to ignore stale updates.

Monitor and fix deliveries

Each endpoint shows its Recent deliveries: Queued, Sending, Delivered, Retrying or Failed, with the attempt number, the last HTTP status and the next attempt time.

Failed deliveries are not sent again. After an outage, reconcile with the API, for example GET /generations or GET /credits/history.

From the endpoint you can also:

  • Edit events to change what it receives;
  • Rotate secret to replace the signing secret: deliveries are signed with the new secret from then on, so update your server first;
  • Delete the endpoint, which stops deliveries and removes its history.