Errores

Códigos HTTP estándar y cuerpos de error consistentes en toda la API.

Códigos de estado

CampoTipoDescripción
200OKPetición correcta.
201CreatedRecurso creado (p. ej. un check-in nuevo).
400Bad RequestJSON inválido o validación fallida — el detalle indica el campo exacto.
401UnauthorizedFalta la API key o no es válida (la rechaza el gateway).
402Payment RequiredHas agotado las reservas de prueba gratuitas. Añade una tarjeta para seguir creando reservas; lo ya enviado no se ve afectado.
403ForbiddenCuenta suspendida por impago (tenant_suspended): regulariza el pago en el panel (Facturación) para reactivar el servicio. O cuenta con la baja pedida (account_closing): solo responde /exports hasta que se reactive o la baja sea efectiva.
404Not FoundEl recurso no existe en tu cuenta (o aún no está disponible, p. ej. un contrato sin firmar).
409ConflictLa operación no cabe en el estado actual del recurso (p. ej. añadir un huésped a una reserva completa, borrar uno cuyo parte ya se comunicó, cambiar las fechas de una reserva cuyo parte SES aún no ha confirmado, o descargar una exportación que aún se está generando). El campo error dice cuál.
410GoneEl enlace del huésped ha caducado (14 días tras la salida), en las rutas públicas /c/…; o, en la API v1, el ZIP de una exportación ya se borró (siete días después de estar lista).
429Too Many RequestsCuota diaria de creación de check-ins alcanzada (se reinicia a medianoche UTC). Si tu operación real necesita más, contáctanos y la ampliamos.
500InternalError nuestro. Reintenta; si persiste, contáctanos.
502Bad GatewayUn sistema externo falló (SES Hospedajes rechazó o no respondió). No es un error de tu petición: reintenta más tarde.
503Service UnavailableSES Hospedajes no respondió a una operación que tiene que salir bien ANTES de guardar tu cambio: anular un parte para cambiar las fechas de una reserva ya comunicada. No se ha guardado nada; reintenta más tarde.

Códigos de error concretos

Más allá del status HTTP, el campo error del cuerpo identifica la causa exacta para que puedas ramificar sin analizar textos:

CampoTipoDescripción
payment_method_required402Has agotado las reservas de prueba gratuitas. Añade una tarjeta en el panel (Ajustes → Facturación) para seguir creando reservas. Lo ya enviado no se ve afectado: los partes comunicados siguen comunicados y el panel sigue accesible. Solo lo devuelve POST /checkins.
tenant_suspended403Cuenta suspendida por impago. Toda la API v1 queda bloqueada hasta regularizar.
account_closing403La baja de la cuenta está pedida. Durante los 30 días de gracia toda la API v1 responde esto salvo /exports, para que puedas llevarte los registros. effectiveAt dice cuándo será definitiva; reactivando la cuenta desde el panel vuelve a funcionar todo. Ver Exportación y fin del servicio.
validation400Datos inválidos. Viene con issues[] o details indicando el campo.
invalid_url400URL de webhook rechazada: debe ser https y apuntar a un servidor público (se bloquean redes internas).
full409La reserva ya tiene tantos huéspedes registrados como plazas confirmadas.
already_submitted409No se puede eliminar el huésped: su parte ya se comunicó a SES.
refiling_blocked409 / 503Se pidió cambiar las fechas de una reserva cuyo parte ya se comunicó y Kinapi no pudo anularlo para volver a comunicarlo. No se ha guardado nada. El campo code dice por qué: en_vuelo (409), el parte está enviado y SES aún no lo ha confirmado, reintenta en una hora; anulacion_fallida (503), SES no aceptó la anulación o no respondió, reintenta más tarde.
not_ready409El parte aún no puede enviarse (sin huéspedes, sin firma cuando se exige, o propiedad sin código de establecimiento). O, en GET /exports/{id}/download, la exportación aún se está generando o falló. El motivo va en details.
not_configured / disabled409Se pidió probar el webhook pero no hay ninguno configurado, o está desactivado.
no_billing409Se pidió el portal de facturación pero la cuenta aún no tiene el pago configurado.
no_guests404Se pidió el parte de viajeros de un check-in que todavía no tiene huéspedes.
no_timestamp404Se pidió el sello de tiempo de un registro de evidencia que aún no lo tiene. details dice por qué; se reintenta cada hora.
ses_error502SES Hospedajes rechazó el envío o no respondió. El detalle va en details.
link_expired410Enlace del huésped caducado (rutas públicas /c/…).
expired410Se pidió descargar una exportación cuyo ZIP ya se borró (siete días después de estar lista). Pide una nueva con POST /exports.

Formato del error

Los errores de validación detallan cada campo problemático:

400 Bad Request
{
  "error": "validation",
  "details": {
    "fieldErrors": {
      "checkInDate": ["Invalid string: must match pattern"]
    }
  }
}
404 Not Found
{ "error": "not found" }

Con la baja de la cuenta pedida, el cuerpo lleva además la fecha en que será definitiva:

403 Forbidden
{
  "error": "account_closing",
  "details": "La baja de la cuenta está pedida y se hará efectiva el 2026-11-13. Hasta entonces la API solo permite exportar los registros (/exports); para volver a usarla, reactiva la cuenta desde el panel.",
  "effectiveAt": "2026-11-13T09:00:00.000Z"
}

Reintentos

La creación de check-ins es idempotente: reintentar un POST /checkins con el mismo reservationId devuelve el check-in existente (200) en vez de duplicarlo. Ante un 500 o un timeout, reintenta con backoff exponencial sin miedo.