Propiedades

Alta y gestión de alojamientos: el vínculo entre los listings de tu PMS, el código de establecimiento SES y los datos del contrato.

El objeto propiedad

Objeto
{
  "id": "b8f3a2c1-…",
  "nickname": "Apartamento Sol 3B",
  "listingId": "38291",
  "channelListingIds": ["airbnb-99812", "booking-4471"],
  "address": { "street": "Calle del Sol 3", "city": "Tarifa", "province": "Cádiz", "postalCode": "11380" },
  "touristLicense": "VFT/CA/12345",
  "ownerId": "a1b2c3d4-…",
  "maxGuests": 6,
  "communicationLocale": "nl",
  "ses": { "codigoEstablecimiento": "0000012345", "tipoPago": "PLATF" },
  "owner": { "legalName": "Gestora Costa SL", "nif": "B12345678", "fiscalAddress": "…" },
  "contractTemplateId": "8a2e1f0c-…",
  "sesCredentialId": "c4d9b7a3-…",
  "active": true,
  "createdAt": "2026-07-01T09:00:00.000Z",
  "updatedAt": "2026-07-19T10:00:00.000Z"
}

Los check-ins referencian la propiedad por listingId (o cualquiera de sus channelListingIds — útil cuando Airbnb/Booking envían la reserva con el id del clon de canal en vez del maestro).

contractTemplateId y sesCredentialId asignan a esta propiedad una plantilla de contrato y un conjunto de credenciales SES concretos, de entre los que hayas creado en /contract-templates y /ses-credentials. Si se omiten, la propiedad usa el que tengas marcado como predeterminado en cada caso.

communicationLocale es el idioma por defecto del alojamiento, y manda sobre todo lo que ve ese huésped: el formulario de registro, el contrato que firma y los correos que se le envían. Es un ajuste, no tres, y el orden es siempre el mismo:

el locale de la reserva → el idioma del alojamiento → castellano

La reserva gana porque va de un huésped concreto, del que tu PMS puede saber el idioma; el alojamiento es el respaldo para cuando no se sabe. Un apartamento en Ámsterdam puesto en nl atiende en neerlandés a todo el que llegue sin idioma declarado, y sigue atendiendo en alemán a la reserva que llegue con locale: "de".

También puedes crearlas y editarlas desde el panel, en Propiedades — los mismos campos, sin escribir una línea de código. Útil para evaluar el producto antes de conectar tu PMS.

El identificador del alojamiento

El listingId es el identificador con el que te refieres a la propiedad al crear check-ins. Es opcional al darla de alta: si tu PMS ya maneja ids propios, mándalo y se respeta tal cual; si no lo mandas, Kinapi genera uno con la forma ALJ-XXXXXX y lo devuelve en la respuesta.

Los ids generados usan un alfabeto sin caracteres que se confundan al leerlos —no llevan ni I, ni O, ni S, ni 0, ni 1—, porque este id acaba dictándose por teléfono y tecleándose a mano en una integración. Si mandas uno tuyo, comprueba que no lo tenga ya otra ficha de tu cuenta, ni como listingId ni entre sus channelListingIds: la API no comprueba duplicados al crear —el alta desde el panel sí—, y la reserva acabaría cayendo en una propiedad o en la otra.

No lo cambies una vez creado. Cada check-in guarda el listingId con el que llegó y resuelve su propiedad por él, así que cambiarlo deja huérfanas las reservas que ya existen. Por eso el panel lo enseña de solo lectura, para copiarlo, y no como campo editable.

Normas de la casa

Las normas de la casa son una entidad aparte del contrato: el articulado legal es el mismo para todo el parque y las normas cambian de un alojamiento a otro. La propiedad guarda en houseRulesId el juego de normas que le toca, de entre los que tengas creados. Si no tiene ninguno asignado se usa el predeterminado de la cuenta, y una reserva concreta puede pisar los dos con el suyo.

Los dos ejes se eligen juntos. Una propiedad guarda su contrato por defecto en contractTemplateId y sus normas por defecto en houseRulesId. Se asignan desde su ficha en el panel (Datos del alojamiento) o por API, en el alta y en el PATCH; la cadena vacía desasigna y devuelve el mando al predeterminado de la cuenta.

