Format de reponse : id, choices et finish_reason
Anatomie d’une reponse Chat Completions
Chaque appel a l’endpoint Chat Completions retourne un objet JSON structure avec des champs standardises. Comprendre cette structure est essentiel pour extraire correctement les donnees, gerer les cas limites et deboguer vos integrations.

Structure complete de la reponse
Voici un exemple de reponse typique retournee par l’API :
{
"id": "chatcmpl-abc123xyz",
"object": "chat.completion",
"created": 1712345678,
"model": "grok-4.20-reasoning",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Le deep learning est une branche du machine learning..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 42,
"completion_tokens": 156,
"total_tokens": 198
},
"system_fingerprint": "fp_abc123"
}
Les champs de premier niveau
id: identifiant unique de la completion (formatchatcmpl-...). Utile pour le suivi et le debogage.object: toujours"chat.completion". Permet de distinguer ce type de reponse d’autres endpoints.created: timestamp Unix de la creation de la reponse.model: le modele qui a genere la reponse. Peut differer legerement du modele demande si vous utilisez un alias.choices: tableau contenant la ou les reponses generees.usage: compteurs de tokens pour la facturation.system_fingerprint: empreinte de la configuration systeme utilisee.
Le tableau choices
Le champ choices est un tableau qui contient generalement un seul element (index 0). Chaque element possede :
index: position dans le tableau (commence a 0)message: objet avecrole(toujours"assistant") etcontent(le texte genere)finish_reason: la raison pour laquelle la generation s’est arretee
Pour extraire la reponse textuelle :
# Python
reponse_texte = response.choices[0].message.content
// JavaScript
const reponseTexte = response.choices[0].message.content;
Les valeurs de finish_reason
Le champ finish_reason est crucial pour comprendre pourquoi le modele a arrete de generer du texte :
stop
"finish_reason": "stop"
Le modele a termine sa reponse naturellement. C’est le cas le plus courant et le plus souhaitable : le modele a dit tout ce qu’il avait a dire.
length
"finish_reason": "length"
La generation a ete interrompue parce que max_tokens a ete atteint. La reponse est donc tronquee. Vous devez soit augmenter max_tokens, soit faire une requete de continuation.
tool_calls
"finish_reason": "tool_calls"
Le modele souhaite appeler un outil (function calling). Au lieu de generer du texte, il a produit un appel de fonction que votre application doit executer avant de renvoyer le resultat.
content_filter
"finish_reason": "content_filter"
La generation a ete bloquee par les filtres de securite de xAI. Le contenu demande ou genere a ete juge inapproprie. Le champ content peut etre vide ou partiellement rempli.
Gerer les differents cas
En production, vous devez verifier finish_reason pour adapter votre comportement :
choice = response.choices[0]
if choice.finish_reason == "stop":
# Reponse complete — afficher normalement
print(choice.message.content)
elif choice.finish_reason == "length":
# Reponse tronquee — prevenir l'utilisateur ou continuer
print(choice.message.content)
print("[Reponse tronquee — augmentez max_tokens]")
elif choice.finish_reason == "tool_calls":
# Le modele veut appeler un outil
for tool_call in choice.message.tool_calls:
print(f"Outil demande : {tool_call.function.name}")
elif choice.finish_reason == "content_filter":
# Contenu filtre
print("La reponse a ete bloquee par les filtres de securite.")
Points cles a retenir
- La reponse contient un
idunique, un tableauchoiceset un objetusage - Le texte genere se trouve dans
choices[0].message.content finish_reasonindique pourquoi la generation s’est arretee :stop,length,tool_callsoucontent_filter- Verifiez toujours
finish_reasonen production pour gerer les reponses tronquees ou filtrees - Le
system_fingerprintidentifie la configuration systeme utilisee pour la generation