|
Документация
Заказать демоПлатформа
ПлатформаMCPCLIAPI
Процессы
РуководстваЖурнал изменений

Добро пожаловать

  • Обзор
  • Аутентификация
  • Ошибки и коды статуса
  • Подписи webhook

Локализация

  • Обзор
  • Создать задачи
  • Заблокировать непереводимые ключи
  • Отслеживание группы заданий
  • Получить одно задание
  • Список заданий
  • Доставка через вебхук
  • Прогресс в реальном времени (WebSocket)

Пайплайн

  • Обзор
  • AI-редактирование перед локализацией
  • Проверка человеком
  • AI-оценка (post-edit)
  • Перефразирование для естественного звучания
  • Проверка обратным переводом
  • Настройка пайплайна
  • Как отслеживать запуски пайплайна

Развёртывание

  • Обзор
  • Создать задание развёртывания
  • Типы источников
  • Что извлекает AI
  • Доставка webhook
  • Прогресс в реальном времени (WebSocket)

Синхронный

  • Локализация
  • Распознавание

Управление движком

  • Предложения для движка

Доставка через вебхук

Вы создали группу задач и за миллисекунды получили 202. Теперь переводы выполняются в фоне: по одной задаче на каждую локаль. Можно опрашивать каждую задачу, пока она не завершится, — но вряд ли вам захочется гонять цикл опроса только ради того, чтобы узнать, что немецкий уже готов. Гораздо лучше, чтобы сервер сам узнавал о готовности каждой локали в ту же секунду.

Именно для этого и нужен вебхук. Если при создании задач вы передаёте callbackUrl, Lingo отправляет результат POST-запросом на этот URL, как только задача достигает конечного состояния — один POST на каждую локаль, ровно в момент её готовности. Если локаль перевелась успешно, вы получите translation.completed с данными. Если локаль завершилась ошибкой, придёт translation.failed с ошибкой. В любом случае вы получите уведомление по каждому языку — без дополнительных запросов.

На этой странице разобраны оба payload и то, как с ними работать. Доставка подписывается и повторяется при сбоях — этот механизм общий с Развёртывание и подробно описан на странице проверка подписи вебхука, на которую мы будем ссылаться в нужных местах.

На этой странице

  • Как работает доставка
  • Payload успешного завершения
  • Payload ошибки
  • Как обрабатывать вебхук
  • Когда доставка — не лучший вариант

Как работает доставка#

Каждая локаль в группе — это отдельная задача. Как только одна из них доходит до конечного состояния, её результат отдельно отправляется на ваш callbackUrl — Lingo не ждёт самую медленную локаль и не собирает всю группу в один вызов. Четырнадцать целевых локалей — это до четырнадцати POST-запросов, которые приходят по мере готовности каждого языка и в том порядке, в каком они завершаются.

Указать адрес назначения для конкретного запроса можно через callbackUrl при создании группы задач, либо задать URL по умолчанию для всей организации в дашборде — тогда его будут наследовать все группы. Значение callbackUrl, переданное в конкретном запросе, переопределяет значение по умолчанию на уровне организации для этой группы.

Только HTTPS

callbackUrl должен использовать HTTPS. URL на HTTP будет отклонён с ошибкой 400 при создании задачи — вебхук подписывается, и передавать подписанный payload по открытому протоколу просто бессмысленно.

По сети идут payload двух типов, и различаются они по полю type: translation.completed и translation.failed. В обоих есть идентификаторы задачи и группы, к которым они относятся, а также локаль, которую они несут, поэтому один обработчик может маршрутизировать события по type и обновлять нужную запись.

Корректно обрабатывайте неизвестные типы событий

Сейчас по сети приходят translation.completed и translation.failed. Но считайте, что этот набор открыт: обрабатывайте известные типы и игнорируйте остальные, чтобы будущий тип события не сломал уже развёрнутый обработчик.

Payload успешного завершения#

Когда задача успешно завершается, payload содержит переведённый data — ту же структуру, что вы получили бы при получении задачи, только здесь результат приходит сам, а не через опрос. Поле data повторяет структуру отправленных вами данных: каждая строка переведена, каждое нестроковое значение (числа, булевы значения, null) сохранено, вся вложенность остаётся как есть.

json
{
  "type": "translation.completed",
  "jobId": "ljb_A1b2C3d4E5f6G7h8",
  "groupId": "ljg_A1b2C3d4E5f6G7h8",
  "sourceLocale": "en",
  "targetLocale": "de",
  "data": {
    "id": "course_101",
    "title": "Einführung in maschinelles Lernen",
    "steps": [
      { "heading": "Was ist ML?", "body": "Maschinelles Lernen ist ein Teilbereich der künstlichen Intelligenz." },
      { "heading": "Überwachtes Lernen", "body": "Trainieren eines Modells mit gelabelten Daten." }
    ],
    "metadata": { "author": "Dr. Smith", "difficulty": "beginner" }
  }
}
ПолеОписание
typetranslation.completed
jobIdЗавершившаяся задача (с префиксом ljb_)
groupIdГруппа, к которой она относится (с префиксом ljg_)
sourceLocaleИсходная локаль, которую вы отправили
targetLocaleЛокаль, на которую переведён этот payload
dataПереведённый контент, соответствующий структуре отправленного вами data

