Callback
Мы сами пришлём результат на ваш сервер, когда задача завершится, — без опроса recordInfo.
Как включить
Передайте callBackUrl в createTask. Когда задача станет success или fail, мы отправим на этот адрес POST с тем же JSON, что возвращает recordInfo.
POST <callBackUrl>
Content-Type: application/json
X-Signature: 3f1c9a…e07b # подпись, см. ниже
X-Timestamp: 1790621128
X-Task-Id: task_nano-banana-2_1790621023886ca4e4d
X-Event: task.success # или task.fail
X-Delivery-Attempt: 1
Что ответить
Любой ответ 2xx в течение 15 секунд. Иначе повторим: через 30 с, 2 мин и 10 мин (всего 4 попытки). Одно событие может прийти дважды — обрабатывайте по taskId.
Проверка подписи
Секрет (whsec_…) — в Кабинете → API-ключи. Подпись = HMAC-SHA256 от сырого тела запроса, в hex:
import hmac, hashlib
def valid(raw_body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
# Flask: valid(request.get_data(), request.headers["X-Signature"], "whsec_...")
import crypto from "node:crypto";
function valid(rawBody, signature, secret) {
const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
return signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
// Express: app.post("/callback", express.raw({ type: "application/json" }), (req, res) => {
// if (!valid(req.body, req.get("X-Signature"), process.env.WEBHOOK_SECRET)) return res.sendStatus(401);
// const task = JSON.parse(req.body).data; res.send("ok");
// });
<?php
$raw = file_get_contents('php://input');
$ok = hash_equals(hash_hmac('sha256', $raw, 'whsec_...'), $_SERVER['HTTP_X_SIGNATURE'] ?? '');
if (!$ok) { http_response_code(401); exit; }
$task = json_decode($raw, true)['data'];
Совет: отклоняйте запросы, где X-Timestamp старше 5 минут.
Ограничения
Адрес должен быть публичным http(s). Локальные и внутренние адреса (localhost, 10.x, 192.168.x и т. п.) отклоняются с кодом 422. Статус доставки виден в recordInfo.data.callback и в кабинете.