API de OpenAI para desarrolladores: usa un endpoint compatible
Si tu código ya habla el formato de red de OpenAI, puedes ejecutarlo contra este endpoint alojado cambiando dos valores: la base URL y la clave. Esta página muestra los pasos exactos, con código que puedes pegar.
Actualizado

Puntos clave
- Configura la base URL en https://api.openaigatewayapi.com/v1 y el modelo en uncensored; nada más en tu código del cliente de OpenAI tiene que cambiar.
- Chat completions, streaming, llamadas a funciones y modo JSON funcionan a través de las llamadas SDK normales.
- Los límites son 8 peticiones simultáneas y 300 peticiones por minuto con una clave completa, así que implementa un reintento para 429.
- Una prueba de un clic de $0.50 no requiere tarjeta, así que puedes probar tu integración antes de pagar.
La versión corta
La mayoría de las guías sobre la API de OpenAI para desarrolladores asumen un único proveedor y una sola factura. Sin embargo, el formato de datos es simplemente JSON sobre HTTPS, y gran parte del código cliente, los frameworks y las herramientas pueden comunicarse con cualquier servidor que lo implemente. Este sitio aloja uno de esos servidores. Conservas tu SDK, cambias la URL base, sustituyes una clave de este sitio y configuras el modelo como uncensored.
Esa es toda la migración para una aplicación típica. Aquí tienes la lista de verificación, y el resto de la página completa cada paso.
- Crea una cuenta y reclama el crédito de prueba en la página de clave de API.
- Configura la base URL en
https://api.openaigatewayapi.com/v1. - Envía la clave como
Authorization: Bearer <key>. Los SDKs hacen esto por ti cuando pasasapi_key. - Usa
uncensoredcomo el ID del modelo en cada petición. - Maneja HTTP 429 con un reintento breve, como se muestra cerca del final.
Existen dos endpoints: POST /v1/chat/completions y GET /v1/models. El servicio es solo de texto. No hay generación de imágenes ni audio, ni embeddings ni ajuste fino, así que si tu aplicación llama a eso, necesitarán un proveedor diferente.
Verifica la conexión con curl
Antes de tocar tu aplicación, confirma que la clave funciona. El endpoint de modelos es la prueba más barata, porque no genera tokens.
export API_KEY="paste-your-key-here"
curl https://api.openaigatewayapi.com/v1/models \
-H "Authorization: Bearer $API_KEY" | grep -o uncensored
El grep imprime el ID del modelo uncensored si la lista lo contiene; elimina el grep para ver la lista JSON completa. Si obtienes un 401, la clave es incorrecta o le falta el prefijo Bearer. Ahora envía una solicitud real:
curl https://api.openaigatewayapi.com/v1/chat/completions \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "uncensored",
"messages": [
{"role": "system", "content": "You are a concise technical assistant."},
{"role": "user", "content": "Explain idempotency keys in two sentences."}
],
"temperature": 0.4
}'
La respuesta contiene los objetos habituales choices y usage. También incluye encabezados que vale la pena registrar: X-Request-Id para preguntas de soporte, X-Balance-USD para tu crédito restante, y los dos encabezados X-RateLimit-Limit-* que muestran los límites máximos de solicitudes y concurrencia.
Python con el paquete oficial openai
En Python solo tocas el constructor del cliente. Todo lo que sigue es el código que ya tienes.
from openai import OpenAI
client = OpenAI(
base_url="https://api.openaigatewayapi.com/v1",
api_key="paste-your-key-here",
)
resp = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": "You write short, accurate release notes."},
{"role": "user", "content": "Summarise: added retry logic, fixed timeout bug."},
],
temperature=0.5,
max_tokens=200,
)
print(resp.choices[0].message.content)
print(resp.usage.prompt_tokens, resp.usage.completion_tokens)
Lee la clave desde una variable de entorno en el código real. La muestra la codifica en duro solo para mantener el fragmento corto. max_tokens es opcional aquí; si no lo incluyes, la completación puede usar todo lo que quede de la ventana de 100.000 tokens (prompt más completación juntos). Establecerlo de todos modos es una forma económica de limitar el costo en una generación descontrolada.
Transmisión
El streaming utiliza Server-Sent Events y la misma bandera stream=True que conoces. Los números de uso llegan al final del flujo, por lo que el último fragmento puede tener una lista choices vacía.
from openai import OpenAI
client = OpenAI(base_url="https://api.openaigatewayapi.com/v1", api_key="paste-your-key-here")
stream = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "List five edge cases for a date parser."}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
if getattr(chunk, "usage", None):
print("\ntokens:", chunk.usage.total_tokens)
Un detalle importante para la planificación de capacidad. Una solicitud en streaming mantiene su slot de concurrencia hasta que finaliza el flujo, no hasta que se envía el primer token. Si un cliente abandona un flujo sin cerrarlo, ese slot permanece ocupado más tiempo del esperado.
Ejemplo en Node.js
El SDK de Node toma los mismos dos ajustes con nombres diferentes.
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.openaigatewayapi.com/v1",
apiKey: process.env.GATEWAY_KEY,
});
const completion = await client.chat.completions.create({
model: "uncensored",
messages: [
{ role: "user", content: "Write a regex that matches ISO 8601 dates, and explain it." },
],
temperature: 0.3,
});
console.log(completion.choices[0].message.content);
Si usas un framework que tiene su propia integración con OpenAI, busca un campo llamado URL base, API base o endpoint en su configuración. Pegar la misma URL allí suele ser todo lo que necesitas. Los frontends de chat, los frameworks de agentes y los complementos de editores siguen principalmente este patrón. Los parámetros de muestreo como temperature, top_p, stop, seed y las penalizaciones de frecuencia y presencia se pasan al modelo.
Llamadas a herramientas y modo JSON
Dos características determinan si un modelo se adapta a una aplicación real: llamar a tus funciones y devolver datos que puedas analizar. Ambas son compatibles.
Llamadas a funciones
Declaras herramientas con tools, fuerzas opcionalmente una elección con tool_choice y envías resultados de vuelta como mensajes con role: "tool". Las respuestas en streaming entregan tool_calls en piezas, como con el formato estándar.
import json
from openai import OpenAI
client = OpenAI(base_url="https://api.openaigatewayapi.com/v1", api_key="paste-your-key-here")
tools = [{
"type": "function",
"function": {
"name": "get_order_status",
"description": "Look up the status of an order by its ID.",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
},
},
}]
messages = [{"role": "user", "content": "Where is order A-1042?"}]
first = client.chat.completions.create(model="uncensored", messages=messages, tools=tools)
msg = first.choices[0].message
if msg.tool_calls:
call = msg.tool_calls[0]
args = json.loads(call.function.arguments)
result = {"order_id": args["order_id"], "status": "shipped"} # your real lookup here
messages.append(msg)
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})
final = client.chat.completions.create(model="uncensored", messages=messages, tools=tools)
print(final.choices[0].message.content)
Valida siempre los argumentos antes de actuar sobre ellos. El modelo produce JSON que coincide con tu esquema la mayor parte del tiempo, pero no siempre, así que trata call.function.arguments como cualquier otra entrada no fiable.
Modo JSON
Para trabajos de extracción y clasificación, solicita un objeto JSON y también indícalo en el prompt. Mencionar JSON en las instrucciones da mejores resultados que confiar solo en el parámetro.
from openai import OpenAI
import json
client = OpenAI(base_url="https://api.openaigatewayapi.com/v1", api_key="paste-your-key-here")
resp = client.chat.completions.create(
model="uncensored",
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": "Reply with JSON only: {\"sentiment\": string, \"topics\": [string]}."},
{"role": "user", "content": "The docs are clear but the rate limits caught me off guard."},
],
)
data = json.loads(resp.choices[0].message.content)
print(data)
Límites, errores y reintentos
Una clave completa permite 8 solicitudes en curso y 300 solicitudes por minuto. La clave de prueba permite 2 en curso y 60 por minuto. El cuerpo máximo de la solicitud es de 8 MB. Si superas un límite, obtienes HTTP 429 y el código de error indica cuál fue el límite excedido.
| Código de error | Significado | Qué hacer |
|---|---|---|
rate_limited | Demasiadas peticiones por minuto | Ralentiza el productor o distribuye el trabajo a lo largo del minuto |
concurrency | Demasiadas peticiones a la vez | Reduce el recuento de trabajadores a 8 o menos, o a 2 en una clave de prueba |
429 con Retry-After: 5 | Sobrecarga temporal | Espera los segundos indicados y vuelve a intentar |
Los SDKs ya reintentan algunos fallos. Añade tu propio manejo para 429 para que una ráfaga no haga estallar un trabajo por lotes:
import time
from openai import OpenAI, RateLimitError
client = OpenAI(
base_url="https://api.openaigatewayapi.com/v1",
api_key="paste-your-key-here",
max_retries=0,
)
def ask(prompt, attempts=5):
for i in range(attempts):
try:
r = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": prompt}],
)
return r.choices[0].message.content
except RateLimitError as e:
wait = float(e.response.headers.get("retry-after", 2 ** i))
time.sleep(wait)
raise RuntimeError("still rate limited after retries")
Las peticiones fallidas o rechazadas no se cobran, así que un bucle de reintento no duplica tu factura. Un semáforo dimensionado a tu límite de concurrencia es la forma más limpia de mantenerse bajo el tope en código asíncrono.
Mover una aplicación existente
Si tienes una aplicación funcional, no codifiques los nuevos valores. Pon la base URL, la clave y el nombre del modelo en variables de entorno para que puedas alternar entre entornos sin un despliegue. Eso también te permite ejecutar la misma suite de pruebas contra dos backends y comparar la salida lado a lado.
import os
from openai import OpenAI
client = OpenAI(
base_url=os.environ.get("LLM_BASE_URL", "https://api.openaigatewayapi.com/v1"),
api_key=os.environ["LLM_API_KEY"],
)
MODEL = os.environ.get("LLM_MODEL", "uncensored")
def complete(messages, **kw):
return client.chat.completions.create(model=MODEL, messages=messages, **kw)
Luego trabaja a través de una rutina de migración breve:
- Ejecuta tu conjunto de prompts existente contra el nuevo endpoint y lee las salidas tú mismo. Las comprobaciones automáticas detectan roturas de formato, no el tono.
- Comprueba que cualquier código que analice JSON aún pasa con
response_formatconfigurado, y mantén un plan de respaldo que elimine texto extraño alrededor del objeto. - Mide los conteos reales de tokens desde
usage, porque un modelo diferente tokeniza el texto de forma diferente y tus estimaciones antiguas pueden estar equivocadas. - Configura tu grupo de trabajadores a 8 o menos para que el tope de concurrencia nunca sea lo primero en fallar bajo carga.
- Despliega a una pequeña parte del tráfico, observa la tasa 429 y los registros de errores, luego amplía.
Los equipos a menudo olvidan el prompt del sistema en este proceso. Los prompts escritos para persuadir a un modelo propenso a negarse a comportarse suelen contener líneas de cautela que no son necesarias aquí y pueden saturar la salida. Lee los tuyos de nuevo y elimina lo que ya no hace nada.
Qué saber antes de cambiar
La compatibilidad cubre el formato de petición y respuesta. No hace que esto sea la API oficial de ningún fabricante de modelos. El servicio ejecuta un modelo de pesos abiertos, alojado por un proveedor independiente y ajustado para responder sin negaciones de contenido para uso adulto legal. No es un enrutador entre proveedores, así que no encontrarás un menú de otros modelos detrás de él. El contenido sexual que involucra a menores no está permitido, y ese límite no se puede cambiar.
Planifica en torno a tres diferencias prácticas con una plataforma multi-modelo grande:
- Un único modelo. El ID es
uncensored. Si tu código cambia de modelo según la tarea, simplifica eso a un único valor. - Solo texto. Elimina cualquier llamada a imágenes, audio o embeddings de la ruta que apunta a este endpoint.
- El comportamiento del prompt varía. Un modelo diferente interpreta las instrucciones de otra manera, por lo que vuelve a ejecutar tus prompts y pruebas después de cambiar. Ajusta los prompts del sistema si la salida se desvía.
Los prompts no se utilizan para el entrenamiento. Para la lista completa de parámetros, consulta la documentación de la API. Si estás estimando el gasto, la página de precios lista las tarifas por token: $0,15 por 1M de tokens de entrada y $0,50 por 1M de tokens de salida, facturados desde el crédito prepago sin suscripción. Las recargas van desde $20 hasta $500 y el crédito no caduca. Si estás sopesando una capa de proxy frente a varios servicios, la página sobre gateways LLM cubre cuándo vale la pena esa pieza móvil adicional.
Más guías
Preguntas y respuestas
¿Necesito un nuevo SDK para usar este endpoint?
No. Los SDK oficiales de OpenAI para Python y Node funcionan una vez que configures la base URL en https://api.openaigatewayapi.com/v1 y uses una clave de este sitio. Cualquier otro cliente que te permita configurar un endpoint personalizado funciona de la misma manera.
¿Qué ID de modelo debo enviar?
Usa uncensored en el campo del modelo de cada petición de chat completions. Puedes confirmarlo con una petición GET a /v1/models.
¿Puedo probarlo sin pagar?
Sí. Tras registrarte, puedes reclamar $0.50 de crédito de prueba con un clic en la página de la clave de API. No requiere tarjeta, es válido por 7 días y está limitado a uno por persona.
¿Admite embeddings o generación de imágenes?
No. La API es solo de texto y ofrece chat completions y una lista de modelos. Para embeddings o imágenes, necesitas un proveedor separado.
¿Se utilizan mis prompts para el entrenamiento?
No, los prompts no se usan para el entrenamiento.
Tu clave está a un formulario de distancia
Crea una cuenta, copia la clave, cambia la URL base. Esa es toda la configuración.