Если задача выдала результат, это не считается ошибкой — поэтому задача, завершившаяся как completed_with_warnings (результат получен, но необязательный этап пайплайн не выполнился), всё равно доставляется как translation.completed, с пригодным для использования data. Вебхук сообщает вам, что локаль готова; предупреждения по отдельным шагам, объясняющие, почему этап был пропущен, находятся в отдельной задаче, которую вы запрашиваете по jobId, когда они вам понадобятся.

Payload ошибки#

Локаль может завершиться ошибкой — например, модель может превысить тайм-аут или все настроенные модели окажутся недоступны. Когда задача доходит до состояния failed, вы всё равно получаете уведомление. В этом случае тип payload — translation.failed, и вместо data он содержит строку error:

json
{
  "type": "translation.failed",
  "jobId": "ljb_C3d4E5f6G7h8I9j0",
  "groupId": "ljg_A1b2C3d4E5f6G7h8",
  "sourceLocale": "en",
  "targetLocale": "ja",
  "error": "Model timeout after 30 seconds"
}
ПолеОписание
typetranslation.failed
jobIdЗадача, завершившаяся ошибкой
groupIdГруппа, к которой она относится
sourceLocaleИсходная локаль, которую вы отправили
targetLocaleЛокаль, завершившаяся ошибкой
errorПонятное человеку описание ошибки

Ошибка относится только к одной локали. Если вы отправили de, fr и ja, то ошибка ja придёт отдельным POST-запросом translation.failed, а de и fr придут как translation.completed — немецкий и французский переводы будут доставлены независимо от этого. Статус группы partial-failure status отражает такую смешанную картину. Чтобы восстановить неуспешную локаль, отправьте новую задачу только для неё с новым ключом идемпотентности.

Как обрабатывать вебхук#

Первая мысль скептически настроенного читателя здесь совершенно справедлива: мой обработчик делает реальную работу — пишет в базу данных, сбрасывает кэш, рассылает события подключённым клиентам, — разве это не продержит соединение открытым слишком долго и вебхук не упрётся в тайм-аут?

Именно так, поэтому не заставляйте Lingo ждать. Сначала верните 200, потом обрабатывайте. Сразу подтвердите получение и выполняйте основную работу уже после отправки ответа. Обработчик, который отвечает быстро, поддерживает стабильную доставку; обработчик, который блокируется на downstream-операциях, провоцирует лишний повтор.

javascript
app.post("/webhooks/translations", verifyWebhook, async (req, res) => {
  // Acknowledge first - one POST per locale, the moment it lands.
  res.status(200).send("ok");

  const { type, jobId, groupId, targetLocale, data } = req.body;

  if (type === "translation.completed") {
    await db.content.update({
      where: { groupId },
      data: { [`content_${targetLocale}`]: data },
    });

    // Advance your own progress model - your UI can poll this or receive it over SSE.
    await db.translationProgress.increment({
      where: { groupId },
      data: { completedLanguages: { increment: 1 } },
    });
  }

  if (type === "translation.failed") {
    console.error(`Translation failed: ${jobId} (${targetLocale})`, req.body.error);
  }
});

Middleware verifyWebhook — единственная часть, которую эта страница не определяет. Каждая доставка подписывается по спецификации Standard Webhooks, так что вам не придётся разбираться в какой-то самодельной схеме. Как именно проверять подпись — и по какому графику идут повторы после ответа не-2xx — полностью описано на странице проверка подписи вебхука, общей с Развёртывание. Подключите этот middleware до того, как начнёте доверять payload: непроверенное тело запроса — это неаутентифицированное тело.

Сначала проверяйте подпись — потом доверяйте телу запроса

Ваш endpoint — это публичный URL, и отправить на него POST-запрос может кто угодно. Проверяйте подпись по исходному телу запроса, прежде чем что-либо делать с payload. Что именно для этого нужно — заголовки, HMAC и секрет whsec_ — описано на странице проверка подписи.

Когда доставка — не лучший вариант#

Вебхук — это удобный push-механизм, а не источник истины. В двух случаях лучше использовать другой инструмент, и оба — в одном клике отсюда.

Если в момент доставки результата ваш endpoint был недоступен, платформа повторит попытку — и даже если все повторы будут исчерпаны, результат не потеряется. Он по-прежнему будет доступен по jobId; поле callbackStatus у задачи фиксирует, удалось ли в итоге доставить результат. Сам график повторов описан на странице подпись и доставка. В обычном сценарии вебхук избавляет вас от цикла опроса; в редком сценарии под ним всегда остаётся запись о задаче.

А если вам нужен живой прогресс в UI — счётчик, который меняется с 3 из 14 на 4 из 14 по мере готовности локалей, а не отдельный callback на сервер для каждой локали, — тогда вам нужен WebSocket группы задач, а не вебхук.

Живой прогресс (WebSocket)
Передавайте прогресс группы в UI потоком полных снимков состояния вместо отдельных callback-вызовов на сервер для каждой локали.
Проверка подписи вебхука
Проверьте подпись, разберите заголовки и настройте обработку повторов — это общий механизм для всех доставок через вебхук.
Получить отдельную задачу
Получайте любой результат по jobId, включая предупреждения, — это источник истины за каждой доставкой.

Эта страница была полезной?

Max PrilutskiyMax Prilutskiy·Обновлено 12 дней назад·6 минут чтения