Responses API
POST https://api.uberllm.dev/v1/responses ofrece la Responses API de OpenAI en cada modelo de chat del catálogo. Úsala desde el OpenAI SDK (client.responses.create), Codex CLI, o cualquier aplicación con un modo "Responses". Las solicitudes pasan por el mismo enrutamiento, reintentos, límites de clave y facturación que /v1/chat/completions, y cada llamada aparece en Dashboard → Activity con su costo.
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)
Sin estado almacenado
UberLLM no guarda las respuestas para que puedas continuar más tarde. Cada respuesta tiene
"store": false, y envías la conversación completa en input en cada llamada: mensajes de usuario anteriores, los elementos de
salida del modelo y los resultados de tus herramientas. Codex CLI ya funciona de esta manera.
Estos son rechazados con un 400 (code: unsupported_parameter) que nombra el campo:
previous_response_idyconversationbackground: true- input items de tipo
item_reference - plantillas de prompt almacenadas (
prompt)
GET /v1/responses/{id} y las otras rutas de respuesta almacenada no existen.
Solicitud
| Campo | Qué sucede |
|---|---|
model |
Cualquier id de modelo de chat, alias o sufijo :floor / :nitro, como en las finalizaciones de chat. |
input |
Una string, o una lista de ítems (abajo). |
instructions |
Enviado al modelo como el mensaje del sistema. |
stream |
true para eventos enviados por el servidor. |
max_output_tokens |
El límite de salida. |
temperature, top_p, seed, stop |
Pasados al modelo. |
tools, tool_choice, parallel_tool_calls |
Ver Herramientas abajo. |
reasoning.effort |
Pasado como el esfuerzo de razonamiento del modelo (modelos que piensan). |
text.format |
text, json_object, o json_schema (salida estructurada). |
metadata |
Tus propias etiquetas, mostradas en la fila de Actividad, como en las finalizaciones de chat. |
provider, models |
Opciones de enrutamiento de UberLLM, como en las finalizaciones de chat (Modelos y enrutamiento). |
store, include, prompt_cache_key, service_tier, truncation |
Aceptados y no usados. El razonamiento cifrado siempre es devuelto. |
Ítems de entrada
| Ítem | Se convierte en |
|---|---|
message con rol user, assistant, system o developer |
Un mensaje de chat. developer se envía como system. Partes del contenido input_text, output_text, input_image (image_url: una URL https o data:) y input_file (file_data o file_url). |
function_call |
La llamada a la herramienta del asistente, mantenida en orden. |
function_call_output |
El resultado de la herramienta. Las imágenes en una salida se envían en el siguiente turno del usuario. |
custom_tool_call, custom_tool_call_output |
Una llamada a una herramienta personalizada (de formato libre), y su resultado. |
reasoning |
El razonamiento anterior del modelo, devuelto al modelo en el siguiente turno. |
web_search_call y otros registros de herramientas alojadas |
Omitidos. |
Los id son aceptados e ignorados. file_id (archivos subidos) no es compatible en
input_image / input_file: envía el archivo en línea o por URL.
Herramientas
function:{"type": "function", "name", "description", "parameters", "strict"}. La llamada del modelo regresa como un elementofunction_callconcall_id,nameyarguments(una cadena JSON). Responda con un elementofunction_call_outputque contenga el mismocall_id.custom(entrada de formato libre, comoapply_patchde Codex): al modelo se le proporciona la herramienta con una entrada de cadena, y la gramática enformat.definitioncomo su descripción. La llamada regresa como un elementocustom_tool_callcon elinputen bruto.namespace(herramientas MCP de Codex): cada herramienta interna se ofrece al modelo bajo su espacio de nombres y nombre unidos (mcp__github__get_issue); la llamada regresa connameynamespacedivididos de nuevo.- Herramientas alojadas (
web_search,file_search,code_interpreter,image_generation,computer_use,mcp) se ejecutan en los propios servidores de OpenAI. Se excluyen de la solicitud y el modelo responde sin ellas.
tool_choice acepta "auto", "none", "required", o
{"type": "function", "name": "…"}.
Respuesta
{
"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 elemento
reasoningaparece cuando el modelo devuelve su razonamiento. Envíalo de vuelta en la siguienteinputtal cual:encrypted_contentcontiene el razonamiento para que los modelos que lo necesiten en el siguiente turno lo obtengan. statusesincompletecuando la respuesta alcanzómax_output_tokens(incomplete_details.reason: "max_output_tokens") o un filtro de contenido ("content_filter").usage.cost_usdes lo que se facturó por la llamada. Las respuestas no-streaming también lo llevan en el encabezadoX-UberLLM-Cost-USD, y cada respuesta tieneX-Request-Id, el ID de su fila de Actividad.- La configuración que enviaste (
instructions,tools,temperature,max_output_tokens…) se devuelve como lo hace OpenAI.
Streaming
Con "stream": true la respuesta son eventos enviados por el servidor, cada uno con type y un
sequence_number que comienza en 0:
response.created,response.in_progress- Para cada elemento de salida:
response.output_item.added, luego sus deltas, luegoresponse.output_item.donecon el elemento terminado:- texto:
response.content_part.added,response.output_text.delta…,response.output_text.done,response.content_part.done - razonamiento:
response.reasoning_text.delta…,response.reasoning_text.done - llamada a función:
response.function_call_arguments.delta…,response.function_call_arguments.done - llamada a herramienta personalizada:
response.custom_tool_call_input.done
- texto:
response.completed(oresponse.incomplete) con la respuesta completa y suusage, incluyendocost_usd.
Mientras un modelo lento se está iniciando, : ping líneas de comentario mantienen la conexión abierta.
Cada cliente SSE las omite.
Errores
Una solicitud rechazada antes de que el stream comience recibe un estado HTTP y el sobre de error de OpenAI, el mismo que chat completions (401, 402 sin crédito, 404 modelo desconocido, 429; ver Errores). Si algo falla después de que el stream ha comenzado, termina con response.failed, cuyo response.error tiene code y message. Un stream que se detiene antes de que el modelo termine también finaliza con response.failed, nunca con response.completed, para que los clientes reintenten en lugar de quedarse con media respuesta.