Documentación

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
  }
}
CampoTipoNotas
messagestringLegible para humanos. Es seguro registrarlo; nunca incluye secretos.
typestringCategoría general (authentication_error, invalid_request_error, …).
codestringIdentificador detallado. Úselo para bifurcar la lógica de forma programática.
paramstring|nullIndica el nombre del campo cuando el error se refiere a uno específico.

Códigos de estado HTTP

HTTPSignificadoRetry?
400invalid_request_error — el cuerpo de la solicitud tiene un formato incorrecto.No: corrija la solicitud.
401authentication_error — la clave de API es incorrecta, falta o se ha revocado.No: cambie la clave.
402insufficient_quota — la cartera está vacía (code: insufficient_balance) o se ha alcanzado un límite mensual.No: añada fondos en /app/billing. Excepción: un encabezado Retry-After significa que hay una recarga automática en curso; vuelva a intentarlo después.
403permission_error — 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.
404model_not_found — el ID del modelo no existe o está deshabilitado.No: consulte /v1/models.
404missing_v1_prefix — una ruta de endpoint en api.kunavo.com sin /v1, o una solicitud POST al host base.No: establezca la URL base como https://api.kunavo.com/v1.
404unknown_url — no hay ningún endpoint en esa ruta bajo /v1; el mensaje indica el más cercano.No: corrija la ruta.
408Tiempo de espera agotado para la solicitud del cliente.Sí, con precaución respecto a la idempotencia.
422upstream_422 — el proveedor ascendente rechazó su entrada (p. ej., un tamaño no compatible).No: ajuste la entrada.
429Límite de frecuencia alcanzado: demasiadas llamadas simultáneas.Sí: aplique una espera exponencial.
500Error interno de Kunavo.Sí: aplique una espera breve.
502upstream_error — el proveedor ascendente ha fallado.Sí: aplique una espera exponencial.
504Tiempo 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.
Las llamadas fallidas (4xx + 5xx) no se facturan. La fila de coste en 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.code es insufficient_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_url abre la página de facturación con una recarga preseleccionada; auto_recharge_url la 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/videos acepta un encabezado Idempotency-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 + message de 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.

Próximos pasos