Al crear una reserva puedes mandar contractTemplateId y houseRulesId para saltarte esos valores — los dos, uno solo, o ninguno. Lo que no mandes se toma de la propiedad, y lo que la propiedad no tenga, del predeterminado de la cuenta. Es lo que permite que un mismo alojamiento firme un contrato distinto en una estancia larga sin tocar su ficha.

El array houseRules de la propiedad es el formato anterior, de cuando las normas se escribían dentro de cada alojamiento. Se sigue aceptando y sigue mandando cuando no hay ningún juego asignado en ningún nivel, pero no lo uses en integraciones nuevas.

Crear una propiedad

POST/properties
Body
CampoTipoDescripción
nicknamerequeridostringNombre interno del alojamiento.
commercialNamestringNombre comercial del alojamiento: el que ve el huésped en sus correos, en su enlace de registro y en el contrato. Sin él se usa nickname (y la página de registro enseña la ciudad), así que nickname puede seguir siendo un código interno. Cadena vacía lo quita. Hasta 80 caracteres.
listingIdstringId del listing en tu PMS o sistema. Opcional: si se omite, Kinapi genera uno con la forma ALJ-XXXXXX y lo devuelve en la respuesta.
channelListingIdsstring[]Ids de clones de canal que resuelven a esta propiedad.
addressobjeto{ street, city, province, postalCode }. Aparece en el contrato.
touristLicensestringNº de licencia turística (p. ej. VFT/CA/12345).
maxGuestsinteger 1-50Capacidad del alojamiento. Las reservas de esta propiedad la HEREDAN si no traen la suya, así que se pone una vez aquí en vez de repetirla en cada llamada. Es el techo hasta el que el propio huésped puede corregir el número del grupo desde su enlace: sin capacidad declarada no puede tocarlo. Cadena vacía (o 0) en el PATCH para quitarla y volver a «sin capacidad declarada».
communicationLocalestringIdioma por defecto del alojamiento: es, en, de, fr, nl, it o pt. Lo heredan las reservas que no mandan locale, y decide LAS TRES COSAS a la vez —el formulario del huésped, su contrato y los correos que se le envían—, no solo los correos. Se normaliza (nl-NL → nl) y un valor desconocido cae al castellano SIN dar error: mira el communicationLocale de la respuesta para saber cuál quedó. Cadena vacía en el PATCH para desasignarlo.
houseRulesarrayLEGADO: normas escritas dentro de la propiedad, como lista de objetos {es, en}. Se sigue aceptando —sustituye a las de la plantilla al generar el PDF, no se suma— pero solo manda si no hay ningún juego de normas asignado. En integraciones nuevas, usa los juegos de normas de la casa.
activebooleanfalse da de baja la propiedad: desaparece del listado (salvo con includeInactive), de los desplegables del panel y del barrido de calendarios. Conserva su histórico y las reservas que ya existen la siguen resolviendo. Volver a true la reactiva.
ses.codigoEstablecimientostringCódigo de establecimiento en SES Hospedajes. Sin él, el parte no puede enviarse.
ses.tipoPagostringCódigo del catálogo TIPO_PAGO de SES (p. ej. PLATF). Opcional: sin él se usa el tipoPago del conjunto de credenciales SES asignado. El tipoPago de una reserva concreta pisa a este.
ownerIdstringId de un propietario existente (de /owners). Un propietario puede estar en varias propiedades. Tiene prioridad sobre owner.
ownerobjeto{ legalName, nif, fiscalAddress } — crea el propietario inline y lo vincula. Alternativa a ownerId.
contractTemplateIdstringId de una plantilla creada en /contract-templates. Sin él, usa la predeterminada del tenant.
sesCredentialIdstringId de un conjunto de credenciales creado en /ses-credentials. Sin él, usa el predeterminado del tenant.
idstringSi se envía y existe, la llamada actualiza en vez de crear.
curl
curl -X POST https://api.kinapi.es/api/v1/properties \
  -H "ocp-apim-subscription-key: TU_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "nickname": "Apartamento Sol 3B",
    "ses": { "codigoEstablecimiento": "0000012345" },
    "owner": { "legalName": "Gestora Costa SL", "nif": "B12345678" }
  }'
201 Created
{
  "id": "b8f3a2c1-…",
  "nickname": "Apartamento Sol 3B",
  "listingId": "ALJ-7KM4TQ",
  …
}

Apunta el listingId de la respuesta: es lo que mandarás en cada check-in. El id es otra cosa — el identificador interno de la ficha, el que va en la URL de /properties/{propertyId}.

