DEV Community

Cover image for Comment Tester l'API ChatGPT avec Apidog : Authentification, Streaming, Outils et Intégration Continue
Antoine Laurent
Antoine Laurent

Posted on • Originally published at apidog.com

Comment Tester l'API ChatGPT avec Apidog : Authentification, Streaming, Outils et Intégration Continue

L'API ChatGPT évolue vite : contrats qui changent, facturation par jeton même sur des tests ratés, streaming SSE différent du mode non-streaming, appels d'outils à valider, limites de débit visibles trop tard en production. Si vous testez tout dans un REPL Python ou avec des boucles curl, vous perdez du temps, de l'argent et de la visibilité.

Essayez Apidog aujourd’hui

Ce guide montre comment tester l'API ChatGPT dans Apidog : authentification, première complétion, streaming SSE, appel de fonction, erreurs, limites de débit, mocks frontend et scénario CI. À la fin, vous aurez un projet Apidog réutilisable pour détecter les dérives de contrat OpenAI avant la production.

En bref

  • Configurez https://api.openai.com/v1 comme URL de base dans un environnement Apidog.
  • Stockez OPENAI_API_KEY comme variable secrète.
  • Appliquez l'authentification Bearer au niveau du dossier.
  • Créez une requête POST /chat/completions réutilisable pour vos modèles.
  • Testez explicitement le streaming SSE avec stream: true.
  • Validez les tool_calls retournés par le modèle.
  • Simulez ChatGPT avec Smart Mock pour débloquer le frontend.
  • Enregistrez les requêtes critiques dans un scénario de test CI avec assertions.

Pourquoi tester l'API ChatGPT ?

L'API OpenAI semble stable, mais plusieurs comportements ont changé ou coexistent encore :

  • function_call et tool_calls
  • Mode strict pour les schémas d'outils
  • Modèles de raisonnement (o1, o3) qui rejettent certains paramètres comme temperature et top_p
  • response_format: { type: "json_schema" }
  • Streaming des appels d'outils avec deltas à assembler
  • Nouveau point de terminaison /v1/responses, qui chevauche /v1/chat/completions

Sans couche de test, une simple modification de prompt peut casser le code aval sans erreur immédiate. Une collection Apidog vous donne un contrat exécutable : même requête, mêmes assertions, échec visible si la forme de réponse change.

Étape 1 : créer l'environnement OpenAI dans Apidog

Dans Apidog, créez un nouveau projet, puis ajoutez un environnement appelé OpenAI Prod.

Variable Valeur
baseUrl https://api.openai.com/v1
OPENAI_API_KEY sk-proj-... à stocker comme Secret
defaultModel gpt-5.5

Marquez OPENAI_API_KEY comme secret. Elle sera masquée dans les espaces partagés et ne sera pas écrite dans les exports. Chaque membre de l'équipe pourra fournir sa propre clé sans modifier la collection.

Étape 2 : configurer l'authentification Bearer

Créez un dossier ChatGPT.

Dans les paramètres du dossier :

  1. Ouvrez l'onglet Auth.
  2. Choisissez Bearer Token.
  3. Utilisez cette valeur :
{{OPENAI_API_KEY}}
Enter fullscreen mode Exit fullscreen mode

Toutes les requêtes du dossier héritent automatiquement de l'en-tête :

Authorization: Bearer {{OPENAI_API_KEY}}
Enter fullscreen mode Exit fullscreen mode

Résultat : plus besoin de copier la clé dans chaque requête, et la rotation de clé se fait en un seul endroit.

Étape 3 : créer une première requête de complétion

Dans le dossier ChatGPT, créez une requête :

  • Méthode : POST
  • URL : {{baseUrl}}/chat/completions
  • Nom : chat-completion-basic
  • Body : JSON
{
  "model": "{{defaultModel}}",
  "messages": [
    {
      "role": "system",
      "content": "You are a senior backend engineer. Answer in under 100 words."
    },
    {
      "role": "user",
      "content": "What's the difference between idempotent and safe HTTP methods?"
    }
  ],
  "temperature": 0.2
}
Enter fullscreen mode Exit fullscreen mode

Envoyez la requête.

Vous devez obtenir :

  • un statut 200
  • une réponse dans choices[0].message.content
  • un bloc usage avec les compteurs de jetons

Exemple de vérifications utiles :

pm.test("Status is 200", () => {
  pm.response.to.have.status(200);
});

pm.test("Response has content", () => {
  const body = pm.response.json();
  pm.expect(body.choices[0].message.content).to.be.a("string");
});

pm.test("Token usage is present", () => {
  const body = pm.response.json();
  pm.expect(body.usage.total_tokens).to.be.greaterThan(0);
});
Enter fullscreen mode Exit fullscreen mode

