Lee la salida traducida de un idioma y el registro por etapa de cómo se generó.
Recurrirás a esto cuando ya tengas un jobId: se devuelve en el 202 de create, llega en un webhook o aparece en un grupo de trabajos. El endpoint del grupo te dice cuántos idiomas están listos. Este endpoint te dice qué produjo un único idioma y qué pasó por el camino.
GET /jobs/localization/:jobId¿Eres nuevo en la localización asíncrona? Empieza por la Descripción general.
Esa distinción es precisamente la razón de ser de esta página. La respuesta de un grupo es un marcador: recuentos y estado por trabajo, explicados en la página del grupo de trabajos. Un trabajo individual es el registro completo de un idioma: el outputData traducido, el status final, cualquier warnings y el rastro en steps[] de cada etapa que ejecutó la pipeline. Cuando estés listo para guardar el texto en alemán en tu base de datos, esta es la llamada que te lo entrega.
Autenticación#
Pasa tu clave de API en la cabecera X-API-Key. Las claves tienen alcance de organización y dan acceso a todos los motores de la organización. Consulta Authentication para más información.
Respuesta#
El campo outputData refleja la estructura del data de entrada, con cada valor de texto traducido y cada valor no textual (números, booleanos, null) conservado en su sitio. Las mismas claves, la misma anidación y el mismo orden en las matrices: solo cambian las cadenas.
{
"id": "ljb_A1b2C3d4E5f6G7h8",
"groupId": "ljg_A1b2C3d4E5f6G7h8",
"targetLocale": "de",
"status": "completed",
"outputData": {
"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" }
},
"errorMessage": null,
"warnings": [],
"callbackStatus": "delivered",
"createdAt": "2026-03-16T10:30:00.000Z",
"startedAt": "2026-03-16T10:30:01.000Z",
"completedAt": "2026-03-16T10:30:04.000Z",
"steps": [
{
"stepId": "localize",
"type": "action",
"status": "completed",
"errorMessage": null,
"externalRefType": null,
"externalRefId": null,
"externalRefUrl": null,
"createdAt": "2026-03-16T10:30:01.000Z",
"startedAt": "2026-03-16T10:30:01.000Z",
"completedAt": "2026-03-16T10:30:04.000Z"
}
]
}El bloque metadata de arriba ha permanecido intacto: Dr. Smith y beginner son hojas no textuales que el motor dejó tal cual. El outputData que recibes encaja con la estructura que enviaste, así que el mismo código que construyó la carga útil puede consumir la traducción.
| Campo | Descripción |
|---|---|
id | El ID de este trabajo (ljb_…). Es el valor que pasaste en la ruta. |
groupId | El grupo de trabajos padre (ljg_…) al que pertenece este trabajo. Pásalo a el endpoint del grupo de trabajos para ver de una vez todos los idiomas del mismo grupo. |
targetLocale | El idioma BCP-47 al que se tradujo este trabajo: existe un trabajo por cada idioma de destino. Este es el campo sobre el que debes bifurcar para enviar outputData a la columna o al archivo correctos. |
status | queued, processing, completed, completed_with_warnings o failed. |
outputData | Contenido traducido que mantiene la estructura de entrada. Está presente cuando status es completed o completed_with_warnings. |
errorMessage | Descripción del error. Está presente cuando status es failed; en caso contrario, null. |
warnings | Fallos no críticos en etapas de la pipeline. Cada entrada es { step, message }. Está vacío salvo que status sea completed_with_warnings. |
callbackStatus | Estado de entrega del webhook: pending, delivered o failed. null si no hay ninguna URL de callback configurada. |
createdAt | Cuándo se aceptó el trabajo (la marca de tiempo del 202 que lo creó). |
startedAt | Cuándo el motor empezó a traducir este idioma. Se establece cuando el trabajo sale de queued. |
completedAt | Cuándo el trabajo alcanzó un estado final. Se establece cuando status pasa a ser completed, completed_with_warnings o failed. |
steps | Registros de ejecución por etapa. Siempre contiene el paso localize, más una entrada por cada etapa opcional de pipeline habilitada. La estructura completa del registro está en Observe pipeline runs. |
outputData es null hasta que termine el trabajo
Mientras status sea queued o processing, outputData está vacío y errorMessage es null: todavía no hay nada que leer. Lee outputData solo después de que status llegue a completed o completed_with_warnings; si está en failed, lee errorMessage en su lugar. Primero bifurca según status y después toca la carga útil.
Valores de estado del trabajo#
Un trabajo pasa de queued a processing y luego a exactamente un estado final. Bifurca según status antes de leer nada más: te indica qué campos están rellenados.
| Estado | Significado | Qué leer |
|---|---|---|
queued | Aceptado, pero aún no ha empezado. | Nada todavía: haz polling o espera al webhook. |
processing | El motor está traduciendo este idioma. | Nada todavía. |
completed | La traducción ha terminado y todas las etapas habilitadas se han completado correctamente. | outputData. |
completed_with_warnings | La traducción ha terminado y outputData está completo, pero una etapa no crítica de la pipeline se quedó por el camino. | outputData y después warnings. |
failed | El trabajo no produjo ninguna traducción. | errorMessage. |
completed_with_warnings sigue entregando una traducción
completed_with_warnings no es un fallo leve. Recibes outputData completo: el paso principal de traducción se ha completado correctamente. Lo que cambia es que una etapa no crítica (por ejemplo, pre-edit o back-translation) no llegó a completarse, y cada fallo queda registrado en warnings como { step, message }. Trata la salida como utilizable; trata warnings como una señal de calidad que merece la pena mostrar a quien haga la revisión de las traducciones. Solo failed significa que no hay ninguna traducción que leer.
Gestiona valores de estado desconocidos
Los cinco valores de estado anteriores constituyen hoy el contrato. Las etapas de la pipeline evolucionan, así que trata status como un conjunto abierto: bifurca según los valores que conoces y envía cualquier valor inesperado a una ruta por defecto que lea outputData si está presente y, si no, lo registre. Un switch sin caso por defecto es la línea que se rompe el día en que aparece un estado nuevo.
La matriz steps#
steps[] es el rastro por etapa de un trabajo individual: un registro por cada etapa que ejecutó el motor, en orden. Todo trabajo incluye al menos el paso localize, porque la traducción principal siempre se ejecuta. Cada etapa opcional de pipeline que habilites añade un registro más. Así que un trabajo sin etapas extra muestra un único paso localize; un trabajo con pre-edit y back-translation habilitados muestra tres.
Esto es lo que hace que un trabajo sea auditable y no una caja negra. No tienes que dar por hecho que una etapa se ejecutó: puedes leer su registro: qué etapa (stepId), si completed, failed o fue skipped, cuánto costó (costUsd) y cuándo empezó y terminó. En las etapas de revisión humana, externalRef* apunta al registro externo.
"steps": [
{
"stepId": "preEdit",
"type": "action",
"status": "completed",
"errorMessage": null,
"costUsd": 0.0012,
"createdAt": "2026-03-16T10:30:01.000Z",
"completedAt": "2026-03-16T10:30:02.000Z"
},
{
"stepId": "localize",
"type": "action",
"status": "completed",
"errorMessage": null,
"costUsd": 0.0184,
"createdAt": "2026-03-16T10:30:02.000Z",
"completedAt": "2026-03-16T10:30:05.000Z"
}
]Que aquí aparezca una entrada failed no significa necesariamente que el trabajo falle. Cuando falla una etapa no crítica, su registro steps[] muestra failed, ese mismo fallo aparece en el campo superior warnings del trabajo y, aun así, el trabajo llega a completed_with_warnings con outputData completo. La estructura completa del registro —cada campo, cada stepId y la semántica de completed/failed/skipped— vive en una única página canónica: Observe pipeline runs. Esta página te muestra dónde encontrarlo dentro de un trabajo; esa página lo especifica.
Leer un trabajo completado#
Un consumidor típico bifurca según status, guarda outputData si hay éxito y registra errorMessage si hay fallo. La llamada lista para copiar y pegar de abajo devuelve la carga útil mostrada arriba.
const jobId = "ljb_A1b2C3d4E5f6G7h8";
const response = await fetch(`https://api.lingo.dev/jobs/localization/${jobId}`, {
headers: { "X-API-Key": process.env.LINGO_API_KEY },
});
const job = await response.json();
switch (job.status) {
case "completed":
case "completed_with_warnings":
// outputData is populated; warnings may carry non-critical stage failures
await db.content.update({
where: { id: job.outputData.id },
data: { [`content_${job.targetLocale}`]: job.outputData },
});
if (job.warnings.length) console.warn(job.targetLocale, job.warnings);
break;
case "failed":
console.error(`${job.targetLocale} failed: ${job.errorMessage}`);
break;
default:
// queued or processing - nothing to read yet; also catches future states
break;
}Polling o push
Este endpoint es una lectura en un momento concreto. En la mayoría de los trabajos, el motor tarda entre 2 y 8 segundos por idioma, así que, si haces polling, un intervalo de 2 segundos es un punto de partida razonable. Para evitar por completo el polling, registra un webhook y recupera el trabajo solo cuando te indique que el idioma ya está listo, o supervisa todo el grupo mediante WebSocket. En cualquier caso, un GET final aquí es la lectura canónica de outputData.
Cuando este endpoint devuelve un error —un jobId desconocido o una clave ausente— sigue el modelo estándar de error JSON. Consulta Errors and status codes.