Listar propiedades

GET/properties

Devuelve las propiedades activas de la cuenta —con includeInactive, también las dadas de baja— con su id y su listingId. Es la forma de recuperar el identificador de una propiedad creada a mano desde el panel: la das de alta ahí, listas aquí, y ya tienes con qué crear sus check-ins desde tu software. En el panel también se ve, bajo el nombre del alojamiento y en su ficha.

Cada propiedad del listado lleva también su ownerId (null si no tiene propietario vinculado), para agruparlas por titular sin una llamada por propiedad. Los datos del propietario (owner) solo vienen al consultar una propiedad concreta.

Query
CampoTipoDescripción
includeInactivebooleantrue para incluir también las dadas de baja.
curl
curl https://api.kinapi.es/api/v1/properties \
  -H "ocp-apim-subscription-key: TU_API_KEY"
200 OK
{
  "results": [
    { "id": "b8f3a2c1-…", "nickname": "Apartamento Sol 3B", "listingId": "ALJ-7KM4TQ", … },
    { "id": "5c7d9e01-…", "nickname": "Ático Levante", "listingId": "38291", … }
  ]
}

Consultar una propiedad

GET/properties/{propertyId}

Devuelve la ficha completa, con los datos del propietario vinculado.

Actualizar una propiedad

PATCH/properties/{propertyId}

Actualización parcial: envía solo los campos que cambian. Es la vía para corregir un alta que salió mal —la dirección, la licencia turística, el nombre interno, los ids de canal, el propietario, la plantilla o las credenciales— sin volver a mandar la ficha entera. El objeto ses se fusiona con el existente y el owner inline actualiza el propietario vinculado.

curl
curl -X PATCH https://api.kinapi.es/api/v1/properties/b8f3a2c1-… \
  -H "ocp-apim-subscription-key: TU_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "address": { "street": "Calle del Sol 3", "city": "Tarifa", "province": "Cádiz", "postalCode": "11380" },
    "touristLicense": "VFT/CA/12345",
    "maxGuests": 6,
    "communicationLocale": "nl"
  }'

address se sustituye entera: no se fusiona campo a campo como ses, así que manda los cuatro campos aunque solo cambie uno. El listingId también se acepta aquí, pero cambiarlo deja huérfanas las reservas ya creadas — mira el aviso de más arriba.

La cadena vacía es la orden de quitar, y vale para todos los campos opcionales: touristLicense, communicationLocale, maxGuests, houseRulesId, contractTemplateId y sesCredentialId. Es lo que distingue «quítalo» de «no lo toques», que sin ella serían la misma llamada.

Cambiar el idioma mueve también las reservas que ya existen, si nunca declararon el suyo. No se guarda una copia del idioma en cada reserva: se resuelve al abrirla, así que una reserva pendiente sin locale pasa a atenderse en el idioma nuevo — formulario, contrato y correos— aunque se creara antes del cambio.

Dos cosas no se mueven, y son las que importan: una reserva que sí trae su locale lo conserva, y un contrato ya firmado no se reescribe nunca — el PDF archivado queda en el idioma en que se firmó, que es lo que le da valor a la firma.

Los mismos datos se corrigen desde el panel, en la ficha de la propiedad, bajo Datos del alojamiento: dirección, licencia, nombre, ids de canal y juego de normas de la casa.

Borrar o dar de baja una propiedad

DELETE/properties/{propertyId}

Qué ocurre depende de si la propiedad tiene reservas, y la respuesta lo dice en action:

Resultado
CampoTipoDescripción
deletedsin reservasNinguna reserva la referencia, ni por su listingId ni por sus ids de canal: la ficha se borra de verdad y desaparece del listado. Es el caso de la propiedad creada por error o de prueba mientras montabas la integración.
deactivatedcon reservasAlguna reserva la referencia: la ficha se conserva y solo se marca active: false, y la respuesta añade reason: "has_bookings". Las reservas resuelven su alojamiento por listingId en cada consulta, así que borrar la ficha las dejaría sin código de establecimiento y sus partes fallarían sin decir por qué.
200 OK
{
  "ok": true,
  "action": "deactivated",
  "active": false,
  "reason": "has_bookings",
  "propertyId": "b8f3a2c1-…"
}

