Webhook 和 实时 WebSocket 会在作业完成的第一时间通知你。但到了第二天早上、一次部署之后,或者当你想找出过去一小时里所有失败的语言区域时,它们就派不上用场了。那一刻已经过去,事件也随之消失;但作业不会。每个作业都会作为平台上的持久记录保留下来,即便提交它的流程早已继续往前走。
GET /jobs/localization 就是用来回查这些记录的。它会按最新优先返回你的作业,按游标分页,并可根据运行所用的引擎或最终状态缩小范围。这就是补查通道:当你没有实时监听时,用来查询持久记录的入口。
GET /jobs/localization刚接触异步本地化?先从 概览 开始。本页默认你已经有作业可查。和所有端点一样,它使用你的 X-API-Key 进行身份验证。
过滤与分页#
GET /jobs/localization?engineId=eng_abc123&status=completed&limit=20&cursor=...| 参数 | 类型 | 说明 |
|---|---|---|
engineId | string(可选) | 仅返回在该本地化引擎上运行的作业(eng_...)。 |
status | string(可选) | 仅返回处于以下状态的作业:queued、processing、completed、completed_with_warnings 或 failed。 |
limit | number(可选) | 每页条数。默认 20,最大 100。 |
cursor | string(可选) | 来自上一条响应中 nextCursor 的不透明游标。请求第一页时请省略。 |
这两个过滤条件都是可选的,而且可以组合使用:engineId=eng_abc123&status=failed 只会返回某个引擎上的失败作业,不会混入其他结果。这个组合正好能回答你在故障处理中真正会问的问题——把这个引擎上所有失败的都给我找出来——而无需先把组织内所有作业拉回客户端再做过滤。
cursor 表示的是结果流中的位置,不是页码。它不是你计算出来的,而是接口返回给你的。每次响应都会带回一个 nextCursor,你只需把这个值传回去,就能获取后续那一页。
响应#
每一页都会返回一个 items 数组和一个 nextCursor。到了最后一页,nextCursor 会是 null——这是循环结束的条件,不是错误。
{
"items": [
{
"id": "ljb_C3d4E5f6G7h8I9j0",
"groupId": "ljg_A1b2C3d4E5f6G7h8",
"targetLocale": "ja",
"status": "completed",
"warnings": [],
"createdAt": "2026-03-16T10:30:00.000Z",
"completedAt": "2026-03-16T10:30:06.000Z"
}
],
"nextCursor": "eyJ0IjoiMjAyNi0wMy0xNlQxMDozMDowMC4wMDBaIiwiaSI6ImxqYl9CMmMzRDRlNUY2ZzdIOGk5In0"
}每个条目都是摘要信息——足够你定位作业并查看结果:对应哪个语言区域、属于哪个分组、当前是什么状态、何时创建、何时完成。它有意不包含翻译后的输出。若要获取其中某个作业完整的 outputData 以及分阶段的 steps,请取出它的 id 并调用 获取单个作业。列表用于发现,详情用于读取。
优雅处理未知状态值
对已知状态值进行匹配,其余情况统一落入默认分支,而不是在遇到从未见过的值时直接让消费者崩溃。对于任何不由你掌控的字符串枚举,能容忍未识别值才是更稳妥的默认策略——这样你的读取方会继续运行,而不是因为无法归类的输入直接抛出异常。
遍历全部结果页#
退出条件正是这里的关键:持续请求,直到 nextCursor 返回 null。把上一条响应中的 nextCursor 作为下一次请求的 cursor 传入,循环就会自然结束。
async function listFailedJobs(engineId) {
const failed = [];
let cursor = undefined; // first page: no cursor
do {
const url = new URL("https://api.lingo.dev/jobs/localization");
url.searchParams.set("engineId", engineId);
url.searchParams.set("status", "failed");
url.searchParams.set("limit", "100"); // fewer round-trips
if (cursor) url.searchParams.set("cursor", cursor);
const response = await fetch(url, {
headers: { "X-API-Key": process.env.LINGO_API_KEY },
});
const { items, nextCursor } = await response.json();
failed.push(...items);
cursor = nextCursor; // null on the last page -> loop ends
} while (cursor);
return failed; // every failed job for this engine
}将 limit 提高到 100,可以减少处理大量积压结果时的往返次数;它不会改变结果本身,只会影响你需要翻多少页。这里没有会漂移的 offset,也没有需要手动保持同步的页数——游标会记录你的位置,而 null 会告诉你何时已经全部读完。
下一步#
现在你已经拿到了某个作业的 id。补查通道把你带到了这里;接下来,你可以读取结果,或者接入实时通道,这样下次就能在事情发生时第一时间收到通知。
