Webhooks
Если не хочешь дёргать GET /tasks/{id} каждые несколько секунд — передай в params поле webhook_url, и мы сами пришлём результат на твой эндпоинт.
Как подключить
Просто добавь webhook_url к остальным параметрам генерации:
{ "params": { "model_name": "veo-3-fast", "prompt": "...", "duration": 8, "webhook_url": "https://your-app.com/api/nexus-callback" }}Когда задача станет completed или failed — мы сделаем POST на этот URL с телом:
{ "task_id": "550e8400-e29b-41d4-a716-446655440000", "status": "completed", "result": { "video_url": "https://..." }}или для провала:
{ "task_id": "550e8400-e29b-41d4-a716-446655440000", "status": "failed", "error": "Provider rejected prompt: contains restricted content"}Твой эндпоинт должен ответить 2xx (200, 201, 202, 204 — любой). Тело ответа мы не читаем.
Retry-логика
Если твой эндпоинт ответил не-2xx или вообще не ответил (таймаут 10 секунд) — мы попробуем ещё 2 раза, всего до 3 попыток, с интервалом нарастающим (несколько секунд, потом минуты).
После 3-х неудачных попыток webhook помечается как недоставленный, в админке остаётся запись. Сама задача в БД и result остаются доступны через GET /tasks/{id}.
Что слать в ответ
Не отвечай 200 OK сразу — сначала запиши task_id и status в свою БД, потом отвечай. Если ответишь до записи и упадёшь — узнаешь о задаче только через прямой запрос к нашему API.
Хороший паттерн:
@app.post("/api/nexus-callback")def callback(payload: dict): task_id = payload["task_id"] # Проверка дубля if db.tasks.find_one({"task_id": task_id, "processed": True}): return {"ok": True} # уже обработали — не падаем # Запись db.tasks.update_one( {"task_id": task_id}, {"$set": {"status": payload["status"], "result": payload.get("result"), "error": payload.get("error"), "processed": True}}, upsert=True, ) return {"ok": True}Безопасность
Альтернативно — проверяй, что task_id в payload действительно принадлежит твоему ключу: дёрни GET /tasks/{task_id} и сверь. Двойной запрос, но zero false positives.
Сравнение polling vs webhook
| Аспект | Polling | Webhook |
|---|---|---|
| Сложность реализации | Простая | Чуть сложнее (свой endpoint) |
| Задержка от готовности | До интервала polling’а (3-5с) | менее 1 секунды |
| Нагрузка на твой rate-limit | Каждый запрос считается | Нулевая |
| Работает за NAT/без публичного IP | Да | Нет (нужен публичный endpoint) |
Polling удобен для скриптов и пробных интеграций. Webhook — для production-нагрузок.