AigenwayDocumentation

Webhooks (callbacks)

If you pass callback_url to POST /v1/generations, our worker will POST to that URL the moment the task reaches a terminal state (SUCCEEDED, FAILED, or CANCELLED).

How to enable

Pass callback_url in the request body (HTTPS required). The URL is stored on the ApiRequest and cannot be changed after task creation.

Request headers

POST <your callback_url>
Content-Type: application/json
User-Agent: aiagg-webhook/1.0
X-Aggregator-Event: generation.completed
X-Aggregator-Task-Id: <task_id>
X-Aggregator-Signature: sha256=<hex>

Payload body

{
  "event": "generation.completed",
  "task_id": "cmomwuy0m000qbr0371src20a",
  "status": "succeeded",
  "provider": "google_banana",
  "model": "gemini-3.1-flash-image-preview",
  "method": "image_edit",
  "charged_amount": "12000000",
  "currency": "USD",
  "result": {
    "type": "image",
    "url": "https://api.aigenway.com/v1/files/results/<userId>/<taskId>/image_0-...png",
    "mime_type": "image/png",
    "available_until": "2026-05-31T12:50:51.831Z",
    "files": [
      {
        "type": "image",
        "url": "https://api.aigenway.com/v1/files/results/<userId>/<taskId>/image_0-...png",
        "mime_type": "image/png",
        "available_until": "2026-05-31T12:50:51.831Z"
      }
    ]
  },
  "error": null
}

result is non-null only when status=succeeded; error is non-null only on failed/cancelled. charged_amount is in nano-USD (1 USD = 100,000,000 units).

X-Aggregator-Signature signature

The signature is HMAC-SHA256 of the raw (not re-serialised) request body using your API key's webhook secret. Compare using timing-safe equality.

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

function verify(rawBody: string, header: string, secret: string): boolean {
  // Header looks like: "sha256=<hex>"
  const expected = createHmac('sha256', secret).update(rawBody).digest('hex');
  const got = header.replace(/^sha256=/, '');
  if (got.length !== expected.length) return false;
  return timingSafeEqual(Buffer.from(got, 'hex'), Buffer.from(expected, 'hex'));
}
<?php
function verify(string $rawBody, string $header, string $secret): bool {
    $got = preg_replace('/^sha256=/', '', $header);
    $expected = hash_hmac('sha256', $rawBody, $secret);
    return hash_equals($expected, $got);
}

Retries

  • Any 2xx response counts as successful delivery; everything else is retried.
  • Up to 5 attempts with exponential backoff (BullMQ).
  • Response timeout is 10 seconds. If your server takes longer, return 200 immediately and process asynchronously.
  • Your handler must be idempotent: treat task_id as the primary key and ignore duplicates.

Debugging

docs.webhooksDebugBody