// api
Referencia de la API.
Nuestra API es compatible con OpenAI: cualquier cliente o SDK que acepte un
base URL + API key funciona sin cambios. La base
URL es https://api.nan.builders/v1 y la autenticación es vía
Bearer token. Para obtener tu key, consulta
Empezar.
Servicio enterprise de Helmcode
Si usas el servicio enterprise de Helmcode recuerda que la URL de la API es api.helmcode.com. El resto de los endpoints es idéntico.
Endpoints
Listado de los endpoints disponibles. Cada uno enlaza a su sección con
request, response y un ejemplo en curl.
Listar modelos
GET /v1/models
Chat completions
POST /v1/chat/completions
Text completions
POST /v1/completions
Embeddings
POST /v1/embeddings
Text-to-speech
POST /v1/audio/speech
Speech-to-text
POST /v1/audio/transcriptions
Responses
POST /v1/responses
Autenticación
Todas las peticiones requieren el header Authorization: Bearer <api-key>.
La key es personal e intransferible — consulta
Empezar
para obtener la tuya.
curl https://api.nan.builders/v1/models \
-H "Authorization: Bearer sk-tu-key-aqui" GET /v1/models
Devuelve la lista de modelos disponibles para tu key. Modelos publicados:
qwen3.6, gemma4, qwen3-embedding,
kokoro, whisper.
Request
Sin body. Solo el header de autenticación.
Response
{
"object": "list",
"data": [
{
"id": "qwen3.6",
"object": "model",
"created": 1677610602,
"owned_by": "openai"
}
]
} Ejemplo
curl https://api.nan.builders/v1/models \
-H "Authorization: Bearer sk-tu-key-aqui" POST /v1/chat/completions
El endpoint principal de chat. Compatible con OpenAI Chat Completions.
Modelos compatibles: qwen3.6 y gemma4.
capacidades por modelo
- qwen3.6
-
Chat, streaming, tool calling, vision (image input), reasoning
(opt-out, devuelve
reasoning_contenten el message). - gemma4
- Chat, streaming, vision (image input), reasoning (opt-in).
Request
model string · required qwen3.6ogemma4.messages array · required -
Lista de mensajes
{ role, content }.contentpuede ser string o un array de partes[{type:"text",text}, {type:"image_url",image_url:{url}}]para input multimodal. max_tokens integer · optional - Tope de tokens generados.
stream boolean · optional -
Default
false. Sitrue, la respuesta llega como SSE. tools array · optional -
Function calling estándar OpenAI:
{type:"function",function:{name,description,parameters}}. Validado solo conqwen3.6. tool_choice string | object · optional - Controla qué tool puede invocar el modelo. Estándar OpenAI.
temperature number · optional - Default
0.6. top_p number · optional - Default
0.95.
Response
Respuesta sin streaming. finish_reason puede ser stop,
length o tool_calls.
{
"id": "chatcmpl-...",
"created": 1778258163,
"model": "qwen3.6",
"object": "chat.completion",
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"role": "assistant",
"content": "...",
"reasoning_content": "..."
}
}
],
"usage": {
"completion_tokens": 20,
"prompt_tokens": 17,
"total_tokens": 37
}
}
El campo reasoning_content se incluye solo cuando se usa
qwen3.6. Es opcional ignorarlo.
Ejemplo
curl https://api.nan.builders/v1/chat/completions \
-H "Authorization: Bearer sk-tu-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.6",
"messages": [{"role": "user", "content": "Hola"}],
"max_tokens": 200
}' Streaming
Con stream: true, la respuesta se entrega como Server-Sent Events.
Cada chunk es data: {...}\n\n con el delta en
choices[0].delta.content. El stream termina con
data: [DONE].
curl https://api.nan.builders/v1/chat/completions \
-N \
-H "Authorization: Bearer sk-tu-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.6",
"messages": [{"role": "user", "content": "Cuéntame un chiste corto"}],
"stream": true
}' Tool calling
qwen3.6 soporta function calling estándar OpenAI. Cuando el
modelo decide invocar una tool, la respuesta incluye
choices[0].message.tool_calls con
{id, type:"function", function:{name, arguments}} y
finish_reason: "tool_calls".
curl https://api.nan.builders/v1/chat/completions \
-H "Authorization: Bearer sk-tu-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.6",
"messages": [{"role": "user", "content": "¿Qué tiempo hace en Madrid?"}],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Obtiene el tiempo actual de una ciudad",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
},
"required": ["city"]
}
}
}
]
}' Vision
Tanto qwen3.6 como gemma4 aceptan input multimodal.
El campo content del mensaje pasa de string a un array de partes
de tipo text y/o image_url.
curl https://api.nan.builders/v1/chat/completions \
-H "Authorization: Bearer sk-tu-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.6",
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "¿Qué hay en esta imagen?"},
{"type": "image_url", "image_url": {"url": "https://example.com/foto.jpg"}}
]
}]
}' Structured outputs
Los modelos de chat aceptan el campo response_format estándar
de OpenAI para forzar respuestas JSON válidas. Soportamos los dos modos:
- json_object
- Garantiza que la respuesta sea JSON sintácticamente válido. No impone estructura.
- json_schema
-
Restringe la salida a un JSON Schema concreto. Con
strict: trueel modelo no puede emitir campos fuera del schema.
Funciona en qwen3.6 y gemma4.
json_object
curl https://api.nan.builders/v1/chat/completions \
-H "Authorization: Bearer sk-tu-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.6",
"messages": [
{"role": "user", "content": "Devuelve un objeto user con name=Alice y age=30."}
],
"response_format": { "type": "json_object" }
}' json_schema (strict)
curl https://api.nan.builders/v1/chat/completions \
-H "Authorization: Bearer sk-tu-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.6",
"messages": [
{"role": "user", "content": "Alice, 30 años."}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "user",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer" }
},
"required": ["name", "age"],
"additionalProperties": false
}
}
}
}'
Con el SDK de openai en Python:
from openai import OpenAI
client = OpenAI(
api_key="sk-tu-key-aqui",
base_url="https://api.nan.builders/v1"
)
response = client.chat.completions.create(
model="qwen3.6",
messages=[{"role": "user", "content": "Alice, 30 años."}],
response_format={
"type": "json_schema",
"json_schema": {
"name": "user",
"strict": True,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
},
"required": ["name", "age"],
"additionalProperties": False
}
}
}
)
import json
data = json.loads(response.choices[0].message.content)
print(data["name"], data["age"]) Reasoning
Ambos modelos soportan reasoning. El toggle se controla con el campo
chat_template_kwargs.enable_thinking en el body del request.
Cuando está activo, la respuesta incluye reasoning_content en
message con la cadena de razonamiento del modelo.
- qwen3.6
- activo por defecto
- gemma4
- desactivado por defecto
curl https://api.nan.builders/v1/chat/completions \
-H "Authorization: Bearer sk-tu-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"model": "gemma4",
"messages": [{"role": "user", "content": "Qué es 2+2?"}],
"chat_template_kwargs": { "enable_thinking": true }
}'
Para desactivarlo en qwen3.6 pasa { "enable_thinking": false }.
En SDKs como openai de Python o Node, este campo va dentro de
extra_body:
from openai import OpenAI
client = OpenAI(
api_key="sk-tu-key-aqui",
base_url="https://api.nan.builders/v1"
)
response = client.chat.completions.create(
model="gemma4",
messages=[{"role": "user", "content": "Qué es 2+2?"}],
extra_body={"chat_template_kwargs": {"enable_thinking": True}}
)
print(response.choices[0].message.reasoning_content) POST /v1/completions
Endpoint legacy de OpenAI para text completion. Modelo compatible:
qwen3.6.
Request
model string · required qwen3.6.prompt string · required - El prompt a completar.
max_tokens integer · optional - Tope de tokens generados.
temperature number · optional - Default
0.6. top_p number · optional - Default
0.95. stream boolean · optional - Default
false.
Response
{
"id": "cmpl-...",
"object": "text_completion",
"created": 1778258166,
"model": "qwen3.6",
"choices": [
{
"text": "...",
"index": 0,
"finish_reason": "stop",
"logprobs": null
}
],
"usage": {
"completion_tokens": 10,
"prompt_tokens": 5,
"total_tokens": 15
}
} Ejemplo
curl https://api.nan.builders/v1/completions \
-H "Authorization: Bearer sk-tu-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.6",
"prompt": "The capital of France is",
"max_tokens": 10
}' Notas
Endpoint legacy de OpenAI. Para conversaciones, usa /v1/chat/completions.
POST /v1/embeddings
Genera embeddings vectoriales. Modelo compatible:
qwen3-embedding. Vectores de 4096 dimensiones.
Request
model string · required qwen3-embedding.input string | array · required - Texto único o array de strings a embeddear.
encoding_format string · optional -
"float"(default) o"base64".
Response
{
"object": "list",
"model": "qwen3-embedding",
"data": [
{
"object": "embedding",
"index": 0,
"embedding": [0.0210, 0.0105, -0.0204, "..."]
}
],
"usage": {
"prompt_tokens": 3,
"total_tokens": 3
}
} Ejemplo
curl https://api.nan.builders/v1/embeddings \
-H "Authorization: Bearer sk-tu-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3-embedding",
"input": ["Hola mundo", "Hello world"]
}' POST /v1/audio/speech
Sintetiza audio a partir de texto (text-to-speech). Modelo compatible:
kokoro.
Request
model string · required kokoro.input string · required - Texto a sintetizar.
voice string · required -
Voz a usar. Algunas opciones:
af_heart(English female),ef_dora(Spanish female),em_alex(Spanish male). Ver listado completo. response_format string · optional -
Formato del audio devuelto. Validados:
mp3(default),wav,flac,aac,pcm,opus. speed number · optional - Default
1.0.
Response
Archivo binario de audio en el formato pedido (sin envoltorio JSON).
Ejemplo
curl https://api.nan.builders/v1/audio/speech \
-H "Authorization: Bearer sk-tu-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"model": "kokoro",
"input": "Bienvenido a NaN.",
"voice": "ef_dora",
"response_format": "mp3"
}' \
-o speech.mp3 POST /v1/audio/transcriptions
Transcribe audio a texto (speech-to-text). Modelo compatible:
whisper. La petición es multipart/form-data.
Request
file file · required - Archivo de audio a transcribir.
model string · required whisper.language string · optional -
Código ISO-639-1 (ej.
es,en). Si no se pasa, se detecta automáticamente. response_format string · optional -
Validados:
json(default) yverbose_json. Otros valores funcionan pero devuelven el contenido envuelto en JSON; recomendamos solo estos dos. timestamp_granularities[] string · optional -
Solo con
verbose_json. Valores:word(timestamps por palabra) osegment(default). temperature number · optional - Sampling temperature.
Response
Ejemplo con response_format=verbose_json:
{
"text": "Hola, esto es una prueba.",
"language": "es",
"task": "transcribe",
"duration": 1.728,
"segments": [
{
"id": 1,
"start": 0.0,
"end": 1.4,
"text": " Hola, esto es una prueba.",
"tokens": [50365, 22637, "..."],
"avg_logprob": -0.059,
"compression_ratio": 0.806,
"no_speech_prob": 0.044,
"temperature": 0.0
}
],
"words": null
}
Si pasas timestamp_granularities[]=word, el campo words
se llena con [{word, start, end, probability}].
Ejemplo
curl https://api.nan.builders/v1/audio/transcriptions \
-H "Authorization: Bearer sk-tu-key-aqui" \
-F "model=whisper" \
-F "file=@grabacion.mp3" \
-F "language=es" \
-F "response_format=verbose_json" Limitaciones
- Tamaño máximo por request — 25 MB
- Límite de tamaño del archivo de audio.
- Audios > 2 min pueden devolver timeout 524
- Recomendamos dividir en segmentos de ≤ 2 min.
- Formatos recomendados
-
OGG/OpusyMP3— mejor compresión, misma calidad de transcripción.
POST /v1/responses
Endpoint Responses estilo OpenAI. Modelos compatibles:
qwen3.6 y gemma4.
Request
model string · required qwen3.6ogemma4.input string | array · required - Texto único o array de mensajes en formato OpenAI Responses.
max_output_tokens integer · optional -
Default
65536enqwen3.6. temperature number · optional - Default
0.6. top_p number · optional - Default
0.95. instructions string · optional - Instrucciones de sistema.
Response
El array output puede contener bloques de tipo
reasoning (solo qwen3.6) y message.
{
"id": "resp_...",
"created_at": 1778258181,
"model": "qwen3.6",
"object": "response",
"status": "completed",
"output": [
{
"id": "rs_...",
"type": "reasoning",
"summary": [],
"content": [
{ "type": "reasoning_text", "text": "..." }
]
},
{
"id": "msg_...",
"type": "message",
"role": "assistant",
"status": "completed",
"content": [
{ "type": "output_text", "text": "Hola.", "annotations": [] }
]
}
],
"usage": {
"input_tokens": 17,
"output_tokens": 118,
"total_tokens": 135
}
} Ejemplo
curl https://api.nan.builders/v1/responses \
-H "Authorization: Bearer sk-tu-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.6",
"input": "Hola, ¿cómo estás?"
}' Notas
El streaming en este endpoint actualmente entrega un único evento
response.completed al final, no chunks incrementales. Para
streaming token-a-token usa
/v1/chat/completions
con stream: true.
Errores
Los errores siguen el formato estándar de OpenAI: HTTP status no-2xx con un body JSON describiendo el problema.
{
"error": {
"message": "...",
"type": null,
"param": null,
"code": "..."
}
} códigos comunes
- 401
-
Header
Authorizationinválido o ausente. - 404
-
Modelo no existe (campo
model). - 429
-
Rate limit excedido —
rpm_limitomax_parallel_requests. - 500
- Error interno (incluye errores upstream del modelo).
- 524
- Timeout (típico con audios grandes en /v1/audio/transcriptions).
Rate limits
Aplican a todas las peticiones por API key.
rate limits por API key
- Requests / min
- 100 rpm
- Paralelo máximo
- 5 concurrentes