Hyperouter API
Esta documentación está disponible en Markdown para asistentes de IA. Empieza en /llms.txt, u obtén /llms-full.txt para tener todas las páginas en un solo archivo. Esta página es /docs.md.
Hyperouter es una API HTTP única delante de muchos proveedores de modelos. Envías una solicitud que indica un modelo. Hyperouter elige un proveedor que pueda atenderla, le reenvía la solicitud y cobra de tu saldo el precio de lista de ese proveedor.
Todos los endpoints siguen las estructuras de solicitud y respuesta de OpenAI. Los SDK de OpenAI funcionan cuando cambias la URL base y la clave de API. Hyperouter añade algunos campos a los cuerpos de OpenAI. En esta referencia están marcados como añadidos.
| Endpoint | Finalidad | Autenticación |
|---|---|---|
GET /v1/models | Enumera los modelos que tu cuenta puede llamar. | Clave de API |
POST /v1/chat/completions | Chat completion, con streaming opcional. | Clave de API |
POST /v1/images/generations | De texto a imagen. | Clave de API |
POST /v1/images/edits | Edita imágenes. | Clave de API |
POST /v1/videos | Crea un vídeo a partir de un prompt, con una imagen opcional. | Clave de API |
POST /v1/videos/edits | Edita o escala un vídeo. | Clave de API |
POST /v1/videos/extensions | Extiende un vídeo. | Clave de API |
POST /v1/videos/{id}/remix | Crea una nueva versión de un vídeo con un nuevo prompt. | Clave de API |
GET /v1/videos, GET /v1/videos/{id}, GET /v1/videos/{id}/content, DELETE /v1/videos/{id} | Lista, consulta, descarga y elimina vídeos. | Clave de API |
GET /v1/generations/{id} | Consulta el registro de cualquier solicitud: estado, consumo y cargo. | Clave de API |
GET /v1/credits | Tu saldo, lo que retienen las solicitudes abiertas y lo que te queda por gastar (balance_usd, held_usd, available_usd, cadenas decimales en USD). | Clave de API |
Inicia sesión en dash.hyperouter.app con Google o GitHub para crear una clave de API. GET /v1/models devuelve los modelos que puedes llamar en el momento de la solicitud.
Inicio rápido
- Inicia sesión y crea una clave de API. Las claves empiezan por
sk-hr-v1-y se muestran una sola vez. - Guárdala en una variable de entorno, por ejemplo
HYPEROUTER_API_KEY. - Añade crédito: abre una solicitud de recarga en el panel. El equipo acredita tu saldo cuando se confirma el pago.
- Apunta cualquier SDK de OpenAI a la URL base anterior y elige un modelo.
curl https://api.hyperouter.app/v1/chat/completions \ -H "Authorization: Bearer $HYPEROUTER_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "x-ai/grok-4.7", "messages": [{"role": "user", "content": "Hello"}] }'
import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://api.hyperouter.app/v1", apiKey: process.env.HYPEROUTER_API_KEY, }); const res = await client.chat.completions.create({ model: "x-ai/grok-4.7", messages: [{ role: "user", content: "Hello" }], }); console.log(res.choices[0].message.content);
import os from openai import OpenAI client = OpenAI( base_url="https://api.hyperouter.app/v1", api_key=os.environ["HYPEROUTER_API_KEY"], ) res = client.chat.completions.create( model="x-ai/grok-4.7", messages=[{"role": "user", "content": "Hello"}], ) print(res.choices[0].message.content)
Autenticación
Envía tu clave de API como token bearer en cada solicitud.
Authorization: Bearer sk-hr-v1-...
Las claves dan acceso a tu saldo. Guárdalas en tu servidor. Nunca las pongas en código de navegador ni de móvil. Hyperouter guarda solo un hash de cada clave, así que una clave perdida no se puede volver a mostrar: crea una nueva.
En el panel puedes ponerle nombre a cada clave, asignarle un límite de crédito y desactivarla. Una clave desactivada deja de funcionar al instante. Una solicitud que llevaría a una clave más allá de su límite se rechaza con 402 insufficient_credits.
Errores de autenticación
| Estado | type | code | Cuándo | message |
|---|---|---|---|---|
401 | authentication_error | invalid_api_key | Falta el encabezado, no es Bearer, o la clave no empieza por sk-hr-v1-. | The API key is missing or malformed. Send Authorization: Bearer sk-hr-v1-… |
401 | authentication_error | invalid_api_key | La clave es desconocida o está desactivada. | The API key is not valid. |
403 | permission_error | account_suspended | La cuenta está suspendida. La comprobación se hace en cada solicitud. | This account is suspended. Open a support ticket. |
429 | rate_limit_error | too_many_auth_failures | Más de 30 solicitudes desde tu dirección en un minuto usaron una clave ausente o no válida. Todas las solicitudes a /v1 desde esa dirección se rechazan durante 15 minutos, incluso con una clave válida. Retry-After indica los segundos restantes. | Too many failed API key checks from this address. Try again after the time in Retry-After. |
500 | server_error | internal | Hyperouter no pudo comprobar la clave. | An internal error occurred. Try again. |
curl https://api.hyperouter.app/v1/generations/0194f2c4-7a1e-7b3c-9d02-5f6a1c0e8b21 \
-H "Authorization: Bearer $HYPEROUTER_API_KEY"
{ "error": { "message": "The API key is not valid.", "type": "authentication_error", "code": "invalid_api_key", "param": null } }
Errores
Todos los errores usan el objeto de error de OpenAI y un estado HTTP correspondiente.
{
"error": {
"message": "n must be an integer from 1 to 128",
"type": "invalid_request_error",
"code": "invalid_body",
"param": "n"
}
}
| Campo | Tipo | Descripción |
|---|---|---|
message | string | Una frase que dice qué falla. No la analices programáticamente. |
type | string | La clase de error. Consulta la lista siguiente. |
code | string | Un identificador estable de la causa. Compara por este campo. |
param | string | null | El campo de la solicitud que causa el error, o null. |
Tipos y estados
| Estado | type | Significado |
|---|---|---|
400 | invalid_request_error | La solicitud no es válida. code indica la causa y param el campo. |
401 | authentication_error | La clave de API falta o no es válida. |
402 | insufficient_credits | Tu saldo, o el límite de la clave, no cubre lo máximo que podría costar la solicitud. |
403 | permission_error | La cuenta está suspendida. |
404 | not_found | El id no existe, pertenece a otra cuenta, o un vídeo ha superado su expires_at. |
409 | conflict | El objeto no está en un estado que permita la llamada (video_not_finished), o hay un conflicto de Idempotency-Key (consulta Reintentos e idempotencia). |
422 | invalid_request_error | La solicitud era válida, pero su respuesta se rechazó (expansion_refused). No se factura. |
429 | rate_limit_error | Todos los proveedores del modelo están al límite de su capacidad, tu cuenta supera sus límites de velocidad, o han fallado demasiadas comprobaciones de clave de API desde tu dirección. Reintenta después del tiempo indicado en el encabezado Retry-After. |
500, 501 | server_error | Hyperouter ha fallado, o el endpoint no está implementado. No se factura. |
503 | upstream_error | Un proveedor falló o no respondió a tiempo: code indica cuál (all_venues_failed, upstream_error o timeout). El encabezado X-Upstream-Status contiene 502 (fallo) o 504 (tiempo agotado). |
Hyperouter nunca responde 502 ni 504: te llegarían como una página simple de nuestra red perimetral, sin el cuerpo del error. Donde una pasarela respondería con ellos, recibes 503 con el cuerpo de más arriba y el estado de la pasarela en X-Upstream-Status.
Códigos que puedes recibir
| code | Estado | Cuándo |
|---|---|---|
invalid_body | 400 | Un campo del cuerpo o un parámetro de consulta no se puede analizar, tiene el tipo equivocado o está fuera de sus valores permitidos. param lo nombra. |
unsupported_content_type | 400 | /v1/images/generations recibió un cuerpo multipart/form-data. Envía JSON. param es null. |
request_too_large | 413 | Una subida multipart/form-data supera los 50 MiB. Envía los medios grandes como URL https. |
unknown_model | 400 | El modelo no existe para este endpoint, o ningún proveedor puede atenderlo con tus preferencias de provider. |
unsupported_parameter | 400 | Un parámetro que existe para otros modelos no está disponible en este modelo. Consulta Parámetros específicos de cada modelo. |
invalid_combination | 400 | El proveedor no permite estos parámetros juntos, por ejemplo medios de referencia con fotogramas clave. |
invalid_size | 400 | size no es WIDTHxHEIGHT, o no está permitido para el modelo. |
too_many_images | 400 | n o el número de imágenes de entrada supera el límite. |
invalid_image, invalid_video | 400 | La URL de una imagen o un vídeo no es https a un host público: una URL data:, una URL http://, una dirección IP o un nombre interno. param nombra el campo. |
image_required | 400 | El modelo necesita una imagen de entrada y no enviaste ninguna (o solo edita y llamaste a generations). |
invalid_seconds | 400 | seconds no está permitido para el modelo, o falta en un vídeo indicado por URL. |
unsupported_operation | 400 | El modelo no admite la operación (editar, extender o remix, o edición de imágenes). |
video_not_ready | 400 | El vídeo de origen no ha terminado. |
context_length_exceeded | 400 | El prompt del chat y max_tokens no caben en el contexto del modelo. |
content_rejected | 400 | El filtro de seguridad del proveedor rechazó la entrada. |
vendor_rejected | 400 | El modelo rechazó la solicitud por no ser válida. Revisa sus parámetros y entradas. |
clip_too_long | 400 | Un clip de referencia más los seconds solicitados superan el límite del modelo (30 s). No se factura. |
prompt_rejected | 400 | El prompt pide al modelo de expansión del prompt sus instrucciones. No se factura. Consulta Expansión del prompt. |
expansion_refused | 422 | La reescritura del modelo de expansión del prompt se rechazó o llegó vacía. No se factura. Consulta Expansión del prompt. |
invalid_api_key | 401 | Consulta Autenticación. |
insufficient_credits | 402 | Consulta Facturación y límites. |
account_suspended | 403 | La cuenta está suspendida. |
moderation_not_enabled | 403 | moderation: "low" no está habilitado para la cuenta. Consulta Moderación. |
feature_not_enabled | 403 | prompt_expand no está habilitado para la cuenta, en un modelo que lo ofrece. Abre un ticket de soporte para solicitar el acceso. No se retiene nada ni se envía al proveedor. Consulta Expansión del prompt. |
model_not_enabled | 403 | El modelo requiere que se conceda acceso a tu cuenta. Abre un ticket de soporte para solicitarlo. No se retiene nada ni se envía nada al proveedor. |
not_found | 404 | El objeto no existe. |
video_not_finished | 409 | Eliminaste un vídeo que todavía se está creando. |
venue_busy | 429 | Todos los proveedores del modelo de chat superan su presupuesto de velocidad. |
rate_limited | 429 | Tu cuenta supera sus solicitudes por minuto o sus solicitudes concurrentes. Consulta Límites de velocidad. |
too_many_auth_failures | 429 | Más de 30 solicitudes desde tu dirección en un minuto usaron una clave de API no válida. Consulta Límites de velocidad. |
all_venues_failed | 503 | Ningún proveedor está disponible, o todos han fallado. |
upstream_error | 503 | Un trabajo de imagen o vídeo falló en el modelo. No se te cobra. |
internal, server_error, no_price | 500 | Hyperouter ha fallado (no_price: el modelo no se puede valorar ahora). No se factura. |
not_implemented | 501 | This endpoint is not implemented yet. |
invalid_idempotency_key | 400 | El encabezado Idempotency-Key supera los 255 caracteres o no es ASCII imprimible. Consulta Reintentos e idempotencia. |
idempotency_key_reused | 409 | La Idempotency-Key ya se usó con una solicitud distinta. |
idempotency_key_in_use | 409 | Una solicitud con esta Idempotency-Key todavía se está iniciando. Reintenta con la misma clave. |
idempotency_key_replayed | 409 | Un chat completion con esta Idempotency-Key ya se ejecutó. error.generation_id es su id. |
timeout | 503 | Una imagen síncrona no estuvo lista en 90 segundos. Todavía se está creando: error.generation_id es el id que debes consultar. |
Reintentos e idempotencia
Un error de red o un tiempo de espera agotado no te dice si Hyperouter recibió la solicitud. Si la vuelves a enviar, puedes iniciar un segundo trabajo y pagar dos veces. Una Idempotency-Key hace segura la repetición: Hyperouter reconoce la repetición, no inicia un segundo trabajo, no hace una segunda retención y responde a partir de la primera solicitud.
Envía una en cada solicitud que cueste dinero. Genera un valor aleatorio nuevo, como un UUID v4, para cada solicitud nueva. Guárdalo junto con la solicitud y envía el mismo valor cada vez que repitas esa solicitud.
Enviar una clave
El encabezado se acepta en estos endpoints:
| Endpoint | Una repetición devuelve |
|---|---|
POST /v1/images/generations, POST /v1/images/edits | la imagen de la primera solicitud, o su 202 con el mismo id bajo Prefer: respond-async |
POST /v1/videos, /v1/videos/edits, /v1/videos/extensions, /v1/videos/{id}/remix | el objeto Video de la primera solicitud, tal como está ahora |
POST /v1/chat/completions | 409 idempotency_key_replayed con el id de la primera solicitud (consulta Chat completions) |
Los SDK de OpenAI no envían este encabezado por su cuenta. Pásalo como encabezado adicional; los SDK lo reenvían sin cambios en sus reintentos automáticos.
curl https://api.hyperouter.app/v1/images/generations \ -H "Authorization: Bearer $HYPEROUTER_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7" \ -d '{"model": "x-ai/grok-imagine-image", "prompt": "A lighthouse at dusk", "n": 1}'
import uuid key = str(uuid.uuid4()) # one per request; reuse it when you retry this request img = client.images.generate( model="x-ai/grok-imagine-image", prompt="A lighthouse at dusk", extra_headers={"Idempotency-Key": key}, )
import { randomUUID } from "node:crypto"; const key = randomUUID(); // one per request; reuse it when you retry this request const img = await client.images.generate( { model: "x-ai/grok-imagine-image", prompt: "A lighthouse at dusk" }, { headers: { "Idempotency-Key": key } }, );
Qué devuelve una repetición
| Envías | Hyperouter responde |
|---|---|
| Una clave nueva | Ejecuta la solicitud con normalidad. |
| La misma clave y la misma solicitud, después de que la primera fuera aceptada | El resultado de la primera solicitud, como en la tabla anterior. Ni segundo trabajo, ni segunda retención, ni segundo cargo. |
| La misma clave y la misma solicitud, mientras la primera todavía se está aceptando | Espera a la primera y luego responde como arriba. Si la primera no ha iniciado su trabajo en 60 segundos: 409 idempotency_key_in_use. Reintenta con la misma clave. |
| La misma clave y una solicitud distinta | 409 idempotency_key_reused. No se ejecuta nada. Usa una clave nueva. |
La misma clave, después de que la primera fuera rechazada antes de iniciar ningún trabajo (un 400, un 402 o un 5xx enviado sin x-should-retry: false) | Ejecuta la solicitud como nueva, para que puedas corregirla y volver a enviarla con la misma clave. |
| La misma clave, más de 30 minutos después de la primera solicitud | Ejecuta la solicitud como nueva. |
| Una clave de más de 255 caracteres, o que no sea ASCII imprimible | 400 invalid_idempotency_key. No se ejecuta nada. |
Reglas
- Ámbito. Una clave pertenece a la clave de API que la envió. Dos claves de API pueden usar el mismo valor sin afectarse entre sí.
- Ventana. Una clave se respeta durante 30 minutos después de la primera solicitud. Reintenta dentro de ese plazo.
- Misma solicitud. Dos solicitudes son la misma cuando coinciden el método, la ruta y el cuerpo. El JSON se compara después de analizarlo, así que el orden de los campos y los espacios no importan. Una imagen o un vídeo es una URL en el cuerpo, así que se compara la URL, nunca los bytes que sirve.
- Facturación. Una solicitud hecha con una clave se factura como máximo una vez, sea cual sea el número de repeticiones. Una repetición respondida a partir de la primera solicitud no cuesta nada.
- Garantía. Una clave nunca inicia más de un trabajo, tampoco cuando dos repeticiones llegan al mismo tiempo.
Chat completions
Las respuestas de chat no se reproducen. Una repetición con la misma clave responde 409 con el código idempotency_key_replayed, y error.generation_id es el id de la primera solicitud. La solicitud no se vuelve a ejecutar ni a facturar. Consulta la primera solicitud con GET /v1/generations/{id} para ver su estado, consumo y coste. Si el primer chat completion falló y no se facturó, su clave queda libre y una repetición se ejecuta como solicitud nueva.
{
"error": {
"message": "A request with this Idempotency-Key already ran as generation 019a1f3c-5b7e-7d21-9c4a-2e8f6b0d3a17. Chat replies are not replayed: GET /v1/generations/019a1f3c-5b7e-7d21-9c4a-2e8f6b0d3a17 for its record.",
"type": "conflict",
"code": "idempotency_key_replayed",
"param": null,
"generation_id": "019a1f3c-5b7e-7d21-9c4a-2e8f6b0d3a17"
}
}
Reintentos automáticos en los SDK de OpenAI
Los SDK de OpenAI reintentan dos veces, por defecto, una respuesta 408, 409, 429 o 5xx, salvo que la respuesta incluya el encabezado x-should-retry: false. Hyperouter envía x-should-retry: false en toda respuesta en la que un reintento iniciaría un segundo trabajo o un segundo cargo:
- el
503timeoutde una imagen síncrona, cuyo trabajo continúa y se factura si tiene éxito; consulta GET /v1/generations/{id} con sugeneration_id; - un
500después de crear el trabajo, por ejemplo cuando no se puede volver a leer una imagen terminada; 409idempotency_key_reusedeidempotency_key_replayed, que un reintento no puede cambiar.
Nunca lo envía en un 429, en un 409 idempotency_key_in_use ni en un 5xx anterior a que exista cualquier trabajo. Esos son seguros de reintentar. Con una Idempotency-Key, todos los reintentos son seguros.
Modelos
Enumera todos los modelos que tu cuenta puede llamar ahora mismo, con sus precios y lo que admiten. Un modelo sin un proveedor habilitado no aparece. Algunos modelos requieren que se conceda acceso a tu cuenta: aparecen una vez concedido. Este endpoint necesita una clave de API y enumera los modelos que puede llamar la cuenta de esa clave. La respuesta puede almacenarse en caché durante 60 segundos, solo por tu cliente.
Parámetros
Ninguno.
Respuesta
{
"data": [{
"id": "x-ai/grok-4.7",
"name": "Grok 4.7",
"kind": "chat",
"context_length": 500000,
"architecture": { "input_modalities": ["text", "image"], "output_modalities": ["text"] },
"pricing": {
"prompt": "0.000002", "completion": "0.000006", "input_cache_read": "0.0000005",
"request": "0", "image": "0", "video_second": "0"
},
"top_provider": { "context_length": 500000, "max_completion_tokens": 32768 },
"response_modes": ["sync", "stream"],
"supported_parameters": ["max_tokens", "temperature", "top_p", "stop", "stream", "tools", "tool_choice", "response_format", "seed", "frequency_penalty", "presence_penalty"],
"extra_parameters": {}
}]
}
| Campo | Tipo | Descripción |
|---|---|---|
id | string | El id del modelo, <provider>/<name>, por ejemplo x-ai/grok-4.7 o qwen/qwen-image-2.0. Envíalo como model. Un modelo renombrado sigue respondiendo a su id anterior. |
response_modes | string[] | Cómo responde el modelo: sync (una respuesta retenida), async (envía Prefer: respond-async, recibe 202 y consulta periódicamente) y stream ("stream": true). Un modelo que solo lista async necesita el encabezado Prefer, y stream solo funciona donde aparece listado. El vídeo es siempre asíncrono a través de la API de vídeos, con o sin el encabezado. |
name | string | Nombre para mostrar. |
kind | string | chat, image o video. |
context_length | integer | Ventana de contexto en tokens. 0 para modelos de imagen y vídeo. |
architecture | object | input_modalities y output_modalities. La salida es ["text"], ["image"] o ["video"]. |
pricing | object of strings | USD por unidad, como cadenas decimales, en el nivel base: prompt y completion (por token), input_cache_read (por token en caché), request, image (por imagen), video_second (por segundo de vídeo). Un vídeo con precio según la resolución muestra el precio más bajo. Una unidad que no se aplica es "0". |
top_provider | object | context_length y max_completion_tokens. |
supported_parameters | string[] | En chat, los parámetros de OpenAI que admite el modelo. En imagen y vídeo, las funciones compartidas que admite (resolution, ratio, audio, seed, negative_prompt, first_frame, last_frame, reference_images, reference_videos, prompt_extend). |
operations | string[] | Solo en modelos de vídeo: edit, extend y remix, para cada una que el modelo admita. Ausente cuando el modelo no admite ninguna. |
extra_parameters | object | Los campos de primer nivel específicos del modelo, por nombre. Cada uno tiene type, values (valores permitidos; vacío significa cualquiera), price_condition (el campo cambia el precio) y description. Consulta Parámetros específicos de cada modelo. |
curl https://api.hyperouter.app/v1/models \
-H "Authorization: Bearer $HYPEROUTER_API_KEY"
Errores
Ninguno específico de este endpoint.
Modelos de chat
Precios por 1 M de tokens: entrada / entrada en caché / salida.
| Modelo | Contexto | Precio |
|---|---|---|
x-ai/grok-4.7 | 500K | $2.00 / $0.50 / $6.00 |
x-ai/grok-4.6 | 500K | $2.00 / $0.50 / $6.00 |
x-ai/grok-4.5 | 500K | $2.00 / $0.30 / $6.00 |
x-ai/grok-4.3 | 1M | $1.25 / $0.20 / $2.50 |
x-ai/grok-build-0.1 | 256K | $1.00 / $0.20 / $2.00 |
deepseek/deepseek-v4.1-flash | 1M | $0.15 / $0.003 / $0.60 |
deepseek/deepseek-v4.1-flash-1017 | 1M | $0.15 / $0.003 / $0.60 |
openai/gpt-6-astra | 272K | $10.00 / $1.00 / $50.00 |
openai/gpt-6.1-sol | 272K | $2.00 / $0.10 / $10.00 |
z-ai/glm-5.3 | 1M | $1.40 / $0.26 / $4.40 |
lumina/face-detect | 4K | $0.0013 por solicitud |
En los modelos x-ai/, una solicitud con 200 000 tokens de prompt o más se factura por completo con las tarifas de contexto largo, que son el doble de las anteriores. Los modelos deepseek/ tienen una única tarifa para cualquier longitud de prompt, razonan antes de responder por defecto (reasoning_effort: "none" lo desactiva) y cuentan su razonamiento dentro de max_tokens, con un máximo de 384 000. z-ai/glm-5.3 siempre razona: reasoning_effort es low, high o max, y none se rechaza. Los modelos openai/ también razonan y aceptan prompts de 272 000 tokens como máximo.
Chat completions
Crea la respuesta de un modelo a una conversación. El cuerpo es la solicitud de Chat Completions de OpenAI. Hyperouter añade models, provider y moderation.
Parámetros
| Nombre | Tipo | Obligatorio | Valores permitidos | Por defecto | Descripción |
|---|---|---|---|---|---|
model | string | Sí | Un id de modelo de chat de GET /v1/models | El modelo que se usará, por ejemplo x-ai/grok-4.7. | |
messages | object[] | Sí | No vacío. Roles system, user, assistant, tool | La conversación hasta ahora. Se aceptan imágenes (partes image_url) cuando el modelo admite imágenes. | |
models | string[] | No | Como máximo 5 ids de modelo | Añadido. Modelos de reserva, probados en orden después de que fallen todos los proveedores de model. | |
provider | object | No | Ver más abajo | Añadido. Preferencias de enrutamiento. | |
moderation | string | No | auto, low | auto | Añadido. Consulta Moderación. |
stream | boolean | No | false | Devuelve eventos enviados por el servidor. | |
stream_options | object | No | {"include_usage": true} | Con include_usage, el stream termina con un fragmento que incluye usage. | |
max_tokens, max_completion_tokens | integer | No | 1 o más | El máximo de salida del modelo | Límite superior de tokens generados. También fija lo máximo que puede costar una solicitud, que Hyperouter retiene antes de la llamada (consulta Facturación). |
n | integer | No | De 1 a 128 | 1 | Número de opciones. |
temperature, top_p, seed, frequency_penalty, presence_penalty, logit_bias | number / integer / object | No | Como en OpenAI | Controles de muestreo, pasados al proveedor. | |
stop | string | string[] | No | Secuencias que terminan la generación. | ||
tools, tool_choice, parallel_tool_calls | object[], string | object, boolean | No | Formato de function calling de OpenAI | Function calling. Solo herramientas de tipo function: cualquier otro tipo se rechaza con 400 unsupported_parameter. | |
response_format | object | No | {"type":"json_object"} o un esquema JSON | Salida estructurada. | |
reasoning_effort, logprobs, top_logprobs, user | como en OpenAI | No | Se pasan al proveedor cuando el modelo los admite. |
Los demás campos se ignoran. supported_parameters de cada modelo en GET /v1/models enumera exactamente lo que admite. Grok 4.20 y posteriores ignoran logprobs y top_logprobs, por lo que no aparecen en la lista.
El objeto provider
Por defecto, Hyperouter envía cada solicitud de chat al proveedor disponible con el precio más bajo para ese modelo, y desempata por el menor tiempo reciente hasta el primer token. Un proveedor que falla repetidamente se omite hasta que se recupera. El objeto provider sigue la estructura de solicitud de OpenRouter.
| Nombre | Tipo | Obligatorio | Valores permitidos | Por defecto | Descripción |
|---|---|---|---|---|---|
sort | string | No | price, latency, throughput | price | Cómo ordenar los proveedores. |
order | string[] | No | Nombres de proveedores | Proveedores que se probarán primero, en orden, por ejemplo ["xai"]. El nombre de un proveedor es su nombre público en cualquier capitalización (xAI, Qwen) o la primera parte de sus ids de modelo (x-ai, qwen). | |
only | string[] | No | Nombres de proveedores | Enruta solo a estos proveedores. | |
ignore | string[] | No | Nombres de proveedores | No enruta nunca a estos proveedores. |
Respuesta
El chat completion de OpenAI. El id es el id de la solicitud: consúltalo con GET /v1/generations/{id}. Hyperouter añade provider (el nombre público del proveedor que atendió la solicitud, por ejemplo xAI) y usage.cost (el cargo, en USD, como número JSON).
{
"id": "0194f2c4-7a1e-7b3c-9d02-5f6a1c0e8b21",
"object": "chat.completion",
"model": "x-ai/grok-4.7",
"provider": "xAI",
"choices": [{
"index": 0,
"message": { "role": "assistant", "content": "Hello! How can I help?" },
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 9,
"completion_tokens": 8,
"total_tokens": 17,
"prompt_tokens_details": { "cached_tokens": 0 },
"cost": 0.000066
}
}
Un modelo de reescritura de prompts responde con una opción, un usage de cero tokens y un cost fijo por solicitud.
Streaming
Con "stream": true la respuesta es un flujo de eventos enviados por el servidor en el formato de fragmentos de OpenAI. Termina con data: [DONE]. Cuando defines stream_options.include_usage, el último fragmento antes de [DONE] tiene un array choices vacío y un objeto usage que incluye cost, además de un campo provider. El consumo siempre se registra para la facturación, pidas o no el fragmento.
Hasta que llega el primer token, el stream envía la línea de comentario : processing cada 15 segundos para mantener abierta la conexión. Los clientes SSE ignoran los comentarios.
La conmutación a otro proveedor solo ocurre antes de enviar el primer token. Si un proveedor falla a mitad del stream, este termina con data: {"error": {...}} seguido de data: [DONE], y se te facturan los tokens ya producidos.
Se te facturan los tokens que produce el proveedor, los leas o no. Un stream que abortas, o una respuesta que dejas de esperar, no se detiene en el proveedor, que continúa y factura toda su respuesta: Hyperouter la lee hasta el final (durante 5 minutos más como máximo) y factura eso.
Un proveedor que ha aceptado una solicitud puede estar ejecutándola. Si luego deja de responder (5 minutos sin ningún token en un stream, o más de lo que tarda una respuesta de max_tokens) o su respuesta se corta antes del primer token, la solicitud no se envía a otro proveedor: responde 503 con el código timeout o upstream_error con error.generation_id, y se factura según su retención, con usage_estimated: true en su registro.
Ejemplo
curl https://api.hyperouter.app/v1/chat/completions \
-H "Authorization: Bearer $HYPEROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "x-ai/grok-4.7",
"models": ["x-ai/grok-4.6"],
"provider": { "sort": "latency" },
"messages": [{ "role": "user", "content": "Hello" }]
}'
Errores
| Estado | type | code | param | Cuándo |
|---|---|---|---|---|
400 | invalid_request_error | invalid_body | el campo | El cuerpo no es JSON válido o supera los 32 MiB; falta model; models tiene más de 5 entradas; n está fuera del rango de 1 a 128; max_tokens no es positivo; provider.sort no está permitido; moderation no es auto ni low (moderation must be auto or low.); messages está vacío. También cuando todos los proveedores rechazaron la solicitud por no ser válida. |
400 | invalid_request_error | unknown_model | model o models | El modelo no es un modelo de chat, o no tiene un proveedor habilitado. |
400 | invalid_request_error | unsupported_parameter | tools, response_format, messages o max_tokens | El modelo no admite herramientas, un formato de respuesta ni imágenes; una herramienta no es de tipo function; o ningún proveedor del modelo puede acotar su salida. |
400 | invalid_request_error | context_length_exceeded | messages | El prompt y max_tokens superan el contexto del modelo. |
402 | insufficient_credits | insufficient_credits | max_tokens | El saldo o el límite de la clave no cubre lo máximo que podría costar la solicitud. El mensaje indica cuántos tokens puedes permitirte. |
429 | rate_limit_error | venue_busy | Todos los proveedores del modelo superan su presupuesto de velocidad. | |
429 | rate_limit_error | rate_limited | Tu cuenta supera sus solicitudes por minuto o sus solicitudes concurrentes (consulta Límites de velocidad). No se retiene ni se reenvía nada. | |
409 | conflict | idempotency_key_replayed, idempotency_key_reused, idempotency_key_in_use | Consulta Reintentos e idempotencia. | |
503 | upstream_error | all_venues_failed | Ningún proveedor está disponible, o todos han fallado. No se factura. | |
503 | upstream_error | upstream_error | El proveedor aceptó la solicitud y su respuesta se cortó antes del primer token. Se factura según la retención (consulta Streaming). | |
503 | upstream_error | timeout | El proveedor aceptó la solicitud y no la terminó a tiempo. Se factura según la retención (consulta Streaming). | |
401, 403, 500 | Consulta Autenticación. | |||
Imágenes
Ambos siguen la API de imágenes de OpenAI y aceptan un cuerpo JSON. /v1/images/edits acepta la forma JSON de OpenAI: las imágenes son images, de 1 a 5 URL https. El images.edit de los SDK de OpenAI envía los archivos de imagen como multipart/form-data, y eso también funciona: el edge de Hyperouter guarda cada archivo (PNG, JPEG o WebP, 20 MiB cada uno, 50 MiB por solicitud) durante 3 días en una URL https://api.hyperouter.app/u/... imposible de adivinar que el proveedor descarga, y luego ejecuta la solicitud como JSON. Un archivo de vídeo se rechaza (400 invalid_video): envía un vídeo como URL https. Ambos aceptan las funciones compartidas que siguen y cualquier parámetro específico del modelo como campos de primer nivel.
Parámetros
| Nombre | Tipo | Obligatorio | Valores permitidos | Por defecto | Descripción |
|---|---|---|---|---|---|
model | string | Sí | Un id de modelo de imagen | El modelo que se usará. | |
prompt | string | Generations: sí. Edits: según lo que necesite el modelo | Texto no vacío | Qué crear. | |
images | object[] | Edits: sí | De 1 a 5 objetos {"image_url": "https://..."}, tantos como admita el modelo. Cada URL es https a un host público, nunca una URL data:, una dirección IP ni un nombre interno. No se acepta file_id. | Las imágenes que se editarán. Cada URL se pasa al proveedor tal cual, por lo que el proveedor debe poder descargarla; si no puede descargarla o leerla, el trabajo falla con vendor_rejected y no se cobra nada. Un modelo que las acepta en un orden determinado lo indica en sus notas de la referencia de modelos. | |
n | integer | No | De 1 a 10, y como máximo el límite del modelo | 1 | Número de imágenes. |
size | string | No | WIDTHxHEIGHT, por ejemplo 1024x1024; el modelo puede permitir menos tamaños | 1024x1024 | Tamaño de salida. |
quality | string | No | Según lo que permita el modelo | Se pasa al modelo. | |
response_format | string | No | url | url | Cómo se devuelve la imagen: siempre como URL. b64_json se rechaza con 400 unsupported_parameter. |
seed | integer | No | Si el modelo lista seed | Semilla para una salida repetible. | |
negative_prompt | string | No | Si el modelo lo lista | Qué evitar. | |
prompt_extend | boolean | No | Si el modelo lo lista | Desactivado salvo que lo pidas | Permite que el modelo amplíe el prompt. |
prompt_expand | boolean | No | Si el modelo lo lista | false | Añadido. Hyperouter reescribe el prompt para el modelo antes de generar. Consulta Expansión del prompt. |
prompt_expand_model | string | No | El slug de un modelo de chat que tu cuenta puede llamar | x-ai/grok-4.6 | Añadido. Con prompt_expand: el modelo que escribe la reescritura. Sin prompt_expand: true es 400 invalid_body. Consulta Expansión del prompt. |
locale | string | No | Una etiqueta BCP 47, por ejemplo zh-CN | Inglés | Añadido. Con prompt_expand: el idioma de los diálogos, si el modelo lo habla. |
ratio | string | No | Si el modelo lo lista | Relación de aspecto. | |
resolution | string | No | 480p, 720p, 1080p, 2K, 4K, según lo que permita el modelo | Resolución de salida. | |
models | string[] | No | Ids de modelos de imagen | Añadido. Modelos de reserva. | |
provider | object | No | only, ignore, order (arrays de nombres de proveedores) | Añadido. Preferencias de enrutamiento. | |
moderation | string | No | auto, low | auto | Añadido. Consulta Moderación. |
| campos específicos del modelo | según se declare | Según se declare | Según se declare | Consulta Parámetros específicos de cada modelo. |
Una función compartida que el modelo no lista, como seed en un modelo que no la tiene, se rechaza con 400 unsupported_parameter. Nunca se descarta en silencio, porque cambiaría la salida y el precio.
Respuesta
{
"created": 1730000000,
"data": [{ "url": "https://..." }],
"usage": { "cost": 0.02 },
"id": "0194f2c4-7a1e-7b3c-9d02-5f6a1c0e8b21"
}
| Campo | Tipo | Descripción |
|---|---|---|
created | integer | Hora Unix de la solicitud. |
data[].url | string | Con response_format: "url": un enlace firmado, válido durante 24 horas. GET /v1/generations/{id} firma uno nuevo. |
usage.cost | number | El cargo en USD, como número JSON. |
id | string | El id de la solicitud. Úsalo con GET /v1/generations/{id}. |
expanded_prompt | string | null | Añadido. Con prompt_expand: el prompt con el que se generó. null si no se reescribió nada. |
Hyperouter almacena cada resultado durante 30 días, de modo que un enlace nunca apunta a un proveedor. Pasados los 30 días el registro permanece, pero su outputs queda vacío.
Esperar el resultado
- En un modelo cuyos
response_modesincluyensync, la solicitud espera la imagen hasta 90 segundos y responde con su estado real:200con las imágenes, o el error. Los errores de validación, saldo y capacidad van primero, con su propio estado. - Una imagen que no está lista tras 90 segundos responde
503con el códigotimeouty el encabezado de respuestax-should-retry: false, de modo que los SDK de OpenAI no la reintentan ni inician una segunda imagen. El trabajo continúa, y el error lleva su id comogeneration_id: consulta GET /v1/generations/{id} para obtener el resultado. Solo se te factura si tiene éxito. Para reintentar con seguridad por tu cuenta, envía una Idempotency-Key: un reintento con la misma clave espera al mismo trabajo. - Un modelo cuyos
response_modesson soloasyncnecesitaPrefer: respond-async. Sin él, la respuesta es400con el códigoasync_required. Para evitar una conexión retenida en cualquier modelo que liste
async, envíaPrefer: respond-async(RFC 7240). El encabezado puede repetirse y puede llevar otras preferencias, por ejemploPrefer: wait=10, respond-async. Recibes202de inmediato con el encabezado de respuestaPreference-Applied: respond-async:{ "id": "0194f2c4-7a1e-7b3c-9d02-5f6a1c0e8b21", "status": "queued" }Consulta periódicamente GET /v1/generations/{id}, o recibe un webhook
image.completedoimage.failed. Los webhooks se disparan para imágenes solo en los trabajos que enviaste con este encabezado.
Ejemplos
curl https://api.hyperouter.app/v1/images/generations \
-H "Authorization: Bearer $HYPEROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "x-ai/grok-imagine-image", "prompt": "A lighthouse at dusk", "n": 1}'
curl https://api.hyperouter.app/v1/images/edits \
-H "Authorization: Bearer $HYPEROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "x-ai/grok-imagine-image", "prompt": "make it night",
"images": [{"image_url": "https://example.com/photo.png"}]}'
Errores
| Estado | code | param | Cuándo |
|---|---|---|---|
400 | unsupported_content_type | El cuerpo es multipart/form-data: Send a JSON body; pictures and videos are https URLs. | |
400 | invalid_body | el campo | El cuerpo no es JSON válido; images no es un array de objetos con image_url; falta prompt en generations; n es menor que 1; response_format no es url (response_format must be url.; b64_json es unsupported_parameter); resolution no está permitida; un campo tipado tiene el tipo equivocado; moderation no es auto ni low. |
400 | unknown_model | model | El modelo no existe para imágenes, o ningún proveedor coincide con tus preferencias de provider. |
400 | invalid_size | size | size no tiene la forma 1024x1024, o el modelo no la permite. |
400 | too_many_images | n o images | n supera 10 o el límite del modelo; más de 5 imágenes; más imágenes de las que admite el modelo. |
400 | image_required | images | Una edición tiene menos imágenes de las que necesita el modelo, o llamaste a generations en un modelo que solo edita (usa /v1/images/edits). |
400 | unsupported_operation | images | El modelo no edita imágenes. |
400 | unsupported_parameter | el campo | El modelo no admite el campo; images[i].file_id. |
400 | invalid_combination | el campo | El proveedor no permite estos campos juntos. |
400 | async_required | El modelo solo responde de forma asíncrona: envía Prefer: respond-async. | |
400 | unsupported_parameter | stream | "stream": true en un modelo cuyos response_modes no incluyen stream. |
400 | invalid_image | images[i].image_url | La URL no es https a un host público: images[i].image_url must be an https URL. para una URL data: o http://. |
400 | content_rejected | El filtro de seguridad del proveedor rechazó la entrada: The request was rejected by a content safety filter. | |
400 | vendor_rejected | The request was refused by the model. Check its parameters and inputs. | |
400 | invalid_idempotency_key | Consulta Reintentos e idempotencia. | |
402 | insufficient_credits | El saldo o el límite de la clave no cubre lo máximo que podría costar la solicitud. | |
409 | idempotency_key_reused, idempotency_key_in_use | Consulta Reintentos e idempotencia. | |
429 | rate_limit_error | Todos los proveedores están al límite de su capacidad (sin code), o tu cuenta supera sus solicitudes por minuto o sus solicitudes concurrentes (code: rate_limited, consulta Límites de velocidad). | |
503 | upstream_error | The model failed to produce a result. You were not charged. | |
503 | provider_busy | El proveedor siguió al límite de su capacidad durante unos dos minutos y no aceptó el trabajo. Reintenta más tarde. No se te cobró. | |
500 | server_error, no_price | Hyperouter ha fallado, o el modelo no se puede valorar ahora. Un 500 después de crear la imagen lleva x-should-retry: false. | |
503 | timeout | La imagen no estuvo lista en 90 segundos. Todavía se está creando: error.generation_id es el id que debes consultar. Lleva x-should-retry: false. |
El mensaje de un trabajo fallido termina con el motivo del propio proveedor, si lo dio, tras Provider:, para distinguir un prompt rechazado, un proveedor saturado y una caída. Las URL que contenga se sustituyen por <url>.
Modelos de imagen
| Modelo | Función | Precio |
|---|---|---|
x-ai/grok-imagine-image | Genera y edita. Hasta 10 imágenes, hasta 5 imágenes de entrada. | $0.02 por imagen |
x-ai/grok-imagine-image-2.0 | Genera y edita, igual que el anterior. | Desde $0.04 por imagen |
qwen/qwen-image-2.0 | Genera y edita (de 1 a 3 imágenes de entrada). n de 1 a 6. | $0.035 por imagen |
bytedance/seedream-5.0-flash | Genera y edita (de 1 a 10 imágenes de entrada). Una imagen 2K por solicitud, sin marca de agua. | $0.018 por imagen |
bytedance/seedream-5.0-lite | Genera y edita, como el anterior. | $0.035 por imagen |
Algunos modelos requieren que se conceda acceso a tu cuenta. La referencia de modelos del panel enumera todos los modelos que tu cuenta puede llamar, con sus parámetros, precios y notas.
Vídeos
El vídeo sigue la API de vídeos de OpenAI. Un vídeo es un trabajo. Una llamada de creación, edición, extensión o remix responde 200 de inmediato con el objeto Video en estado queued. Consultas GET /v1/videos/{id} hasta que el estado sea completed, o recibes un webhook. Prefer no cambia nada aquí: los vídeos son siempre asíncronos.
| Endpoint | Función |
|---|---|
POST /v1/videos | Crea un vídeo a partir de un prompt, con un input_reference opcional. |
POST /v1/videos/edits | Edita o escala un vídeo completado. Solo modelos que listan edit en operations. |
POST /v1/videos/extensions | Extiende un vídeo completado. Solo modelos que listan extend. |
POST /v1/videos/{id}/remix | Nuevo prompt sobre un vídeo completado, con el mismo modelo. Solo modelos que listan remix. |
GET /v1/videos | Lista tus vídeos. |
GET /v1/videos/{id} | El objeto Video. |
GET /v1/videos/{id}/content | El MP4 o la miniatura. |
DELETE /v1/videos/{id} | Elimina un vídeo. |
Crear un vídeo
El cuerpo es JSON, en todos los endpoints de vídeo; el videos.create de los SDK de OpenAI con un archivo de imagen input_reference también se acepta, y el archivo se trata como en las ediciones de imágenes. Toda imagen y todo vídeo es una URL https a un host público, que se pasa al proveedor tal cual: el proveedor debe poder descargarla, y si no puede descargarla o leerla, el vídeo falla con vendor_rejected y no se cobra nada. Una URL data:, una URL http://, una dirección IP o un nombre interno se rechaza con 400 invalid_image o 400 invalid_video. Un cuerpo multipart/form-data se rechaza con 400 unsupported_content_type.
| Nombre | Tipo | Obligatorio | Valores permitidos | Por defecto | Descripción |
|---|---|---|---|---|---|
model | string | Sí | Un id de modelo de vídeo | El modelo que se usará. | |
prompt | string | Sí | Texto no vacío | Qué crear. | |
seconds | string | integer | No | Según lo que permita el modelo | El primer valor permitido del modelo; si no, 4 s (o el máximo del modelo si es menor) | Duración del vídeo. "8" y 8 son lo mismo. |
size | string | No | WIDTHxHEIGHT | La altura determina la resolución salvo que envíes resolution: hasta 480 es 480p, hasta 720 es 720p, hasta 1080 es 1080p, hasta 1440 es 2K, por encima es 4K. El modelo debe permitir esa resolución. | |
input_reference | object | Si el modelo necesita una imagen | {"image_url": "https://..."}, una URL https | La primera imagen del vídeo. No se acepta file_id. | |
resolution | string | No | 480p, 720p, 1080p, 2K, 4K, según lo que permita el modelo | La primera resolución del modelo | Resolución de salida. Cambia el precio. |
ratio | string | No | Si el modelo lo lista | Relación de aspecto. | |
audio | boolean | No | Si el modelo genera sonido | false | Genera sonido. |
seed | integer | No | Si el modelo lo lista | Semilla para una salida repetible. | |
negative_prompt | string | No | Si el modelo lo lista | Qué evitar. | |
prompt_extend | boolean | No | Si el modelo lo lista | Desactivado salvo que lo pidas | Permite que el modelo amplíe el prompt. |
prompt_expand, locale | boolean, string | No | Como en imágenes | false | Añadido. Consulta Expansión del prompt. |
prompt_expand_model | string | No | Como en imágenes | x-ai/grok-4.6 | Añadido. Con prompt_expand: el modelo que escribe la reescritura. Consulta Expansión del prompt. |
first_frame, last_frame | string | No | Una URL https de una imagen | Fotogramas clave. | |
reference_images, reference_videos | string[] | No | URL https | Medios de referencia. No se pueden combinar con fotogramas clave, según lo establece el proveedor. | |
models, provider | string[], object | No | Como en imágenes | Añadido. Modelos de reserva y preferencias de enrutamiento. | |
moderation | string | No | auto, low | auto | Añadido. Consulta Moderación. |
| campos específicos del modelo | según se declare | Según se declare | Según se declare | Consulta Parámetros específicos de cada modelo. |
Editar, extender y remix
| Endpoint | Cuerpo (JSON) |
|---|---|
POST /v1/videos/edits | model, video (obligatorio), prompt, resolution y las funciones compartidas. video es {"id": "<your video id>"} (un vídeo tuyo completado) o {"url": "https://..."}. model toma por defecto el modelo del vídeo de origen cuando envías un id. |
POST /v1/videos/extensions | model, video (obligatorio), prompt, seconds. Los nuevos segundos siguen las mismas reglas que en una creación. |
POST /v1/videos/{id}/remix | prompt (obligatorio). El modelo es el del vídeo de origen. |
El vídeo de origen debe haberse completado. Un vídeo indicado por URL es una URL https, que se pasa al proveedor tal cual, igual que una imagen. Si indicas un vídeo por URL, seconds es obligatorio en los modelos que no tienen un máximo fijo.
Listar, consultar, descargar, eliminar
| Endpoint | Parámetros | Respuesta |
|---|---|---|
GET /v1/videos | Consulta: after (un id de vídeo), limit (de 1 a 100, por defecto 20), order (desc por defecto, o asc) | {"object":"list","data":[Video],"first_id","last_id","has_more"}. Los vídeos que han superado su expires_at se omiten. |
GET /v1/videos/{id} | El objeto Video. | |
GET /v1/videos/{id}/content | Consulta: variant (video por defecto, o thumbnail) | 302 Found a un enlace firmado a los bytes (video/mp4, o el tipo de la miniatura), válido durante 15 minutos. Los clientes HTTP y los SDK de OpenAI lo siguen. 404 not_found antes de completarse o cuando no hay miniatura. |
DELETE /v1/videos/{id} | {"id","object":"video.deleted","deleted":true}. Responde 409 video_not_finished mientras el trabajo se ejecuta. Un vídeo eliminado responde 404. | |
El objeto Video
{
"id": "0194f2c4-7a1e-7b3c-9d02-5f6a1c0e8b21",
"object": "video",
"model": "x-ai/grok-imagine-video",
"status": "completed",
"progress": 100,
"prompt": null,
"seconds": "8",
"size": "",
"created_at": 1730000000,
"completed_at": 1730000137,
"expires_at": 1732592000,
"error": null,
"remixed_from_video_id": null,
"usage": { "cost": 0.4, "seconds": 8 }
}
| Campo | Tipo | Descripción |
|---|---|---|
status | string | queued, in_progress, completed o failed. |
progress | integer | De 0 a 100. |
prompt | string | null | El prompt solo se devuelve mientras el trabajo se ejecuta. El objeto terminado devuelve null. |
seconds | string | Duración del vídeo, como cadena, igual que en OpenAI. |
size | string | El size que enviaste, si lo hiciste. |
expires_at | integer | Hora Unix: created_at más 30 días. Después, GET /v1/videos/{id} y /content responden 404 not_found y el vídeo se omite de la lista. Descarga lo que quieras conservar antes de esa fecha. |
error | object | null | En un trabajo fallido: {"code", "message"}, por ejemplo content_rejected. |
remixed_from_video_id | string | null | El vídeo de origen de una edición, extensión o remix. |
usage | object | null | Se define cuando el trabajo se liquida: cost (USD, número JSON) y seconds (entero). |
expanded_prompt | string | null | Añadido. Con prompt_expand: el prompt con el que se generó, una vez enviado el trabajo. Se conserva 30 días; después, null. |
Un vídeo se factura según los segundos que solicitas. El importe se retiene por adelantado y se libera por completo si el trabajo falla.
Ejemplo: x-ai/grok-imagine-video
El modelo x-ai/grok-imagine-video crea un vídeo a partir de un prompt, con una imagen opcional como punto de partida. seconds va de 1 a 15. Precio: $0.050 por segundo.
curl https://api.hyperouter.app/v1/videos \
-H "Authorization: Bearer $HYPEROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "x-ai/grok-imagine-video",
"prompt": "She turns to the camera and smiles",
"input_reference": { "image_url": "https://example.com/portrait.png" },
"seconds": 8
}'
{
"id": "0194f2c4-7a1e-7b3c-9d02-5f6a1c0e8b21",
"object": "video",
"model": "x-ai/grok-imagine-video",
"status": "queued",
"progress": 0,
"prompt": "She turns to the camera and smiles",
"seconds": "8",
"size": "",
"created_at": 1730000000,
"completed_at": null,
"expires_at": 1732592000,
"error": null,
"remixed_from_video_id": null,
"usage": null
}
A este trabajo se le cobra 8 × $0.050 = $0.40, así que el objeto liquidado muestra "usage": {"cost": 0.4, "seconds": 8}.
Errores
| Estado | code | param | Cuándo |
|---|---|---|---|
400 | unsupported_content_type | El cuerpo es multipart/form-data: Send a JSON body; pictures and videos are https URLs. | |
400 | invalid_body | el campo | El cuerpo no es JSON válido; prompt está vacío; video no es un objeto con id o url; input_reference no es un objeto con image_url; limit, after o variant no es válido; un campo tipado tiene el tipo equivocado; resolution no está permitida; moderation no es auto ni low. |
400 | unknown_model | model | El modelo no existe para vídeos. |
400 | invalid_seconds | seconds | seconds no está permitido para el modelo (el mensaje enumera los valores permitidos), o hace falta para un vídeo indicado por URL. |
400 | invalid_size | size | size no tiene la forma 1280x720. |
400 | unsupported_parameter | el campo | El modelo no admite el campo; la resolución no está disponible (resolution o size); audio en un modelo sin sonido; input_reference.file_id. |
400 | unsupported_operation | model | El modelo no lista la operación (editar, extender o remix). |
400 | invalid_combination | el campo | Medios de referencia junto con fotogramas clave, según lo establece el proveedor. |
400 | image_required | input_reference | This model needs an input_reference picture. |
400 | video_not_ready | video | El vídeo de origen no ha terminado. |
400 | invalid_image, invalid_video | el campo | La URL de una imagen (invalid_image) o de un vídeo (invalid_video: reference_videos[i], video.url) no es https a un host público, por ejemplo una URL data: o http://: <field> must be an https URL. param es el campo, por ejemplo input_reference.image_url, first_frame o reference_images[1]. Una URL se pasa al proveedor tal cual: si el proveedor no puede descargarla o leerla, el vídeo falla con vendor_rejected y no se cobra nada. |
400 | clip_too_long | El clip de referencia más los seconds solicitados superan el límite del modelo: The reference clip plus the requested seconds run past the model's limit of 30 s. Send a shorter clip or fewer seconds. You were not charged. Aparece en error.code del objeto Video. | |
400 | content_rejected, vendor_rejected | El trabajo falló en el proveedor. Aparece en error.code del objeto Video. | |
402 | insufficient_credits | El saldo o el límite de la clave no cubre el importe retenido. | |
404 | not_found | El vídeo no existe, no es tuyo, se eliminó o ha superado expires_at; o el contenido no está listo. | |
409 | video_not_finished | Eliminaste un vídeo que todavía se está creando. | |
409 | idempotency_key_reused, idempotency_key_in_use | Consulta Reintentos e idempotencia. | |
429, 503, 500 | Igual que en imágenes. Un 500 después de crear el vídeo lleva x-should-retry: false. | ||
Modelos de vídeo
| Modelo | Precio por segundo de vídeo | Notas |
|---|---|---|
x-ai/grok-imagine-video | Desde $0.050 | Entrada de texto, imagen o vídeo. 15 s como máximo. Admite edit. |
x-ai/grok-imagine-video-1.5 | Desde $0.080 | Entrada de texto, imagen o referencia. 15 s como máximo. |
x-ai/grok-imagine-video-1.5-lite | Desde $0.020 | Igual que el anterior, más pequeño y barato. |
bytedance/seedance-2.0 | Desde $0.0431892 | Entrada de texto, primer y último fotograma o imágenes de referencia, audio opcional. De 4 a 15 s. 480p, 720p, 1080p o 4K; la tarifa indicada es la de 480p. |
bytedance/seedance-2.0-fast | Desde $0.0331452 | Entrada de texto, primer y último fotograma o imágenes de referencia, audio opcional. De 4 a 15 s. 480p o 720p; la tarifa indicada es la de 480p. |
bytedance/seedance-2.0-mini | Desde $0.0210924 | Entrada de texto, primer y último fotograma o imágenes de referencia, audio opcional. De 4 a 15 s. 480p o 720p; la tarifa indicada es la de 480p. |
bytedance/seedance-2.5 | Desde $0.0642816 | Entrada de texto, primer y último fotograma o imágenes de referencia, audio opcional. De 4 a 15 s. 480p, 720p o 1080p; la tarifa indicada es la de 480p. |
lumina/berry-1.0 | Desde $0.050 | Entrada de texto, imagen o referencia, audio opcional. 30 s como máximo. 480p, 720p o 1080p; la tarifa indicada es la de 480p. |
minimax/minimax-h3 | Desde $0.080 | Entrada de texto, primer y último fotograma o imágenes de referencia, sin audio. De 4 a 15 s, a 768p o 2K. |
alibaba/wan3.0 | Desde $0.050 | Entrada de texto, imagen o referencia, audio opcional. 30 s como máximo. 480p, 720p o 1080p; la tarifa indicada es la de 480p. |
La referencia de modelos del panel enumera todos los modelos de vídeo que tu cuenta puede llamar.
Generaciones
Devuelve el registro de una de tus solicitudes, de cualquier tipo: su estado, consumo, cargo, tiempos y, para imágenes y vídeos, enlaces firmados a las salidas. Úsalo para consultar periódicamente una solicitud de imagen que enviaste con Prefer: respond-async y para conciliar el gasto. El texto del prompt y de la respuesta nunca está en el registro. Hyperouter lo conserva cifrado durante 180 días solo para cumplir obligaciones legales, y ninguna API ni página del panel lo devuelve (Política de privacidad).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (UUID) | Sí | El id de un chat completion, una respuesta de imagen o un objeto Video. |
Respuesta
{
"data": {
"id": "0194f2c4-7a1e-7b3c-9d02-5f6a1c0e8b21",
"kind": "chat",
"model": "x-ai/grok-4.7",
"provider_name": "xAI",
"status": "done",
"created_at": "2026-10-24T08:12:00Z",
"finished_at": "2026-10-24T08:12:02Z",
"usage": {
"input_tokens": 120, "output_tokens": 300, "cache_read_tokens": 0,
"image": 0, "video_seconds": 0, "cost": 0.00204
},
"usage_estimated": false,
"ttft_ms": 320,
"latency_ms": 2100,
"error": null,
"outputs": []
}
}
| Campo | Tipo | Descripción |
|---|---|---|
kind | string | chat, image o video. |
provider_name | string | null | El proveedor que atendió una solicitud de chat terminada. null para imágenes y vídeos. |
status | string | queued, submitting, running, done o failed. |
created_at, finished_at | string | null | RFC 3339 UTC. finished_at es null hasta que la solicitud termina. |
usage | object | input_tokens, output_tokens, cache_read_tokens, image, video_seconds y cost. cost es el cargo en USD, un número JSON. Los contadores son 0 hasta que la solicitud termina. |
usage_estimated | boolean | true cuando el proveedor no envió el recuento de tokens y Hyperouter lo calculó. |
ttft_ms, latency_ms | integer | null | Tiempo hasta el primer token y tiempo total, en milisegundos. |
error | object | null | {"code", "message"} cuando la solicitud falló. |
outputs | object[] | Para imágenes y vídeos: [{"url", "expires_at"}], enlaces firmados válidos durante 24 horas. Disponibles durante 30 días tras la solicitud; después outputs queda vacío y el registro permanece. Siempre vacío en chat. |
expanded_prompt | string | null | Para imágenes y vídeos enviados con prompt_expand: el prompt con el que se generó. Se conserva 30 días tras la solicitud; después, null. |
curl https://api.hyperouter.app/v1/generations/0194f2c4-7a1e-7b3c-9d02-5f6a1c0e8b21 \
-H "Authorization: Bearer $HYPEROUTER_API_KEY"
Errores
| Estado | type | code | param | Cuándo |
|---|---|---|---|---|
404 | not_found | not_found | id | No generation with that id. El id no es un UUID, no existe, pertenece a otra cuenta o se eliminó. |
500 | server_error | server_error | Hyperouter no pudo leer ni firmar el registro. | |
401, 403 | Consulta Autenticación. | |||
Parámetros específicos de cada modelo
Algunos modelos tienen campos que otros modelos no tienen. Son los parámetros adicionales. Los envías como campos de primer nivel del cuerpo de la solicitud, como cualquier otro campo. Cualquier SDK de OpenAI puede enviarlos (extra_body en Python, propiedades adicionales en JavaScript).
GET /v1/models enumera los parámetros adicionales de cada modelo en extra_parameters. Cada entrada tiene:
| Campo | Tipo | Descripción |
|---|---|---|
type | string | Uno de string, integer, number, boolean, array, object. |
values | array | Los valores permitidos. Vacío significa cualquier valor del tipo. |
price_condition | boolean | true cuando el campo cambia el precio. |
description | string | Qué hace el campo. |
La referencia de modelos del panel describe los parámetros adicionales de cada modelo que tu cuenta puede llamar.
Reglas
- Un parámetro conocido que el modelo no tiene se rechaza:
400 invalid_request_errorcon el códigounsupported_parameter,paramcon el nombre del campo (por ejemploloras) y el mensajeThis model does not support "loras".Un parámetro es conocido cuando algún modelo del catálogo lo declara. La misma regla cubre las funciones compartidas (resolution,ratio,audio,seed,negative_prompt,first_frame,last_frame,reference_images,reference_videos,prompt_extend). Nada se descarta en silencio, porque cambiaría la salida y el precio. - Un valor de tipo incorrecto se rechaza con
400 invalid_body,paramcon el nombre y un mensaje comoloras must be of type array. - Un valor fuera de
valuesse rechaza con400 invalid_bodyy el mensaje<name> must be one of [...]. - Un campo que ningún modelo declara se ignora, igual que la API de OpenAI ignora los campos desconocidos.
- Cada modelo comprueba sus parámetros con su propio esquema: valores permitidos, mínimo y máximo, campos obligatorios y longitudes de lista. Un valor fuera del esquema responde
400 invalid_bodyconparamnombrando el campo, por ejemploseconds must be one of 5, 8. - Una combinación que un proveedor no permite, como medios de referencia junto con fotogramas clave, responde
400 invalid_combinationcon el motivo. Las comprobaciones se ejecutan antes de cobrar nada. - Los campos que cambian el precio, como
resolutionyaudio, se valoran en la retención previa, por lo que la retención es exacta.
Funciones compartidas
Estos campos tienen el mismo nombre en todos los modelos que los tienen. Un modelo lista los que admite en supported_parameters.
| Campo | Significado |
|---|---|
resolution | 480p, 720p, 1080p, 2K o 4K, según lo que permita el modelo. |
ratio, seed, negative_prompt, prompt_extend, audio | Según su nombre. audio y prompt_extend están desactivados salvo que los pidas. |
first_frame, last_frame | Fotogramas clave para vídeo. |
reference_images, reference_videos | Medios de referencia para vídeo y edición de imágenes. |
Expansión del prompt
Con "prompt_expand": true, Hyperouter reescribe tu prompt para el modelo antes de generar: una descripción más completa para una imagen y un guion segundo a segundo para un vídeo. Está desactivada por defecto, así que el prompt se envía tal cual. Solo la acepta un modelo cuyo supported_parameters incluya prompt_expand, y solo para crear una imagen o un vídeo; en cualquier otro modelo, y en la edición, extensión o remezcla de un vídeo, se rechaza con 400 unsupported_parameter. Tampoco se puede combinar con prompt_extend: true (400 invalid_body).
La expansión del prompt está disponible para una cuenta cuando Hyperouter la habilita; abre un ticket de soporte para solicitar el acceso. Hasta entonces, GET /v1/models no lista prompt_expand en ningún modelo, y una solicitud con prompt_expand: true en un modelo que lo ofrece responde 403 permission_error, código feature_not_enabled, param prompt_expand, sin retener nada ni enviarlo al proveedor.
- Lo que se generó. La respuesta de imagen, el objeto de vídeo y
GET /v1/generations/{id}incluyenexpanded_prompt, el prompt que recibió el modelo. Se conserva 30 días tras la solicitud; después se devuelvenull.promptsigue siendo tu propio texto. - Modelo que escribe.
prompt_expand_modelindica el modelo de chat que escribe la reescritura; por defecto,x-ai/grok-4.6. Solo es válido conprompt_expand: true(si no,400 invalid_body). Un modelo que no existe o que no es de chat da400 unknown_model, y uno que tu cuenta no puede llamar da403 model_not_enabled, ambos antes de retener nada. Si el modelo lee imágenes, se le muestran las imágenes de la solicitud; si no, escribe solo a partir del texto. - Precio. La reescritura se cobra en la misma solicitud, a los precios por token del modelo que la escribió (
prompt_expand_model; si no,x-ai/grok-4.6) según los tokens que usó, y su importe máximo se retiene por adelantado junto con la generación. La referencia de modelos detalla cada modelo. - Cuándo no se ejecuta. Si la reescritura falla, agota el tiempo o no se puede usar, se genera con tu prompt tal cual, se devuelve
expanded_prompt: nully no cuesta nada. - Idioma. Los diálogos de un vídeo siguen
locale(si no, el inglés) cuando el modelo habla ese idioma.
La reescritura como modelo de chat
Una cuenta con expansión del prompt también tiene un modelo de chat que devuelve la reescritura en lugar de generarla; tu referencia de modelos lo nombra. Llámalo en POST /v1/chat/completions con exactamente un mensaje user: su texto es el prompt, y sus partes image_url (URL https, 5 como máximo) son las imágenes; una URL data: o http:// devuelve 400 invalid_image con param igual a messages. target_model es obligatorio: un modelo que liste prompt_expand. seconds, locale y negative_prompt son opcionales. Un destino de vídeo con una imagen se escribe a partir de ese primer fotograma. No admite streaming (stream: true devuelve 400 unsupported_parameter), y cualquier otro mensaje, incluido un mensaje system, devuelve 400 invalid_body.
Este modelo de chat usa siempre x-ai/grok-4.6; no admite prompt_expand_model. choices[0].message.content es una cadena JSON, {"prompt": "...", "negative_prompt": "..."}, más "beats" (una línea por segundo) para un destino de vídeo. Se factura a los precios por token de x-ai/grok-4.6, que figuran en usage. Un prompt que pide las instrucciones del modelo devuelve 400 prompt_rejected; una reescritura rechazada o vacía devuelve 422 expansion_refused, y una que falla, 503 upstream_error. Ninguno de estos casos se cobra.
Moderación
El campo moderation es de OpenAI. Funciona en /v1/chat/completions, /v1/images/generations, /v1/images/edits y /v1/videos con sus llamadas de edición, extensión y remix.
| Valor | Significado |
|---|---|
auto (por defecto) | Se aplica el filtrado propio del proveedor. Hyperouter no envía nada adicional. |
low | Hyperouter envía la exclusión voluntaria del filtrado del proveedor, en los modelos donde el proveedor la ofrece. En los demás modelos low se ignora sin error, como hace OpenAI. La entrada de cada modelo en tu referencia de modelos indica si la ofrece. Envía moderation en el cuerpo: una cabecera o un campo de filtrado propio del proveedor no se reenvía en estos endpoints. |
Cualquier otro valor se rechaza: 400 invalid_request_error, código invalid_body, param moderation, mensaje moderation must be auto or low.
low está disponible para una cuenta una vez que Hyperouter lo ha habilitado; abre un ticket de soporte para solicitarlo. Hasta entonces, una solicitud con low responde 403 permission_error, código moderation_not_enabled, param moderation, y no se envía al proveedor.
{
"model": "qwen/qwen-image-2.0",
"prompt": "...",
"moderation": "low"
}
La respuesta no indica si se usó la exclusión voluntaria. Las políticas de los Términos del servicio siguen aplicándose. Una solicitud que el filtro del proveedor rechaza falla con 400 content_rejected y no se cobra.
Webhooks
En lugar de consultar periódicamente, un endpoint tuyo puede recibir una solicitud cuando termina un trabajo. Añade endpoints en el panel. La estructura es la de los webhooks de OpenAI, firmados con el esquema Standard Webhooks, por lo que los SDK de OpenAI los verifican.
| Evento | Se envía cuando |
|---|---|
video.completed, video.failed | Termina un trabajo de vídeo. |
image.completed, image.failed | Termina un trabajo de imagen que enviaste con Prefer: respond-async. |
raw.completed, raw.failed | Termina la tarea de una llamada directa (cuentas con llamadas directas): cobrada, o su retención liberada. Una llamada directa que responde en el momento no envía ninguno. |
La carga útil lleva un id, nunca un resultado, un prompt ni un cargo. Obtén el objeto con tu clave de API: data.id es el id que aceptan GET /v1/videos/{id} y GET /v1/generations/{id}. En una tarea directa es el X-Generation-Id que devolvió la creación.
{
"id": "evt_0194f2c4-7a1e-7b3c-9d02-5f6a1c0e8b21",
"object": "event",
"type": "video.completed",
"created_at": 1761300000,
"data": { "id": "0194f2c4-7a1e-7b3c-9d02-5f6a1c0e8b21" }
}
Encabezados y verificación
Cada entrega es un POST con content-type: application/json y estos encabezados:
webhook-id: el id del evento. Es el mismo en cada reintento, así que úsalo para eliminar duplicados.webhook-timestamp: segundos Unix.webhook-signature:v1,y el HMAC-SHA256 en base64 deid.timestamp.body, con la clave secreta del endpoint.
El secreto de firma empieza por whsec_. Se muestra una sola vez, cuando creas el endpoint y cuando lo rotas. Verifica el cuerpo bruto de la solicitud, antes de analizarlo:
// Node, with the OpenAI SDK
const event = client.webhooks.unwrap(rawBody, req.headers, process.env.HYPEROUTER_WEBHOOK_SECRET);
if (event.type === "video.completed") {
const video = await client.videos.retrieve(event.data.id);
}
unwrap lanza una excepción cuando la firma no se verifica; responde a una solicitud así con un estado de error. La llamada posterior usa la misma URL base que el resto de esta API.
Endpoints, reintentos y límites
- Un endpoint debe ser
httpsen el puerto 443 (o sin puerto) y un nombre de host, no una dirección IP. El host debe resolverse a una dirección pública; Hyperouter lo vuelve a comprobar al conectarse. No se siguen las redirecciones. - Una cuenta tiene como máximo 10 endpoints. Cada endpoint elige los tipos de evento que quiere.
- Un
2xxen 10 segundos es un éxito. Cualquier otra cosa se reintenta tras unos 5 segundos, 1 minuto, 5 minutos, 30 minutos, 2 horas, 5 horas, 10 horas y 10 horas, y después la entrega se marca como fallida. - Un endpoint cuyas entregas fallan todas durante 3 días se desactiva, y el panel indica el motivo. Vuelve a activarlo después de arreglar el receptor.
- El panel lista las entregas de cada endpoint con su estado, intentos, último estado HTTP y último error. Tiene Resend (mismo id de evento) y Send test event, que entrega un evento
webhook.testcuyodata.ides el id del endpoint.
Servidor MCP
Un asistente de IA puede trabajar con tu cuenta de Hyperouter a través del Model Context Protocol (MCP). El servidor gestiona el panel: claves de API, actividad, créditos, tickets, webhooks y la lista de modelos. No ejecuta modelos. Las llamadas a modelos siguen yendo a /v1 con una clave de API.
El servidor habla Streamable HTTP y JSON-RPC 2.0. Admite las revisiones de MCP 2025-11-25 y 2025-06-18. No tiene estado: no hay sesiones, y GET /mcp responde 405.
Tokens de acceso
Un cliente MCP se autentica con un token de acceso del panel, no con una clave de API.
- Crea un token en el panel. Dale un nombre, un ámbito y, opcionalmente, una fecha de caducidad.
- Un token empieza por
hr_dt_. Se muestra una sola vez. Hyperouter guarda solo un hash. - Un usuario de la cuenta puede tener como máximo 25 tokens no caducados ni revocados. Revoca un token en el panel para detenerlo al instante.
- Un token no funciona en
/v1, y una clave de API no funciona en/mcp. - Un token actúa como el usuario que lo creó, con los permisos de ese usuario. Los permisos se comprueban en cada mensaje, así que un cambio de rol se aplica en la siguiente llamada.
| Ámbito | Herramientas que el token puede llamar |
|---|---|
read | Herramientas que solo leen datos. |
write | Todas las herramientas que el usuario tiene permiso para usar. |
Envía el token como token bearer:
Authorization: Bearer hr_dt_...
Protocolo
| Método | Respuesta |
|---|---|
initialize | La versión del protocolo (la del cliente, si se admite; si no, 2025-11-25), la capacidad tools y la información del servidor. |
ping | Un resultado vacío. |
tools/list | Las herramientas que permiten el usuario y el ámbito del token. |
tools/call | El resultado de una herramienta. |
Una notificación, o una respuesta al servidor, responde 202 sin cuerpo. Un lote JSON-RPC se rechaza con el error -32600. Un mensaje no debe superar 1 MiB. Un encabezado MCP-Protocol-Version desconocido responde 400. Una solicitud de navegador debe proceder de https://dash.hyperouter.app; un cliente que no envía el encabezado Origin no se ve afectado.
curl https://api.hyperouter.app/mcp \
-H "Authorization: Bearer $HYPEROUTER_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}'
Herramientas
tools/list devuelve el conjunto actual de herramientas. Cada herramienta corresponde a una ruta del panel y lleva un esquema JSON Schema para sus argumentos. Las herramientas cubren:
- Cuenta y claves:
get_me,list_api_keys,create_api_key,update_api_key. - Actividad y créditos:
list_activity,get_activity,get_activity_summary,get_credits,get_topup_fee. - Tickets:
list_tickets,create_ticket,get_ticket,reply_to_ticket,close_ticket. - Webhooks:
list_webhooks,create_webhook,update_webhook,rotate_webhook_secret,delete_webhook,list_webhook_deliveries,resend_webhook_delivery,send_test_webhook. - Modelos:
list_models. - Las herramientas de personal, con el prefijo
admin_, aparecen solo para los usuarios que tienen el permiso de personal.
Una herramienta responde con un elemento de contenido de texto que contiene el cuerpo JSON de la ruta. Cuando la ruta falla, el resultado tiene isError: true y el texto <message> (<code>, HTTP <status>). Una herramienta desconocida, o una que tu token no puede ver, es el error JSON-RPC -32602.
Aprobaciones
Una escritura sensible, como acreditar una cuenta, no se ejecuta de inmediato. La herramienta no la ejecuta. Responde con status igual a approval_required y una approval_url en el panel. El usuario abre el enlace, confirma con un segundo factor y aprueba la acción. Una aprobación caduca a las 24 horas. El usuario también puede rechazarla.
Facturación y límites
- Las solicitudes se pagan con un saldo prepagado en USD, facturadas al precio de lista del proveedor que las atendió, sin recargo.
- Retener y liquidar. Antes de ejecutar una solicitud, Hyperouter retiene lo máximo que puede costar: tu entrada más
max_tokensen chat, la cantidad solicitada en imágenes y los segundos en vídeo. Cuando termina, se te cobra lo que se usó y el resto de la retención se libera. El saldo nunca es negativo. - Una solicitud fallida, o un trabajo de imagen o vídeo fallido, no cuesta nada. Un intento de reserva que falla no cuesta nada.
- Cada respuesta incluye su cargo como
usage.cost, un número JSON en USD: en chat, en imágenes, en un vídeo liquidado y enGET /v1/generations/{id}. El panel muestra todas las solicitudes y tu gasto por día, modelo y clave. - Los importes son exactos: el dinero se cuenta en milmillonésimas de dólar y nunca se redondea a través de un float. Los precios de
GET /v1/modelsson cadenas decimales. - Por ahora las recargas son manuales. Abre una solicitud de recarga en el panel con el importe, la referencia del pago y una captura de pantalla del pago. El equipo comprueba el pago y acredita tu saldo, y responde en el mismo ticket.
- Comisión por recarga. Cada recarga lleva una comisión del 5,5 % del importe pagado, con un mínimo de $0.80, que se descuenta cuando se acredita la recarga: un pago de $100 acredita $94.50, y un pago de $10 acredita $9.20. La comisión vigente se muestra en la página Credits antes de que solicites una recarga, y cada recarga de tu historial muestra el importe pagado y la comisión. Las solicitudes en sí no llevan ninguna comisión.
Límites de velocidad
Cada cuenta tiene un límite de solicitudes por minuto y de solicitudes en curso a la vez. Ambos cuentan juntas todas las claves de API de la cuenta, y se aplican a toda solicitud que inicia trabajo: chat completions, creaciones de imagen y vídeo, y creaciones directas. Leer un resultado (GET /v1/generations/{id}, GET /v1/videos…, una consulta directa de tarea) no cuenta; las consultas directas se cuentan aparte, por proveedor, con el mismo límite de solicitudes por minuto.
Tu nivel depende del total que hayas recargado, antes de la comisión por recarga:
| Nivel | Recargado | Solicitudes por minuto | Solicitudes concurrentes |
|---|---|---|---|
| 1 | Menos de $10 | 60 | 10 |
| 2 | $10 o más | 300 | 30 |
| 3 | $100 o más | 1,200 | 100 |
| 4 | $1,000 o más | 6,000 | 300 |
Tus límites actuales aparecen en la página Credits. Son los valores por defecto; el personal puede cambiarlos para la plataforma o para una cuenta concreta, y el cambio se aplica en un minuto.
Si se supera cualquiera de los dos límites, la solicitud se rechaza antes de retener o reenviar nada, con 429, type: rate_limit_error, code: rate_limited y un encabezado Retry-After en segundos. El mensaje indica el límite alcanzado. Una solicitud cuenta para el minuto aunque se rechace. Una solicitud en curso, incluido un stream, cuenta hasta que termina.
Como protección contra el intento de adivinar claves, Hyperouter cuenta las comprobaciones fallidas de clave de API por dirección de cliente. Más de 30 en un minuto bloquean esa dirección en todas las rutas /v1 durante 15 minutos: 429, rate_limit_error, too_many_auth_failures, con Retry-After. Una clave válida no levanta el bloqueo.
Soporte
Abre un ticket en el panel para dudas sobre facturación, recargas y la API; el equipo responde en el mismo hilo. También puedes escribir a [email protected]. Incluye el id de la respuesta cuando informes de una solicitud concreta.