Si vous obtenez 401, vérifiez que l'environnement OpenAI Prod est sélectionné et que la clé est bien renseignée.

Si vous obtenez 429, vous avez probablement atteint une limite de débit.

Étape 4 : tester le streaming SSE

Le streaming ChatGPT utilise text/event-stream. La réponse n'est pas un JSON unique : elle arrive sous forme de lignes data: {...} contenant des deltas partiels.

Dupliquez chat-completion-basic, renommez la copie en chat-completion-stream, puis utilisez ce body :

{
  "model": "{{defaultModel}}",
  "stream": true,
  "messages": [
    {
      "role": "user",
      "content": "Stream the first 100 prime numbers, comma-separated."
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Envoyez la requête.

Dans Apidog, le panneau de réponse affiche les fragments SSE au fur et à mesure. C'est utile pour déboguer :

  • les deltas incomplets
  • les chunks malformés
  • le terminateur manquant
  • les appels d'outils streamés morceau par morceau

Points à vérifier :

  • La dernière trame doit être :
data: [DONE]
Enter fullscreen mode Exit fullscreen mode
  • Si votre client tente de parser [DONE] comme JSON, il échouera.
  • Le champ usage n'est pas présent par défaut en streaming.
  • Pour inclure l'utilisation des jetons, ajoutez :
"stream_options": {
  "include_usage": true
}
Enter fullscreen mode Exit fullscreen mode

Body complet :

{
  "model": "{{defaultModel}}",
  "stream": true,
  "stream_options": {
    "include_usage": true
  },
  "messages": [
    {
      "role": "user",
      "content": "Stream the first 100 prime numbers, comma-separated."
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Pour les appels d'outils en streaming, testez aussi l'assemblage des champs :

  • index
  • id
  • function.name
  • function.arguments

Les arguments peuvent arriver caractère par caractère. Votre client doit les concaténer avant de parser le JSON.

Étape 5 : tester les appels de fonction et les outils

Les appels d'outils cassent souvent silencieusement après une modification de prompt. Le modèle retourne un tableau tool_calls, et votre code doit vérifier que les arguments correspondent au schéma attendu.

Créez une requête chat-completion-tools :

{
  "model": "{{defaultModel}}",
  "messages": [
    {
      "role": "user",
      "content": "What is the weather in Singapore right now?"
    }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Get current weather for a city.",
        "parameters": {
          "type": "object",
          "properties": {
            "city": {
              "type": "string"
            },
            "unit": {
              "type": "string",
              "enum": ["c", "f"]
            }
          },
          "required": ["city"]
        },
        "strict": true
      }
    }
  ],
  "tool_choice": "auto"
}
Enter fullscreen mode Exit fullscreen mode

Une réponse exploitable doit contenir :

choices[0].message.tool_calls[0].function.name === "get_weather"
Enter fullscreen mode Exit fullscreen mode

Et function.arguments doit être une chaîne JSON valide, par exemple :

{
  "city": "Singapore",
  "unit": "c"
}
Enter fullscreen mode Exit fullscreen mode

Ajoutez ces tests dans l'onglet Tests :

pm.test("Tool was called", () => {
  const body = pm.response.json();
  const call = body.choices[0].message.tool_calls?.[0];

  pm.expect(call?.function?.name).to.eql("get_weather");
});

pm.test("Arguments parse as valid JSON", () => {
  const body = pm.response.json();
  const argsRaw = body.choices[0].message.tool_calls[0].function.arguments;
  const args = JSON.parse(argsRaw);

  pm.expect(args.city).to.be.a("string");
});
Enter fullscreen mode Exit fullscreen mode

Ces assertions deviennent votre contrat. Si la forme de réponse change, le test échoue avant que votre application ne casse en production.

Étape 6 : tester les erreurs et les limites de débit

Créez des requêtes dédiées pour les scénarios d'erreur prévisibles.

Scénario Comment déclencher Attendu
Clé invalide Définir OPENAI_API_KEY sur sk-bad dans un environnement Sandbox 401 avec error.code = "invalid_api_key"
Limite de débit Exécuter la requête 200 fois dans le collection runner Apidog 429 avec l'en-tête Retry-After
Limite de jetons dépassée Envoyer un prompt de 200K jetons à un modèle de contexte de 128K 400 avec error.code = "context_length_exceeded"
Nom de modèle incorrect Utiliser "model": "gpt-99" 404
Violation de schéma Appel d'outil avec strict: true et entrée malformée Le modèle rejette l'outil ou renvoie du texte brut

Exemple d'assertion pour une clé invalide :

pm.test("Invalid key returns 401", () => {
  pm.response.to.have.status(401);
});

pm.test("Error code is invalid_api_key", () => {
  const body = pm.response.json();
  pm.expect(body.error.code).to.eql("invalid_api_key");
});
Enter fullscreen mode Exit fullscreen mode

Exemple pour une limite de débit :

pm.test("Rate limit returns 429", () => {
  pm.response.to.have.status(429);
});

pm.test("Retry-After header exists", () => {
  pm.expect(pm.response.headers.get("Retry-After")).to.not.be.null;
});
Enter fullscreen mode Exit fullscreen mode

Ne codez pas un backoff fixe sans lire Retry-After. Cet en-tête est souvent en secondes, parfois avec une valeur fractionnaire.

Étape 7 : simuler ChatGPT pour le frontend

Votre équipe frontend peut avoir besoin de travailler avant que le prompt backend soit stable, ou sans consommer le budget OpenAI.

Dans Apidog :

  1. Faites un clic droit sur chat-completion-basic.
  2. Choisissez Smart Mock.
  3. Activez le mock.

Apidog génère une réponse compatible avec le schéma OpenAI :

  • id
  • object
  • created
  • model
  • choices
  • usage

L'URL de mock ressemble à ceci :

https://mock.apidog.com/m1/<projectId>/chat/completions
Enter fullscreen mode Exit fullscreen mode

Elle accepte le même body que l'API réelle.

Pour un frontend qui consomme du SSE, configurez un mock avancé qui écrit des fragments au format :

data: { ... }

data: { ... }

data: [DONE]
Enter fullscreen mode Exit fullscreen mode

Avec un intervalle court, par exemple 50 ms, l'interface peut tester :

  • affichage token par token
  • état de chargement
  • bouton stop
  • rendu progressif
  • cartes d'appel d'outils

Quand le prompt réel est prêt, remplacez simplement l'URL de base par :

https://api.openai.com/v1
Enter fullscreen mode Exit fullscreen mode

Le contrat de requête reste identique.

Étape 8 : créer un scénario de test CI

Les scénarios Apidog permettent d'enchaîner plusieurs requêtes avec assertions.

Créez un scénario qui exécute :

  1. chat-completion-basic

    • vérifie status === 200
    • vérifie usage.total_tokens > 0
  2. chat-completion-stream

    • vérifie que le flux se termine par [DONE]
  3. chat-completion-tools

    • vérifie que tool_calls existe
    • vérifie que function.arguments est un JSON valide
  4. Les scénarios d'erreur de l'étape 6

    • vérifie les statuts attendus
    • vérifie les codes d'erreur utiles

Exportez le scénario, puis exécutez-le en CI :

apidog-cli run scenario.json --env "OpenAI Prod"
Enter fullscreen mode Exit fullscreen mode

Ajoutez cette commande dans le pipeline de PR qui modifie vos prompts. Chaque changement est alors testé contre l'API OpenAI avant merge.

Coût : quelques appels API.

Bénéfice : les régressions de prompt deviennent des tests rouges, pas des incidents de production.

FAQ

Cela fonctionne-t-il avec Azure OpenAI ?

Oui. Remplacez baseUrl par l'URL de votre ressource Azure, ajoutez le paramètre api-version, puis utilisez l'en-tête api-key au lieu de l'authentification Bearer. Les corps de requête restent similaires.

Puis-je tester les modèles de raisonnement o1 et o3 ?

Oui, mais ces modèles rejettent certains paramètres comme :

  • temperature
  • top_p
  • presence_penalty
  • frequency_penalty

Créez un dossier séparé Reasoning avec un body simplifié.

Comment versionner les prompts dans Apidog ?

Utilisez les branches Apidog. Créez une branche par expérience de prompt, exécutez le scénario de test, comparez l'utilisation des jetons et la qualité des réponses, puis fusionnez. C'est le même flux que pour le code, appliqué aux prompts.

Et le point de terminaison /v1/responses ?

Créez un dossier dédié. L'authentification et l'URL de base sont les mêmes ; seule la forme du body change. Gardez /chat/completions et /responses séparés pour pouvoir les tester en A/B avec les mêmes prompts.

Apidog facture-t-il par appel API ?

Non. OpenAI facture par jeton. Apidog ne s'intercale pas entre vous et OpenAI pour facturer les appels.

En résumé

L'API ChatGPT continuera d'évoluer. Le streaming changera, les schémas d'outils deviendront plus stricts, et certains modèles continueront à rejeter des paramètres que vous pensiez stables.

La défense pratique :

  • une collection de requêtes contrôlée
  • des assertions sur les réponses critiques
  • des mocks pour le frontend
  • un scénario CI exécuté avant chaque PR de prompt

Téléchargez Apidog, importez vos appels OpenAI existants, puis construisez ces requêtes une fois. Chaque future mise à jour de ChatGPT deviendra une exécution de test contrôlée au lieu d'un incident de production.

Top comments (0)