Leia o resultado traduzido de um idioma e o registo por etapa de como foi produzido.
Vai precisar disto assim que tiver um jobId — devolvido no 202 da criação, enviado num webhook ou listado num grupo de trabalhos. O endpoint do grupo diz-lhe quantos idiomas já estão concluídos. Este endpoint diz-lhe o que um único idioma produziu e o que aconteceu pelo caminho.
GET /jobs/localization/:jobIdÉ a sua primeira vez com localização assíncrona? Comece pela Visão geral.
Essa distinção é precisamente o objetivo desta página. A resposta de grupo é um quadro de resultados — contagens e estado por trabalho, explicados na página do grupo de trabalhos. Um único trabalho é o registo completo de um idioma: o outputData traduzido, o status terminal, quaisquer warnings e um rasto em steps[] de todas as etapas que o pipeline executou. Quando estiver pronto para gravar o texto em alemão na sua base de dados, esta é a chamada que lho entrega.
Autenticação#
Passe a sua chave de API no cabeçalho X-API-Key. As chaves estão associadas à organização e dão acesso a todos os motores dessa organização. Consulte Authentication para mais detalhes.
Resposta#
O campo outputData espelha a estrutura do data de entrada, com cada valor de string traduzido e cada valor não textual (números, booleanos, null) preservado no respetivo lugar. Mesmas chaves, mesmo aninhamento, mesma ordem no array — só mudam as strings.
{
"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"
}
]
}O bloco metadata acima manteve-se intacto — Dr. Smith e beginner são folhas não textuais que o motor deixou como estavam. O outputData que recebe de volta mantém a forma do que enviou, por isso o mesmo código que construiu a payload pode consumir a tradução.
| Campo | Descrição |
|---|---|
id | O ID deste trabalho (ljb_…). O valor que passou no caminho. |
groupId | O grupo de trabalhos principal (ljg_…) a que este trabalho pertence. Passe-o ao endpoint do grupo de trabalhos para ver todos os idiomas associados de uma só vez. |
targetLocale | O idioma BCP-47 para o qual este trabalho traduziu — existe um trabalho por idioma de destino. É este o campo em que faz a ramificação para encaminhar outputData para a coluna ou ficheiro certo. |
status | queued, processing, completed, completed_with_warnings ou failed. |
outputData | Conteúdo traduzido que corresponde à estrutura de entrada. Presente quando status é completed ou completed_with_warnings. |
errorMessage | Descrição do erro. Presente quando status é failed; caso contrário, null. |
warnings | Falhas não críticas em etapas do pipeline. Cada entrada é { step, message }. Vazio, a menos que status seja completed_with_warnings. |
callbackStatus | Estado da entrega do webhook: pending, delivered ou failed. null se não estiver configurado nenhum URL de callback. |
createdAt | Momento em que o trabalho foi aceite (o carimbo temporal do 202 que o criou). |
startedAt | Momento em que o motor começou a traduzir este idioma. Fica definido quando o trabalho sai de queued. |
completedAt | Momento em que o trabalho atingiu um estado terminal. Fica definido quando status é completed, completed_with_warnings ou failed. |
steps | Registos de execução por etapa. Contém sempre a etapa localize, mais uma entrada por cada etapa opcional do pipeline ativada. A estrutura completa do registo está em Observe pipeline runs. |
outputData é null até o trabalho terminar
Enquanto status for queued ou processing, outputData está vazio e errorMessage é null — ainda não há nada para ler. Leia outputData apenas depois de status chegar a completed ou completed_with_warnings; se for failed, leia antes errorMessage. Faça primeiro a ramificação sobre status e só depois toque na payload.
Valores de estado do trabalho#
Um trabalho passa de queued para processing e depois para exatamente um estado terminal. Faça a ramificação sobre status antes de ler qualquer outra coisa — é isso que lhe diz que campos estão preenchidos.
| Estado | Significado | O que ler |
|---|---|---|
queued | Aceite, ainda não iniciado. | Ainda nada — faça polling ou espere pelo webhook. |
processing | O motor está a traduzir este idioma. | Ainda nada. |
completed | A tradução terminou e todas as etapas ativadas foram concluídas com sucesso. | outputData. |
completed_with_warnings | A tradução terminou e outputData está completo, mas uma etapa não crítica do pipeline falhou. | outputData, depois warnings. |
failed | O trabalho não produziu tradução. | errorMessage. |
completed_with_warnings continua a entregar uma tradução
completed_with_warnings não é uma falha ligeira. Recebe o outputData completo — a etapa principal de tradução foi concluída com sucesso. O que mudou foi que uma etapa não crítica (por exemplo, pre-edit ou back-translation) não ficou concluída, e cada falha é registada em warnings como { step, message }. Trate o resultado como utilizável; trate warnings como um sinal de qualidade que vale a pena mostrar a quem faz a revisão das traduções. Só failed significa que não há tradução para ler.
Lidar com valores de estado desconhecidos
Os cinco valores de estado acima são hoje o contrato. As etapas do pipeline evoluem, por isso trate status como um conjunto aberto: faça a ramificação sobre os valores que conhece e encaminhe qualquer valor inesperado para um comportamento por defeito que leia outputData, se estiver presente, e registe caso contrário. Um switch sem fallback é a linha que falha no dia em que um novo estado entra em produção.
O array steps#
steps[] é o rasto por etapa por trás de um único trabalho — um registo por cada etapa que o motor executou, por ordem. Todos os trabalhos incluem pelo menos a etapa localize, porque a tradução principal é sempre executada. Cada etapa opcional do pipeline que ativar acrescenta mais um registo. Assim, um trabalho sem etapas extra mostra uma única etapa localize; um trabalho com pre-edit e back-translation ativados mostra três.
É isto que torna um trabalho auditável, em vez de uma caixa negra. Não tem de assumir que uma etapa foi executada — pode ler o respetivo registo: que etapa foi (stepId), se completed, failed ou foi skipped, quanto custou (costUsd) e quando começou e terminou. Para etapas de revisão humana, externalRef* aponta para o registo 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"
}
]Uma entrada failed aqui não significa necessariamente que o trabalho falhou. Quando uma etapa não crítica falha, o respetivo registo steps[] surge como failed, a mesma falha aparece no warnings de topo do trabalho, e o trabalho continua a chegar a completed_with_warnings com outputData completo. A estrutura completa do registo — cada campo, cada stepId, e a semântica de completed/failed/skipped — está numa única página canónica: Observe pipeline runs. Esta página mostra-lhe onde a encontrar num trabalho; essa página define-a.
Ler um trabalho concluído#
Um consumidor típico faz a ramificação sobre status, grava outputData em caso de sucesso e regista errorMessage em caso de falha. A chamada pronta a copiar abaixo devolve a payload mostrada acima.
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 vs push
Este endpoint é uma leitura num dado momento. Para a maioria dos trabalhos, o motor demora 2–8 segundos por idioma, por isso, se fizer polling, um intervalo de 2 segundos é um ponto de partida razoável. Para evitar totalmente o polling, registe um webhook e obtenha o trabalho apenas quando este indicar que o idioma está concluído, ou acompanhe o grupo inteiro através de WebSocket. De qualquer forma, um GET final aqui é a leitura canónica de outputData.
Quando este endpoint devolve um erro — um jobId desconhecido, uma chave em falta — segue o modelo padrão de erro JSON. Consulte Errors and status codes.
