Chaque étape de pipeline activée laisse un enregistrement dans le job, pour que vous puissiez voir ce qui s'est exécuté au lieu de le supposer.
Vous avez activé quelques étapes de pipeline — peut-être pre-edit pour nettoyer la source et back-translation pour repérer les dérives — et un job est revenu completed_with_warnings. Quelle étape a décroché ? Est-ce que le relecteur humain l'a seulement prise en charge, ou est-ce que le délai a expiré ? Qu'ont coûté ces étapes supplémentaires ? Un pipeline qui enchaîne plusieurs étapes IA et humaines par langue a vite fait de devenir une boîte noire : le résultat sort, et vous êtes censé croire que tout ce qui s'est passé entre-temps a bien fonctionné.
Ici, on ne vous demande pas d'y croire sur parole. Chaque étape activée écrit un enregistrement dans le tableau steps[] du job — quelle étape, avec quel statut, pour quel coût, et quand elle a commencé puis s'est terminée. Vous lisez ce que chaque étape a fait ; vous ne partez pas du principe qu'elle s'est exécutée. C'est tout l'objet de cette page.
Nouveau sur le pipeline ? Commencez par la Vue d'ensemble du pipeline.
Sur cette page
- Où se trouvent les enregistrements
- Le tableau steps
- Associer un stepId à une étape
- Statut d'une étape : completed, failed, skipped
- Comment l'échec d'une étape devient un avertissement de job
Où se trouvent les enregistrements#
Le tableau steps[] est un champ du job de localisation. Vous n'avez pas besoin de le récupérer séparément — il est renvoyé chaque fois que vous lisez le job :
GET /jobs/localization/:jobIdAuthentifiez-vous avec votre clé API dans l'en-tête X-API-Key. Le point de terminaison complet, les valeurs de statut du job et la charge utile outputData sont présentés sur la page dédiée au job individuel ; cette page se concentre sur un champ de cette réponse — la trace par étape — et sur ce qu'elle vous apprend.
La règle est donc simple : chaque job que vous consultez embarque déjà son propre journal d'audit. Un job sans pipeline activé affiche un seul enregistrement, parce que la localisation de base s'exécute toujours. Activez deux étapes facultatives et vous obtenez trois enregistrements. Le tableau s'allonge avec le pipeline, à raison d'une entrée par étape, dans l'ordre où elles se sont exécutées.
Le tableau steps#
Chaque entrée de steps[] correspond à l'enregistrement d'une étape. Voici les champs à lire pour auditer une exécution — quelle étape, avec quel résultat, à quel coût et à quel moment :
"steps": [
{
"stepId": "preEdit",
"type": "action",
"status": "completed",
"errorMessage": null,
"costUsd": 0.0012,
"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:02.000Z"
},
{
"stepId": "localize",
"type": "action",
"status": "completed",
"errorMessage": null,
"costUsd": 0.0184,
"externalRefType": null,
"externalRefId": null,
"externalRefUrl": null,
"createdAt": "2026-03-16T10:30:02.000Z",
"startedAt": "2026-03-16T10:30:02.000Z",
"completedAt": "2026-03-16T10:30:05.000Z"
}
]| Champ | Description |
|---|---|
stepId | L'étape du pipeline à laquelle correspond cet enregistrement. Voir la table de correspondance ci-dessous. |
type | Le type d'étape. action pour une étape automatisée. |
status | completed, failed ou skipped pour cette étape — indépendamment du statut du job. |
errorMessage | Pourquoi cette étape a échoué. null sauf si status vaut failed. |
costUsd | Le coût de cette étape, en USD — un nombre JSON, ou null. |
externalRefType, externalRefId, externalRefUrl | Un pointeur vers un enregistrement externe pour les étapes qui confient le travail à un tiers — l'étape de relecture humaine. null pour les étapes entièrement automatisées. |
createdAt, startedAt, completedAt | Quand l'étape a été créée, prise en charge et terminée. |
Chaque enregistrement contient aussi un champ outputData — le contenu produit par cette étape, dans la même structure que le outputData du job. Cette charge utile correspond à la traduction, pas à la piste d'audit ; elle est donc documentée sur la page dédiée au job individuel, avec le outputData au niveau du job. Les champs ci-dessus sont ceux à lire pour voir ce que le pipeline a fait.
Ces enregistrements vous apportent deux choses qu'un simple blob outputData ne peut pas donner. D'abord, le coût est détaillé étape par étape, et pas seulement totalisé au niveau du job — ainsi, lorsque vous activez la back-translation et que la facture évolue, vous pouvez voir exactement quelle étape en est la cause. Ensuite, le timing est détaillé par étape — un enregistrement humanEdit dont startedAt et completedAt sont espacés de plusieurs heures vous indique que l'attente venait de l'humain, pas du moteur.
Lisez steps par stepId, pas par position
Les enregistrements apparaissent dans l'ordre d'exécution, mais n'indexez pas le tableau par position — les étapes exécutées dépendent de celles que vous avez activées, donc la position n'est pas stable d'un job à l'autre. Identifiez une étape par son stepId (steps.find(s => s.stepId === "humanEdit")). L'ensemble des valeurs de stepId est fixe ; celles présentes sur un job donné correspondent simplement aux étapes que vous avez activées.
Associer un stepId à une étape#
Chaque stepId désigne une étape du pipeline. Voici la table de correspondance entre la valeur présente dans l'enregistrement, l'étape qu'elle représente et la page qui documente son rôle :
stepId | Étape |
|---|---|
preEdit | Édition IA avant localisation |
localize | Localisation de base |
humanEdit | Relecture humaine post-localisation |
postEdit | évaluation IA post-localisation |
rephrase | Reformuler pour un texte plus naturel |
backTranslation | Vérification par back-translation |
localize est le seul stepId qui apparaît sur chaque job, avec ou sans pipeline — c'est l'étape de traduction principale, et elle s'exécute toujours. Les cinq autres n'apparaissent que si vous avez activé cette étape sur le moteur ou dans la requête.
Statut d'une étape : completed, failed, skipped#
Chaque étape a son propre status, défini indépendamment du job et de toutes les autres étapes. Trois valeurs :
status de l'étape | Signification |
|---|---|
completed | L'étape s'est exécutée et a produit son résultat. |
failed | L'étape s'est exécutée puis a échoué. errorMessage indique pourquoi. |
skipped | L'étape n'est pas allée au bout cette fois, même si elle était activée. |
completed et failed se lisent comme on s'y attend. skipped est celui qui mérite qu'on s'y attarde, car il ne signifie pas la même chose que « disabled ». Une étape que vous n'avez jamais activée ne produit aucun enregistrement. Un enregistrement skipped signifie que l'étape était activée, mais qu'elle a été passée pour une raison définie par le pipeline — le cas le plus clair est la relecture humaine : si la fenêtre de relecture se ferme sans réponse humaine, cette étape est marquée skipped et la traduction IA est conservée comme résultat final. L'enregistrement est toujours là, donc ce saut d'étape reste visible au lieu de passer inaperçu.
Le statut d'une étape n'est pas le statut du job
Une étape failed ne signifie pas toujours un job failed. La plupart des étapes facultatives ne sont pas critiques : quand l'une échoue, son enregistrement indique failed, le moteur reprend la dernière sortie valide et le job se termine quand même avec un outputData complet. Le statut de job qui en résulte — completed_with_warnings — est expliqué sur la page dédiée au job individuel. Le statut de l'étape vous dit ce qui est arrivé à une étape ; le statut du job vous dit si vous avez obtenu une traduction.
Comment l'échec d'une étape devient un avertissement de job#
Lorsqu'une étape non critique échoue, cet échec apparaît à deux endroits à la fois — deux vues du même événement. L'enregistrement steps[] indique failed avec un errorMessage — c'est la vue détaillée. Le même échec apparaît aussi comme une entrée dans le tableau warnings au niveau supérieur du job — c'est la vue synthétique sur laquelle votre code de gestion des statuts s'appuie :
{
"id": "ljb_A1b2C3d4E5f6G7h8",
"status": "completed_with_warnings",
"outputData": { "title": "Hallo" },
"warnings": [
{ "step": "backTranslation", "message": "Back-translation check did not complete" }
],
"steps": [
{ "stepId": "localize", "type": "action", "status": "completed", "errorMessage": null, "costUsd": 0.0184, "completedAt": "2026-03-16T10:30:05.000Z" },
{ "stepId": "backTranslation", "type": "action", "status": "failed", "errorMessage": "Back-translation check did not complete", "costUsd": 0.0031, "completedAt": "2026-03-16T10:30:11.000Z" }
]
}Chaque entrée de warnings est un { step, message }, où step est le même stepId que celui figurant dans l'enregistrement en échec. Les deux tableaux se correspondent donc : warnings est la liste courte de ce qui s'est mal passé, et steps[] est l'endroit où aller chercher le détail. Lisez warnings pour décider s'il faut signaler la langue à un humain ; consultez l'enregistrement steps[] correspondant si vous voulez le errorMessage, le coût et le timing associés.
C'est le mécanisme derrière completed_with_warnings : la traduction principale a réussi, donc vous avez un outputData exploitable, mais au moins une étape non critique a laissé un enregistrement failed et un avertissement correspondant. Considérez le résultat comme publiable et les avertissements comme un signal qualité à faire remonter. Seul un status de job égal à failed signifie qu'il n'y a pas de traduction à lire — et cette décision, avec la table complète des statuts de job, se trouve sur la page dédiée au job individuel.
La santé globale des étapes se consulte ailleurs
steps[] répond à la question « qu'a fait le pipeline sur ce job ? ». Si vous voulez voir la tendance sur de nombreux jobs — à quelle fréquence pre-edit échoue, à quelle fréquence back-translation corrige une traduction — vous êtes dans une logique agrégée, et la réponse se trouve sur la page Reports, pas dans une réponse par job. Ici, les enregistrements par job ; là-bas, les agrégats.
