Responses API
POST https://api.uberllm.dev/v1/responses propose l'API Responses d'OpenAI sur chaque modèle de chat du catalogue. Utilisez-la depuis le SDK OpenAI (client.responses.create), le Codex CLI, ou toute application dotée d'un mode "Responses". Les requêtes passent par le même routage, les mêmes nouvelles tentatives, les mêmes limites de clés et la même facturation que /v1/chat/completions, et chaque appel est répertorié dans Tableau de bord → Activité avec son coût.
curl https://api.uberllm.dev/v1/responses \
-H "Authorization: Bearer $UBERLLM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek/deepseek-v4.1-flash",
"instructions": "Answer in one short sentence.",
"input": "What is the capital of France?"
}'
from openai import OpenAI
client = OpenAI(base_url="https://api.uberllm.dev/v1", api_key="ull_...")
r = client.responses.create(model="deepseek/deepseek-v4.1-flash", input="Say hi")
print(r.output_text)
Aucun état stocké
UberLLM ne conserve pas les réponses pour que vous puissiez les reprendre plus tard. Chaque réponse a
"store": false, et vous envoyez toute la conversation en input à chaque appel : les messages utilisateur précédents, les
éléments de sortie du modèle et les résultats de vos outils. Codex CLI fonctionne déjà de cette manière.
Ceux-ci sont refusés avec un 400 (code: unsupported_parameter) qui nomme le champ :
previous_response_idetconversationbackground: true- éléments d'entrée de type
item_reference - modèles d'invite stockés (
prompt)
GET /v1/responses/{id} et les autres routes de réponse stockées n'existent pas.
Requête
| Champ | Ce qui se passe |
|---|---|
model |
Tout ID de modèle de chat, alias ou suffixe :floor / :nitro, comme pour les complétions de chat. |
input |
Une chaîne de caractères, ou une liste d'éléments (ci-dessous). |
instructions |
Envoyé au modèle comme message système. |
stream |
true pour les événements envoyés par le serveur. |
max_output_tokens |
La limite de sortie. |
temperature, top_p, seed, stop |
Transmis au modèle. |
tools, tool_choice, parallel_tool_calls |
Voir Outils ci-dessous. |
reasoning.effort |
Transmis comme effort de raisonnement du modèle (modèles qui réfléchissent). |
text.format |
text, json_object, ou json_schema (sortie structurée). |
metadata |
Vos propres tags, affichés sur la ligne d'Activité, comme pour les complétions de chat. |
provider, models |
Options de routage UberLLM, comme pour les complétions de chat (Modèles et routage). |
store, include, prompt_cache_key, service_tier, truncation |
Acceptés et non utilisés. Le raisonnement chiffré est toujours renvoyé. |
Éléments d'entrée
| Élément | Devient |
|---|---|
message avec le rôle user, assistant, system ou developer |
Un message de chat. developer est envoyé comme system. Parties de contenu input_text, output_text, input_image (image_url : une URL https ou data:) et input_file (file_data ou file_url). |
function_call |
L'appel d'outil de l'assistant, maintenu dans l'ordre. |
function_call_output |
Le résultat de l'outil. Les images dans une sortie sont envoyées au tour d'utilisateur suivant. |
custom_tool_call, custom_tool_call_output |
Un appel à un outil personnalisé (libre), et son résultat. |
reasoning |
Le raisonnement antérieur du modèle, redonné au modèle au tour suivant. |
web_search_call et autres enregistrements d'outils hébergés |
Ignorés. |
Les éléments id sont acceptés et ignorés. file_id (fichiers téléchargés) n'est pas pris en charge dans input_image / input_file : envoyez le fichier en ligne ou par URL.
Outils
function:{"type": "function", "name", "description", "parameters", "strict"}. L'appel du modèle revient sous forme d'un élémentfunction_callaveccall_id,nameetarguments(une chaîne JSON). Répondez avec un élémentfunction_call_outputportant le mêmecall_id.custom(entrée libre, commeapply_patchde Codex) : le modèle reçoit l'outil avec une seule entrée de chaîne, et la grammaire enformat.definitioncomme description. L'appel revient sous forme d'un élémentcustom_tool_callavec leinputbrut.namespace(outils MCP de Codex) : chaque outil à l'intérieur est proposé au modèle sous son espace de noms et son nom joints (mcp__github__get_issue) ; l'appel revient avecnameetnamespaceà nouveau séparés.- Outils hébergés (
web_search,file_search,code_interpreter,image_generation,computer_use,mcp) fonctionnent sur les propres serveurs d'OpenAI. Ils sont exclus de la requête et le modèle répond sans eux.
tool_choice prend "auto", "none", "required", ou
{"type": "function", "name": "…"}.
Réponse
{
"id": "resp_…",
"object": "response",
"created_at": 1793333237,
"status": "completed",
"model": "deepseek/deepseek-v4.1-flash",
"output": [
{"type": "reasoning", "id": "rs_…", "summary": [],
"content": [{"type": "reasoning_text", "text": "…"}], "encrypted_content": "ull1:…"},
{"type": "message", "id": "msg_…", "status": "completed", "role": "assistant",
"content": [{"type": "output_text", "text": "Paris.", "annotations": []}]},
{"type": "function_call", "id": "fc_…", "status": "completed",
"call_id": "call_…", "name": "get_weather", "arguments": "{\"city\":\"Paris\"}"}
],
"usage": {
"input_tokens": 43, "input_tokens_details": {"cached_tokens": 0},
"output_tokens": 23, "output_tokens_details": {"reasoning_tokens": 0},
"total_tokens": 66, "cost_usd": 0.0000184
},
"store": false
}
- Un élément
reasoningapparaît lorsque le modèle renvoie son raisonnement. Renvoyez-le dans le prochaininputtel quel :encrypted_contentcontient le raisonnement afin que les modèles qui en ont besoin au tour suivant le reçoivent. statusestincompletelorsque la réponse a atteintmax_output_tokens(incomplete_details.reason: "max_output_tokens") ou un filtre de contenu ("content_filter").usage.cost_usdcorrespond à ce qui a été facturé pour l'appel. Les réponses non-streaming le contiennent également dans l'en-têteX-UberLLM-Cost-USD, et chaque réponse aX-Request-Id, l'id de sa ligne d'Activity.- Les paramètres que vous avez envoyés (
instructions,tools,temperature,max_output_tokens…) sont renvoyés comme le fait OpenAI.
Streaming
Avec "stream": true la réponse est des événements Server-Sent, chacun avec type et un
sequence_number commençant à 0 :
response.created,response.in_progress- Pour chaque élément de sortie :
response.output_item.added, puis ses deltas, puisresponse.output_item.doneavec l'élément terminé :- texte :
response.content_part.added,response.output_text.delta…,response.output_text.done,response.content_part.done - raisonnement :
response.reasoning_text.delta…,response.reasoning_text.done - appel de fonction :
response.function_call_arguments.delta…,response.function_call_arguments.done - appel d'outil personnalisé :
response.custom_tool_call_input.done
- texte :
response.completed(ouresponse.incomplete) avec la réponse complète et sesusage, incluantcost_usd.
Pendant qu'un modèle lent démarre, : ping lignes de commentaire maintiennent la connexion ouverte.
Chaque client SSE les ignore.
Erreurs
Une requête refusée avant le démarrage du stream reçoit un statut HTTP et l'enveloppe d'erreur d'OpenAI, identique à celle des complétions de chat (401, 402 hors crédit, 404 modèle inconnu, 429 ; voir Erreurs). Si quelque chose échoue après le démarrage du stream, cela se termine par response.failed, dont le response.error contient code et message. Un stream qui s'arrête avant que le modèle n'ait terminé se termine également par response.failed, jamais par response.completed, afin que les clients réessayent au lieu de garder une demi-réponse.