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