À la fin de ce guide, vous saurez utiliser l’API de lot d’OpenAI (Batch API) pour exécuter des milliers de requêtes de modèle dans une tâche asynchrone unique, récupérer les résultats et réduire le coût des jetons de 50 %. Vous préparerez un fichier JSONL, téléverserez ce fichier, créerez un lot, interrogerez son état, téléchargerez la sortie, puis testerez le flux dans Apidog avant de l’automatiser. Si votre cas d’usage est interactif, utilisez plutôt le chemin synchrone et consultez comment tester l’API ChatGPT avec Apidog.
Qu’est-ce que l’API de lot et quand l’utiliser
L’API de lot permet d’exécuter un grand volume d’appels de modèles de manière asynchrone. Au lieu d’envoyer une requête HTTP par invite, vous regroupez les requêtes dans un fichier JSONL, vous soumettez ce fichier comme une tâche unique, puis vous interrogez son état jusqu’à la fin du traitement.
OpenAI exécute le lot hors du chemin synchrone et renvoie les résultats dans un fichier de sortie.
Les deux bénéfices principaux sont :
- 50 % de réduction sur les jetons d’entrée et de sortie par rapport aux points d’accès synchrones.
- Un débit séparé, car les lots utilisent un pool de limites distinct de votre trafic en direct.
Le compromis est la latence : OpenAI indique une fenêtre de complétion pouvant aller jusqu’à 24 heures.
Utilisez l’API de lot pour des traitements hors ligne comme :
- classer ou étiqueter un arriéré d’enregistrements ;
- générer des embeddings pour un corpus entier ;
- produire du contenu en volume : descriptions de produits, résumés, traductions ;
- exécuter des suites d’évaluation ou comparer des modèles sur un dataset.
Évitez-la pour les parcours utilisateur interactifs : chat, autocomplétion, agents en direct ou toute fonctionnalité qui attend une réponse immédiate. Pour des cas comme la génération de nombreuses configurations d’agents, le traitement par lots est adapté ; voir aussi le guide sur la génération de plus de 100 configurations d’agents avec le traitement par lots.
Prérequis
Vous allez utiliser deux points d’accès :
/v1/files/v1/batches
Le flux complet contient quatre étapes :
| Étape | Point d’accès | Action |
|---|---|---|
| 1. Téléverser | POST /v1/files |
Envoyer le fichier .jsonl avec purpose: "batch" et récupérer un ID de fichier |
| 2. Créer | POST /v1/batches |
Soumettre l’ID du fichier, le point d’accès cible et la fenêtre de complétion |
| 3. Interroger | GET /v1/batches/{id} |
Lire le status jusqu’à completed
|
| 4. Récupérer | GET /v1/files/{id}/content |
Télécharger les résultats via output_file_id
|
Avant de commencer, préparez :
- une clé API OpenAI exportée dans
OPENAI_API_KEY; - un fichier JSONL contenant vos requêtes ;
- un outil pour exécuter et inspecter les appels HTTP, par exemple Apidog ou
curl.
export OPENAI_API_KEY="sk-..."
Étape 1 : construire le fichier JSONL
Le fichier d’entrée est un fichier JSONL : une requête par ligne.
Chaque ligne doit contenir :
-
custom_id: un identifiant unique que vous choisissez ; -
method: généralementPOST; -
url: le point d’accès cible, par exemple/v1/chat/completions; -
body: les paramètres réels de la requête.
Exemple requests.jsonl :
{"custom_id": "req-1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4.1-mini", "messages": [{"role": "user", "content": "Classify the sentiment of: 'shipping was slow but the product is great'"}]}}
{"custom_id": "req-2", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4.1-mini", "messages": [{"role": "user", "content": "Classify the sentiment of: 'returned it the same day'"}]}}
Points à vérifier avant le téléversement :
-
custom_iddoit être unique dans le fichier ; -
urldoit correspondre au point d’accès que vous indiquerez dans le lot ; - chaque ligne doit être un JSON valide ;
- ne comptez pas sur l’ordre des résultats : utilisez toujours
custom_idpour faire la correspondance.
Un lot peut contenir jusqu’à 50 000 requêtes et le fichier peut atteindre 200 Mo.
Étape 2 : téléverser le fichier
Envoyez le fichier à l’API Files avec purpose="batch" :
curl https://api.openai.com/v1/files \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F purpose="batch" \
-F file="@requests.jsonl"
La réponse contient un id de fichier :
{
"id": "file-abc123",
"object": "file",
"purpose": "batch"
}
Conservez cette valeur. Elle devient votre input_file_id.
Étape 3 : créer le lot
Créez ensuite la tâche de lot avec POST /v1/batches.
curl https://api.openai.com/v1/batches \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input_file_id": "file-abc123",
"endpoint": "/v1/chat/completions",
"completion_window": "24h",
"metadata": {
"job": "sentiment-backfill"
}
}'
À vérifier :
-
input_file_iddoit être l’ID renvoyé par/v1/files; -
endpointdoit correspondre au champurlde vos lignes JSONL ; -
completion_windowaccepte actuellement"24h"; -
metadataest optionnel et peut servir à identifier la tâche.
Les cibles prises en charge incluent notamment :
/v1/chat/completions/v1/responses/v1/embeddings/v1/completions/v1/moderations
La réponse renvoie un objet de lot :
{
"id": "batch_abc123",
"object": "batch",
"endpoint": "/v1/chat/completions",
"input_file_id": "file-abc123",
"completion_window": "24h",
"status": "validating",
"output_file_id": null,
"error_file_id": null,
"request_counts": {
"total": 0,
"completed": 0,
"failed": 0
},
"created_at": 1733452800,
"metadata": {
"job": "sentiment-backfill"
}
}
Conservez id, par exemple batch_abc123.
Étape 4 : interroger l’état du lot
Un lot démarre généralement avec le statut validating.
Interrogez l’état avec :
curl https://api.openai.com/v1/batches/batch_abc123 \
-H "Authorization: Bearer $OPENAI_API_KEY"
Surveillez le champ status.
| État | Signification |
|---|---|
validating |
Le fichier d’entrée est vérifié avant l’exécution |
in_progress |
Les requêtes sont en cours de traitement |
finalizing |
L’exécution est terminée et le fichier de sortie est en préparation |
completed |
Les résultats sont prêts à être téléchargés |
failed |
La validation a échoué ; rien n’a été exécuté |
expired |
La fenêtre de 24 heures s’est fermée avant la fin de toutes les requêtes |
cancelling / cancelled
|
Une annulation a été demandée |
Pendant in_progress, utilisez request_counts pour suivre l’avancement :
"request_counts": {
"total": 50000,
"completed": 32000,
"failed": 10
}
Il n’y a pas de webhook à attendre dans ce flux. Utilisez donc une boucle d’interrogation à intervalle raisonnable, par exemple toutes les quelques minutes, pas chaque seconde.
Exemple minimal en Bash :
BATCH_ID="batch_abc123"
while true; do
RESPONSE=$(curl -s https://api.openai.com/v1/batches/$BATCH_ID \
-H "Authorization: Bearer $OPENAI_API_KEY")
STATUS=$(echo "$RESPONSE" | jq -r '.status')
echo "Status: $STATUS"
if [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ] || [ "$STATUS" = "expired" ] || [ "$STATUS" = "cancelled" ]; then
echo "$RESPONSE" > batch-status.json
break
fi
sleep 180
done
Vous pouvez aussi annuler un lot en cours :
curl -X POST https://api.openai.com/v1/batches/batch_abc123/cancel \
-H "Authorization: Bearer $OPENAI_API_KEY"
Étape 5 : télécharger la sortie
Quand status vaut completed, l’objet de lot contient un output_file_id.
Téléchargez le fichier de sortie :
curl https://api.openai.com/v1/files/file-output456/content \
-H "Authorization: Bearer $OPENAI_API_KEY" \
> results.jsonl
La sortie est aussi en JSONL : une ligne par requête.
Chaque ligne contient notamment :
- le
custom_idd’origine ; - un objet
response; - le code d’état ;
- le corps de réponse.
Exemple simplifié :
{"custom_id":"req-1","response":{"status_code":200,"body":{"choices":[{"message":{"content":"mixed positive"}}]}}}
{"custom_id":"req-2","response":{"status_code":200,"body":{"choices":[{"message":{"content":"negative"}}]}}}
Important : les résultats ne sont pas garantis dans le même ordre que les lignes d’entrée. Faites toujours la jointure via custom_id.
Si certaines requêtes échouent, vérifiez aussi error_file_id dans l’objet de lot et téléchargez ce fichier avec /v1/files/{id}/content.
Coût, délai et limites pratiques
Le modèle opérationnel est simple : vous économisez 50 % sur les jetons, mais vous acceptez une fenêtre pouvant aller jusqu’à 24 heures.
C’est adapté pour :
- des traitements nocturnes ;
- des backfills ;
- des enrichissements de données ;
- des évaluations hors ligne.
Ce n’est pas adapté pour :
- une interface de chat ;
- une action utilisateur bloquante ;
- une autocomplétion ;
- un agent qui doit répondre immédiatement.
Quelques points à intégrer dans votre implémentation :
- La réduction s’applique aux jetons d’entrée et de sortie sur les modèles pris en charge.
- La fenêtre de 24 heures est un plafond, pas un SLA de rapidité.
- Si un lot passe à
expired, les requêtes terminées sont renvoyées et facturées ; les autres ne le sont pas. - Les lots utilisent une limite de jetons en file d’attente distincte et ne consomment pas les mêmes limites que le trafic synchrone.
- Les volumes élevés restent coûteux même avec 50 % de réduction : utilisez
metadatapour suivre les jobs et attribuer les dépenses.
Si vous atteignez déjà les plafonds côté synchrone, consultez le guide sur les limites de taux de l’API GPT et comment les tester. Pour l’attribution des coûts, voir aussi ce guide d’attribution des dépenses OpenAI.
Tester le flux dans Apidog
L’API de lot est plus facile à casser qu’un appel de chat synchrone : un JSONL mal formé, un endpoint qui ne correspond pas à url, un custom_id dupliqué ou une mauvaise boucle d’interrogation peuvent faire échouer tout le workflow.
Apidog vous permet d’exécuter chaque étape comme une requête API, de chaîner les appels et d’ajouter des assertions sur les réponses. Ce n’est pas un SDK OpenAI ; c’est une plateforme pour tester, documenter et simuler des API.
Un plan de test utile :
- Valider localement le JSONL
Vérifiez que chaque ligne contient :
custom_idmethodurlbodybody.model- les messages ou paramètres attendus
- Tester le téléversement multipart
Envoyez POST /v1/files avec :
purpose=batch- le fichier
requests.jsonl
Capturez l’id retourné dans une variable d’environnement.
- Créer le lot
Exécutez POST /v1/batches, puis ajoutez des assertions :
-
statusvautvalidating -
endpointcorrespond au point d’accès attendu -
input_file_idcorrespond au fichier téléversé
- Interroger le lot
Appelez GET /v1/batches/{id} jusqu’à un état terminal :
completedfailedexpiredcancelled
- Télécharger les résultats
Quand output_file_id est présent, appelez :
GET /v1/files/{output_file_id}/content
Puis vérifiez que chaque ligne de sortie contient un custom_id.
- Tester les erreurs
Soumettez un fichier volontairement invalide pour confirmer que votre gestion du statut failed fonctionne. Testez aussi :
POST /v1/batches/{id}/cancel
Comme la sortie peut arriver plus tard, vous pouvez aussi configurer une API simulée qui renvoie un objet de lot terminé et un fichier de résultats pré-enregistré. Cela permet de développer la logique de récupération et de parsing sans attendre une vraie tâche de 24 heures ni consommer de jetons.
Si votre équipe travaille à partir de spécifications, vous pouvez également générer une collection de tests depuis une spécification OpenAPI et maintenir ce workflow sous tests de régression en CI.
Foire aux questions
Combien de temps prend réellement une tâche par lots ?
OpenAI indique une fenêtre de complétion allant jusqu’à 24 heures. Certaines tâches peuvent se terminer plus vite, mais votre système doit gérer le pire cas.
Si la fenêtre expire, le lot passe à expired. Les requêtes déjà terminées sont renvoyées et facturées ; les autres ne le sont pas.
Quelle est la réduction ?
L’API de lot offre une réduction forfaitaire de 50 % par rapport aux points d’accès synchrones, sur les jetons d’entrée et de sortie.
Si vous devez rattacher ces dépenses à des fonctionnalités ou à des jobs, utilisez metadata et consultez le guide d’attribution des coûts.
Quels points d’accès puis-je exécuter dans un lot ?
Vous indiquez la cible à deux endroits :
- dans
urlpour chaque ligne JSONL ; - dans
endpointlors de la création du lot.
Les deux doivent correspondre.
Les cibles prises en charge incluent notamment :
/v1/chat/completions/v1/responses/v1/embeddings/v1/completions/v1/moderations
OpenAI peut faire évoluer cette liste ; vérifiez la documentation actuelle pour les points d’accès disponibles.
Pourquoi mes résultats ne sont-ils pas dans le même ordre ?
C’est normal. La sortie JSONL ne garantit pas l’ordre des lignes d’entrée.
Utilisez custom_id pour faire correspondre chaque résultat à sa requête source. Si deux lignes partagent le même custom_id, vous ne pourrez pas distinguer leurs réponses de manière fiable.
Conclusion
Le workflow complet est maintenant clair :
- préparer un fichier JSONL ;
- le téléverser avec
purpose=batch; - créer un lot avec
POST /v1/batches; - interroger l’état jusqu’à un statut terminal ;
- télécharger
output_file_id; - traiter les résultats via
custom_id.
L’API de lot est utile dès que vous avez un gros volume de requêtes hors ligne et que vous pouvez accepter une fenêtre de traitement pouvant aller jusqu’à 24 heures.
Avant de l’automatiser en production, exécutez le cycle de vie à la main. Téléchargez Apidog pour valider vos requêtes, tester les points d’accès de téléversement, de création, d’interrogation et d’annulation, et ajouter des assertions sur les objets de lot.
Top comments (0)