|
Documentación
Reservar una demoPlataforma
PlataformaMCPCLIAPI
Flujos de trabajo
GuíasRegistro de cambios

Bienvenida

  • Descripción general
  • Autenticación
  • Errores y códigos de estado
  • Firmas de webhook

Localización

  • Descripción general
  • Crear trabajos
  • Bloquear claves no traducibles
  • Hacer seguimiento de un grupo de trabajos
  • Obtener un trabajo
  • Listar trabajos
  • Entrega del webhook
  • Progreso en tiempo real (WebSocket)

Pipeline

  • Descripción general
  • Edición con IA previa a la localización
  • Revisión humana
  • evaluación de IA (posedición)
  • Reescritura para que suene natural
  • Comprobación de retrotraducción
  • Configurar la canalización
  • Supervisar ejecuciones del pipeline

Aprovisionamiento

  • Descripción general
  • Crear un trabajo de aprovisionamiento
  • Tipos de fuente
  • Qué extrae la IA
  • Entrega de webhooks
  • Progreso en tiempo real (WebSocket)

Síncrono

  • Localize
  • Recognize

Gestión del motor

  • Sugerencias del motor

Entrega del webhook

Has creado un grupo de trabajos y has recibido un 202 en milisegundos. Las traducciones se están ejecutando ahora en segundo plano, un trabajo por idioma. Podrías consultar cada trabajo hasta que termine, pero seguramente no quieras montar un bucle de sondeo solo para saber que el alemán ya está listo. Lo que quieres es que tu servidor se entere en cuanto llegue cada idioma.

Para eso está el webhook. Cuando pasas un callbackUrl al crear trabajos, Lingo.dev envía el resultado por POST a esa URL en cuanto cada trabajo alcanza un estado terminal: un POST por idioma, en el mismo momento en que está listo. Un idioma que se traduce sin problemas llega como translation.completed con los datos. Un idioma que falla llega como translation.failed con el error. Se te notifica en cualquier caso, por idioma, sin tener que preguntar.

Esta página cubre las dos cargas útiles y cómo gestionarlas. La entrega va firmada y se reintenta; ese mecanismo se comparte con el aprovisionamiento y está documentado en la página de verificación de la firma del webhook, enlazada en cada punto en el que la necesites.

En esta página

  • Cómo funciona la entrega
  • La carga útil completada
  • La carga útil fallida
  • Cómo gestionar un webhook
  • Cuándo la entrega no es la herramienta adecuada

Cómo funciona la entrega#

Cada idioma de un grupo es un trabajo independiente. En el instante en que uno alcanza un estado terminal, su resultado se entrega por separado a tu callbackUrl: Lingo.dev no espera al idioma más lento ni agrupa todo el grupo en una sola llamada. Catorce idiomas de destino significan hasta catorce POST, que van llegando a medida que termina cada idioma, en el orden en que terminen.

Configura el destino por solicitud con callbackUrl cuando crees el grupo de trabajos, o define un valor predeterminado para la organización en el panel que heredarán todos los grupos. Un callbackUrl por solicitud anula el valor predeterminado de la organización para ese grupo.

Solo HTTPS

callbackUrl debe usar HTTPS. Una URL HTTP se rechaza con un 400 al crear el trabajo: el webhook va firmado, y enviar una carga útil firmada sobre texto sin cifrar va justo en contra de su propósito.

Por la red circulan dos formatos de carga útil, diferenciados por su campo type: translation.completed y translation.failed. Ambos indican el trabajo y el grupo al que pertenecen, así como el idioma que llevan, de modo que un único controlador pueda enrutar según type y actualizar el registro correcto.

Gestiona con elegancia los tipos de evento desconocidos

Hoy por hoy, por la red viajan translation.completed y translation.failed. Trata ese conjunto como abierto: ramifica según los tipos que conozcas e ignora el resto, para que un futuro tipo de evento no rompa un controlador ya desplegado.

La carga útil completada#

Cuando un trabajo termina correctamente, la carga útil incluye el data traducido: la misma estructura que obtendrías al recuperar el trabajo, pero enviada a ti en lugar de consultarla por sondeo. El data refleja la estructura que enviaste: cada cadena traducida, cada valor no textual (números, booleanos, null) preservado y la anidación intacta.

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" }
  }
}
CampoDescripción
typetranslation.completed
jobIdEl trabajo que terminó (prefijo ljb_)
groupIdEl grupo al que pertenece (prefijo ljg_)
sourceLocaleEl idioma de origen que enviaste
targetLocaleEl idioma al que se ha traducido esta carga útil
dataContenido traducido, con la misma estructura que el data que enviaste