Una propiedad desactivada deja de listarse, de ofrecerse en el panel y de importar reservas de sus calendarios, y su histórico —reservas, contratos, partes SES— se conserva íntegro para auditoría. Lo que no hace es rechazar check-ins: una reserva que llegue con su listingId se sigue creando, así que el alta se corta dejando de enviarlas desde tu PMS.

Importar reservas de un calendario (iCal)

Airbnb, Vrbo y la mayoría de los PMS publican un calendario .ics por alojamiento. Si pegas su dirección en la ficha de la propiedad, Kinapi da de alta las reservas solo, una vez por hora. Se configura desde el panel y no por API: la dirección es una credencial —quien la tenga puede ver las fechas ocupadas del alojamiento— y no queremos que circule por integraciones.

Qué NO hace. La importación solo crea reservas: nunca modifica ni cancela una que ya exista, y nunca anula un parte ante el Ministerio. Que un evento desaparezca de un calendario no significa que la reserva se cancelara — los portales retiran los eventos pasados por diseño y un error de red produce la misma ausencia. Los cambios de fecha y las reservas que se solapan se avisan en la ficha para que los mire una persona.

Y una advertencia que conviene leer antes de contar con ello: ningún calendario trae los datos del viajero. Airbnb da la reserva y los cuatro últimos dígitos del teléfono; Vrbo, el nombre; Booking, nada. Lo que la importación quita es teclear cada reserva a mano — que no es poco —, no conseguir que el huésped rellene su parte.

Qué se puede importar de cada portal
CampoTipoDescripción
AirbnbsíDistingue reservas de bloqueos sin margen de error. Importa la reserva y su código.
Vrbo / HomeAwaysíImporta la reserva y el nombre del huésped, que publica en el resumen del evento.
Booking.comnoSu calendario marca igual una reserva que un bloqueo del propietario, así que no se puede saber cuál es cuál. No se importa nada: importar a ciegas acabaría en partes de viajeros que no existen.
Otros PMSdependeSe importa si el evento dice explícitamente que es una reserva (por ejemplo, un resumen que empieza por «Reserved» o «Reserva»). Si no, se descarta.

Las estancias ya terminadas no se importan, y las reservas que llegan del calendario se deduplican contra las que ya tengas —vengan de tu PMS o de otro portal— comparando alojamiento y fechas, no identificadores. Una reserva que entra el mismo día que sale la anterior es otra reserva distinta, y se crea.

Avisos por correo, alojamiento a alojamiento

Kinapi puede escribir al huésped para que haga su registro y avisarte cuando una reserva queda completa. Se decide por propiedad y no para toda la cuenta: donde el canal ya manda el enlace en su mensaje de bienvenida, encenderlo haría que el huésped reciba dos correos iguales; donde la reserva es directa, no lo manda nadie.

El objeto notifications de la propiedad admite cuatro campos —invitacion, recordatorio, ultimoAviso (el de la mañana de la llegada) y completo— y cada uno tiene tres estados: ausente hereda lo que tengas en Configuración → Notificaciones, true lo enciende para este alojamiento y false lo apaga aunque la cuenta lo tenga encendido. Mandar {} borra los ajustes propios y vuelve a heredar.

Los tres correos al huésped son independientes: si el enlace lo mandas tú desde tu PMS, apaga la invitación y deja el recordatorio y el último aviso, que solo le llegan a quien aún no se ha registrado. Las propiedades configuradas antes de que existiera esta opción siguen como estaban —allí el recordatorio iba con la invitación— hasta que se vuelvan a guardar.

Territorios que Kinapi no comunica

Cataluña y el País Vasco tienen policía propia competente en el registro de viajeros: los partes van a los Mossos d’Esquadra y a la Ertzaintza, no a SES.Hospedajes. Kinapi no se conecta con esos sistemas — en el caso catalán no existe servicio web al que conectarse: los partes se suben a mano a su portal.

Si das de alta una propiedad en una de esas dos comunidades, su ficha en el panel lo avisa. Puedes seguir usando Kinapi para recoger los datos del huésped y para el contrato, pero la comunicación a la policía la tienes que hacer tú, y el plazo de 24 horas del RD 933/2021 corre igual.

La competencia se decide por la province de la dirección, y solo por el código postal si no hay provincia. No es lo mismo: el Condado de Treviño es municipio de Burgos —y por tanto de SES— pero tiene códigos postales de Álava. Manda el territorio administrativo.