Documentación
Errores
Kunavo devuelve cargas útiles de error con formato de OpenAI y códigos de estado HTTP que indican si debes volver a intentarlo. Usa la gestión de errores estándar del SDK de OpenAI y todo irá bien.
Todas las respuestas que no sean 2xx tienen la misma estructura JSON: el estándar de OpenAI. Para gestionarlas mediante código, usa error.code; para la política de reintentos, usa status_code.
Carga útil del error
{
"error": {
"message": "Model 'xyz-2025' is not available",
"type": "model_not_found",
"code": "model_not_found",
"param": null
}
}| Campo | Tipo | Notas |
|---|---|---|
message | string | Legible para humanos. Es seguro registrarlo; nunca incluye secretos. |
type | string | Categoría general (authentication_ |
code | string | Identificador detallado. Úselo para bifurcar la lógica de forma programática. |
param | string|null | Indica el nombre del campo cuando el error se refiere a uno específico. |
Códigos de estado HTTP
| HTTP | Significado | Retry? |
|---|---|---|
| 400 | invalid_ — el cuerpo de la solicitud tiene un formato incorrecto. | No: corrija la solicitud. |
| 401 | authentication_ — la clave de API es incorrecta, falta o se ha revocado. | No: cambie la clave. |
| 402 | insufficient_ — la cartera está vacía (code: insufficient_) o se ha alcanzado un límite mensual. | No: añada fondos en /app/Retry-After significa que hay una recarga automática en curso; vuelva a intentarlo después. |
| 403 | permission_ — la clave es válida, pero su lista de direcciones IP permitidas no incluye la suya. | No: realice la llamada desde una dirección permitida. |
| 404 | model_ — el ID del modelo no existe o está deshabilitado. | No: consulte /v1/models. |
| 404 | missing_ — una ruta de endpoint en api./v1, o una solicitud POST al host base. | No: establezca la URL base como https://api. |
| 404 | unknown_url — no hay ningún endpoint en esa ruta bajo /v1; el mensaje indica el más cercano. | No: corrija la ruta. |
| 408 | Tiempo de espera agotado para la solicitud del cliente. | Sí, con precaución respecto a la idempotencia. |
| 422 | upstream_422 — el proveedor ascendente rechazó su entrada (p. ej., un tamaño no compatible). | No: ajuste la entrada. |
| 429 | Límite de frecuencia alcanzado: demasiadas llamadas simultáneas. | Sí: aplique una espera exponencial. |
| 500 | Error interno de Kunavo. | Sí: aplique una espera breve. |
| 502 | upstream_ — el proveedor ascendente ha fallado. | Sí: aplique una espera exponencial. |
| 504 | Tiempo de espera agotado para la tarea (la generación de imagen/vídeo superó nuestro límite de consultas de estado). | Sí, pero prevea un coste. |
usage_logs muestra $0. Excepción: los tiempos de espera agotados 504 en las API de tareas de larga duración pueden mostrar un coste del proveedor ascendente si la tarea se completó, pero no pudimos entregar el resultado; es poco frecuente.Códigos de error frecuentes
authentication_error
- Olvidó establecer el encabezado
Authorization: Bearer .... - La clave de API se revocó desde
/app/keys. - La clave aún tiene un prefijo incorrecto (debe comenzar por
sk-kn-).
insufficient_quota
- Saldo de la cartera demasiado bajo para esta solicitud →
error.codeesinsufficient_balance, y el error incluye el saldo que tenía la cartera (balance_usd), el importe que reserva esta solicitud (needed_usd) y dos enlaces:topup_urlabre la página de facturación con una recarga preseleccionada;auto_recharge_urlla abre en la configuración de recarga automática. Ninguno de los enlaces realiza un cargo por sí mismo. - Se alcanzó el límite mensual por clave. Se restablece al comienzo de cada mes natural (UTC). Aumente el límite en
/app/keys.
{
"error": {
"message": "Wallet balance is too low for this request. Top up at https://kunavo.com/app/billing — or turn on auto-recharge there, and a saved card refills the wallet before requests are refused.",
"type": "insufficient_quota",
"code": "insufficient_balance",
"param": null,
"balance_usd": 0.0142,
"needed_usd": 0.0381,
"topup_url": "https://kunavo.com/app/billing?topup=20",
"auto_recharge_url": "https://kunavo.com/app/billing?autorecharge=1&src=api_402"
}
}Deje de reintentar ante insufficient_balance, salvo que la respuesta incluya un encabezado Retry-After: este significa que ya se está cobrando a su tarjeta guardada una recarga automática y la misma solicitud debería funcionar unos segundos después.
permission_error
- La clave tiene una lista de direcciones IP permitidas y la llamada se originó desde una dirección que no está incluida. El mensaje indica la dirección que detectamos: añádala (o añada su bloque CIDR) en
/app/keys, o elimine por completo la lista para permitir cualquier dirección. - Trasladar un agente a un nuevo host, a una nueva pasarela NAT o a un portátil conectado a otra red cambia esa dirección. Una clave sin lista de direcciones permitidas nunca se rechaza de esta manera.
model_not_found
- Error tipográfico en el slug. Use /models para consultar la lista canónica.
- El modelo está deshabilitado actualmente (por una interrupción del proveedor ascendente o una revisión de precios).
upstream_error
Indica que un proveedor ascendente del modelo devolvió un error que no pudimos traducir a un código más específico. El cuerpo incluye el mensaje original. Causas frecuentes:
- Sobrecarga del proveedor.
- Rechazo por moderación de contenido (pruebe con otra instrucción).
- Restricciones de región o disponibilidad.
Estrategia de reintentos
El patrón robusto más sencillo: espera exponencial con fluctuación aleatoria solo ante errores 429 / 5xx.
import time, random
from openai import OpenAI, RateLimitError, APIError
client = OpenAI(api_key=os.environ["KUNAVO_API_KEY"], base_url="https://api.kunavo.com/v1")
def call_with_retry(call, max_attempts=5):
for attempt in range(max_attempts):
try:
return call()
except RateLimitError:
if attempt + 1 == max_attempts: raise
# 429: exponential backoff with jitter
time.sleep(min(2 ** attempt, 30) + random.random())
except APIError as e:
if e.status_code and 500 <= e.status_code < 600 and attempt + 1 < max_attempts:
time.sleep(min(2 ** attempt, 30) + random.random())
else:
raise
result = call_with_retry(lambda: client.chat.completions.create(
model="claude-haiku-4-5",
messages=[{"role": "user", "content": "hi"}],
))- Limite la espera a 30 segundos por intento y el total a 5 intentos.
- No reintente los errores 4xx (salvo 408 y 429). Hacerlo solo le hará perder tiempo.
- La generación de imágenes y vídeos no es idempotente: un reintento es una generación nueva y se factura si tiene éxito. Una llamada fallida nunca se facturó, así que reintentarla es seguro. Para vídeo,
POST /v1/videosacepta un encabezadoIdempotency-Key: un envío repetido con la misma clave devuelve la primera tarea. - Para chats con efectos secundarios en su propio código, elimine duplicados mediante una clave de idempotencia en la capa de su aplicación.
Depuración desde el panel
Todas las llamadas a la API, tanto las correctas como las fallidas, están visibles en /app/usage. Haga clic en cualquier fila para abrir la página con todos los detalles de la solicitud y la respuesta:
- Código de estado HTTP devuelto al cliente.
- Código de error del proveedor ascendente (cuando corresponda).
- Latencia, IP de la solicitud y agente de usuario.
- Filtrar por estado ayuda a detectar patrones (p. ej., todos los errores 422 en un modelo específico).
Cómo informar de un incidente
Si observa errores 5xx persistentes en un modelo que debería funcionar, envíe un correo a support@kunavo.com con lo siguiente:
- El slug del modelo y un ejemplo del cuerpo de la solicitud (oculte los secretos).
- El intervalo de tiempo en que se produjeron los fallos.
- El error
code+messagede la respuesta. - Si es posible, un enlace al registro de uso desde
/app/usage/[id].
Tiempo de respuesta: un día hábil; más rápido si el problema urgente afecta a los ingresos.