Un trabajo que genera salida no es un fallo. Por eso, un trabajo que termina como completed_with_warnings (se generó salida, pero una fase opcional del pipeline se quedó por el camino) se entrega como translation.completed, con un data utilizable. El webhook te avisa de que el idioma está listo; las advertencias por paso que explican lo ocurrido están en el trabajo individual, que puedes recuperar por jobId cuando las necesites.

La carga útil fallida#

Un idioma puede fallar: un modelo puede agotar el tiempo de espera, o todos los modelos configurados pueden no estar disponibles. Cuando un trabajo alcanza failed, se te sigue notificando. El tipo de carga útil es translation.failed y contiene una cadena error en lugar de data:

json
{
  "type": "translation.failed",
  "jobId": "ljb_C3d4E5f6G7h8I9j0",
  "groupId": "ljg_A1b2C3d4E5f6G7h8",
  "sourceLocale": "en",
  "targetLocale": "ja",
  "error": "Model timeout after 30 seconds"
}
CampoDescripción
typetranslation.failed
jobIdEl trabajo que falló
groupIdEl grupo al que pertenece
sourceLocaleEl idioma de origen que enviaste
targetLocaleEl idioma que falló
errorDescripción del fallo en lenguaje natural

El fallo se limita a un solo idioma. Si enviaste de, fr y ja, un fallo de ja se entrega en su propio POST translation.failed, mientras que de y fr llegan como translation.completed; las traducciones al alemán y al francés se entregan igualmente. El estado de fallo parcial del grupo refleja esa combinación. Para recuperar el idioma fallido, envía un nuevo trabajo solo para ese idioma con una clave de idempotencia nueva.

Cómo gestionar un webhook#

La primera idea de una persona escéptica al leer esto es la correcta: mi controlador hace trabajo real —una escritura en base de datos, una invalidación de caché, una distribución a clientes conectados—, así que ¿no mantendrá la conexión abierta el tiempo suficiente como para que el webhook agote el tiempo de espera?

Sí. Así que no hagas que Lingo.dev espere. Devuelve primero un 200 y procesa después. Confirma la recepción de inmediato y haz el trabajo real una vez enviada la respuesta. Un controlador que responde rápido mantiene la entrega en buen estado; uno que se queda bloqueado por trabajo aguas abajo provoca un reintento innecesario.

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);
  }
});

El middleware verifyWebhook es la única pieza que esta página no define. Cada entrega va firmada siguiendo la especificación Standard Webhooks, así que no es un esquema que tengas que deducir por ingeniería inversa. Cómo verificarlo —y la cadencia de reintentos tras una respuesta no 2xx— está documentado por completo en verificación de la firma del webhook, compartida con el aprovisionamiento. Conecta ese middleware antes de confiar en una carga útil: un cuerpo no verificado es un cuerpo no autenticado.

Verifica antes de confiar en el cuerpo

Tu endpoint es una URL pública; cualquiera puede hacerle POST. Verifica la firma con el cuerpo en bruto de la solicitud antes de actuar sobre cualquier carga útil. El cómo —cabeceras, el HMAC, el secreto whsec_— está en la página de verificación de firma.

Cuándo la entrega no es la herramienta adecuada#

El webhook es una comodidad basada en push, no el sistema de referencia. Hay dos casos en los que conviene usar otra cosa, y ambos están a un clic.

Si tu endpoint estaba caído cuando se entregó un resultado, la plataforma reintenta el envío; y si se agotan todos los reintentos, el resultado no se pierde. Sigue siendo recuperable mediante jobId; el callbackStatus del trabajo registra si ese push acabó teniendo éxito. La propia cadencia de reintentos está en la página de firma y entrega. El webhook te ahorra un bucle de sondeo en el caso habitual; el registro del trabajo siempre está ahí debajo en el caso menos común.

Y si lo que quieres es progreso en tiempo real en una UI —un contador que pase de 3 de 14 a 4 de 14 a medida que van llegando idiomas, en lugar de una devolución de llamada por idioma a tu servidor—, entonces lo que necesitas es el WebSocket del grupo de trabajos, no el webhook.

Progreso en tiempo real (WebSocket)
Lleva el progreso del grupo a una UI con instantáneas del estado completo, en lugar de devoluciones de llamada por idioma a tu servidor.
Verificación de la firma del webhook
Verifica la firma, revisa las cabeceras y gestiona la cadencia de reintentos: compartido por todas las entregas de webhook.
Obtener un trabajo individual
Recupera cualquier resultado por jobId, incluidas las advertencias: la fuente de verdad detrás de cada entrega.

¿Te ha resultado útil esta página?

Max PrilutskiyMax Prilutskiy·Actualizado hace 12 días·7 min de lectura