Operaciones de bloqueos de calendario
Lista, crea y borra bloqueos de calendario por API v1 o MCP.
Un bloqueo cierra fechas de una unidad de alojamiento, un material de alquiler o un miembro del personal para que no se puedan reservar, sin ser una reserva real: no tiene cliente, ni pago, ni pedido. Se crea a mano desde el calendario (por obras, vacaciones o mantenimiento) o llega importado automáticamente por un enlace iCal de un canal externo. Más sobre cómo se hace desde el panel en Gestionar la disponibilidad y bloquear fechas.
Operaciones de esta página: list-blocks, create-block, delete-block (solo lectura: list-blocks; escritura: create-block, delete-block).
Las bases comunes (autenticación, GET frente a POST, prueba en seco, errores HTTP, límites) están en API v1 — Introducción y primeros pasos. El identificador de tu cuenta se toma siempre de tu token; solo hace falta pasarlo con tokens multicuenta.
list-blocks: consulta los bloqueos activos
Devuelve los bloqueos del calendario, con quién los creó (a mano o por iCal) y detecta los que quedaron huérfanos tras desconectar un canal. Nunca devuelve reservas reales. Es de solo lectura: vale con cualquier token.
Cómo llamarla
curl "https://api.bukyapp.com/v1/ops/list-blocks?from=2026-09-01&to=2026-12-31" \
-H "Authorization: Bearer bk_TU_TOKEN"Por MCP: «¿Qué bloqueos tengo entre septiembre y diciembre?» o «Muéstrame los bloqueos huérfanos».
Parámetros
| Parámetro | Tipo | Nivel | Qué hace |
|---|---|---|---|
resource | texto | opcional | Identificador de la unidad (alojamiento, material o personal) para ver solo sus bloqueos. |
from | fecha | opcional | Inicio del rango. Entra todo bloqueo cuyo fin sea posterior a esta fecha. |
to | fecha | opcional | Fin del rango. Entra todo bloqueo cuyo inicio sea anterior a esta fecha. |
origin | texto | opcional | manual (creados a mano) o ical (importados por un enlace externo). Por defecto, ambos. |
only_orphans | booleano | opcional | true para ver solo los bloqueos de enlaces iCal que ya no existen; si necesitas limpiarlos en bloque, contacta con soporte. |
limit | número | opcional | Máximo de bloqueos a devolver, los más antiguos primero. |
Qué devuelve
Ejemplo real, sin filtros, en la cuenta demo (un único bloqueo manual):
{
"success": true,
"operation": "list-blocks",
"customer_id": "5a55fff67e9fe0036a541d15",
"count": 1,
"total": 1,
"breakdown": { "manual": 1, "ical": 0, "orphans": 0, "by_dead_cal": {} },
"items": [
{
"_id": "694658a75c898dd607a4fde3",
"resource": "5a5602b07e9fe0036a541d16",
"start": "2025-12-01T23:00:00.000Z",
"end": "2025-12-03T23:00:00.000Z",
"notes": null,
"origin": "manual"
}
],
"warnings": []
}| Campo | Significado |
|---|---|
count | Bloqueos que cumplen los filtros que pediste. |
total | Total de bloqueos vivos de la cuenta, sin filtrar. Compáralo con count para saber si tus filtros dejaron fuera resultados. |
breakdown | Cuántos son manuales, cuántos de iCal, cuántos huérfanos y de qué enlace muerto viene cada uno. |
items[]._id | Identificador del bloqueo. Lo necesitas para borrarlo con delete-block. |
items[].resource | Identificador de la unidad bloqueada. Pásaselo a get-resource, get-accommodation o get-staff si quieres el nombre. |
items[].start / end | Rango bloqueado, en UTC. |
items[].origin | manual o ical. |
Probé el rango pedido (septiembre-diciembre de 2026) y devolvió count: 0: el único bloqueo de la cuenta demo es de diciembre de 2025, fuera de rango. El filtro por rango y por resource funcionan como describe el manual.
Consejos
- Para ver de un vistazo cuántos bloqueos huérfanos tienes antes de pedir a soporte que los limpie, ejecuta esta operación con
only_orphans: true: te da el desglose sin tocar nada. - Si
resourceno te dice nada, resuélvelo conget-resource,get-accommodationoget-staffsegún el tipo de unidad.
create-block: bloquea fechas de un recurso
Crea un bloqueo sobre una unidad de alojamiento, una unidad de material de alquiler o un miembro del personal. Un bloqueo impide reservas nuevas; no cancela ni toca las que ya existen, y se exporta también por iCal a tus canales sincronizados. Es una operación de escritura: siempre se ejecuta en modo prueba (dry_run: true), aquí y por MCP.
Cómo llamarla
curl -X POST https://api.bukyapp.com/v1/ops/create-block \
-H "Authorization: Bearer bk_TU_TOKEN" \
-H "Content-Type: application/json" \
-d '{"resource": "Habitación Doble", "start_date": "2026-10-01", "end_date": "2026-10-03", "notes": "Obras", "dry_run": true}'Por MCP: «Bloquea la Habitación Doble del 1 al 3 de octubre por obras».
Parámetros
| Parámetro | Tipo | Nivel | Qué hace |
|---|---|---|---|
resource | texto | obligatorio | Identificador o nombre de la unidad a bloquear: de alojamiento (Alojamientos), de material de alquiler (Recursos y material) o de personal (Personal). Si el nombre resuelve a un producto con variaciones (por ejemplo, un material con tallas), la operación se niega y te devuelve las unidades finales en candidates. |
start_date | fecha | obligatorio | AAAA-MM-DD para un bloqueo por días, o AAAA-MM-DDTHH:mm para uno por horas (solo material de alquiler y personal). Debe usar la misma granularidad que end_date. |
end_date | fecha | obligatorio | Su significado cambia según el tipo de unidad: en alojamientos es el día de salida (esa noche ya no se bloquea); en material de alquiler y personal es el último día bloqueado, inclusive. Por horas, es el instante exacto de fin. |
notes | texto | recomendado | Nota visible en el bloqueo del calendario. Si la omites, se guarda vacía; no es obligatoria en la práctica. |
Qué devuelve
Prueba en seco bloqueando una habitación dos noches:
{
"success": true,
"operation": "create-block",
"dry_run": true,
"resolved_resource": { "_id": "5a5602b07e9fe0036a541d16", "type": "BasicAccommodation", "title": "Alojamiento simple" },
"semantics": { "branch": "accommodation", "end_date_meaning": "día de salida (esa noche NO se bloquea)", "nights_blocked": 2 },
"payload_preview": {
"type": "Blocked",
"startDate": "2026-09-30T22:00:00.000Z",
"endDate": "2026-10-02T22:00:00.000Z",
"resource": "5a5602b07e9fe0036a541d16",
"mode": "unique",
"notes": "Mantenimiento"
},
"warnings": ["NO idempotente: si el rango solapa con un booking/bloqueo existente del recurso, el server responderá 400 collision."]
}| Campo | Significado |
|---|---|
resolved_resource | Qué unidad se eligió a partir del nombre o identificador que diste, y de qué tipo es. |
semantics.branch | accommodation (por noches, end_date = salida), rental_staff (por días, end_date inclusive) u hourly (por horas, intervalo exacto). |
semantics.nights_blocked / days_blocked / hours_blocked | Cuánto va a bloquear en realidad, ya calculado. Compáralo con lo que esperabas antes de confirmar. |
payload_preview | El bloqueo tal cual se enviaría, con las fechas ya convertidas a UTC. |
warnings | Avisa de que la operación no es idempotente: repetirla sobre fechas ya bloqueadas da un error de colisión, no un «ya estaba hecho». |
Con un material de alquiler con tallas (unidad hoja, un día suelto), el bloqueo es por días y end_date es inclusive:
{
"semantics": { "branch": "rental_staff", "end_date_meaning": "último día bloqueado inclusive (+1d en el body)", "days_blocked": 1 },
"payload_preview": { "startDate": "2026-09-30T22:00:00.000Z", "endDate": "2026-10-01T22:00:00.000Z", "resource": "6a37ed55a0cc4a3ec77c6a5b" }
}Y con personal, por horas, el intervalo es exacto (sin redondeos):
{
"semantics": { "branch": "hourly", "end_date_meaning": "instante exacto de fin (intervalo [start, end), sin ajustes)", "hours_blocked": 4 },
"payload_preview": { "startDate": "2026-10-01T08:00:00.000Z", "endDate": "2026-10-01T12:00:00.000Z", "resource": "602a2edd48bcd3005f403474" }
}Errores propios de esta operación
| Situación | Respuesta |
|---|---|
| El nombre no resuelve a ninguna unidad | success: false, error: "resource_unresolved". |
| Bloqueo por horas sobre un alojamiento | success: false, error: "accommodation_hourly_not_supported": el calendario de alojamientos no tiene vista por horas, se bloquea por noches. |
start_date igual a end_date en un alojamiento | success: false, error: "range_degenerate": son 0 noches (el panel lo permite por accidente; esta operación no). |
| El identificador resuelve a un producto con variaciones (tallas, unidades) en vez de a una unidad final | success: false, error: "resource_is_parent", con la lista de unidades válidas en candidates. |
Consejos
- Si te da
resource_is_parent, repite la llamada con uno de los identificadores decandidates: son las unidades finales, las únicas que se pueden bloquear. - Revisa siempre
semanticsantes de confirmar: el significado deend_datecambia según el tipo de unidad y es la causa más común de bloquear una noche de más o de menos. - El bloqueo no comprueba colisiones en la prueba en seco; se comprueba al ejecutar de verdad. Si sospechas solape, revisa antes con
list-blocksfiltrando porresourcey rango.
delete-block: borra un bloqueo por su identificador
Borra un bloqueo de calendario por su block_id. Se niega si el identificador no corresponde a un bloqueo vivo de tu cuenta —porque no existe, ya está borrado o pertenece a una reserva real—, así que nunca toca una reserva por error. Es una operación de escritura: siempre se ejecuta en modo prueba.
Cómo llamarla
curl -X POST https://api.bukyapp.com/v1/ops/delete-block \
-H "Authorization: Bearer bk_TU_TOKEN" \
-H "Content-Type: application/json" \
-d '{"block_id": "694658a75c898dd607a4fde3", "dry_run": true}'Por MCP: «Borra el bloqueo del 1 al 3 de diciembre en la Habitación Doble» (el asistente lo busca antes con list-blocks).
Parámetros
| Parámetro | Tipo | Nivel | Qué hace |
|---|---|---|---|
block_id | texto | obligatorio | Identificador del bloqueo a borrar. Lo obtienes de list-blocks. |
Qué devuelve
Prueba en seco sobre un bloqueo real de la cuenta demo:
{
"success": true,
"operation": "delete-block",
"dry_run": true,
"_id": "694658a75c898dd607a4fde3",
"would_delete": {
"block_id": "694658a75c898dd607a4fde3",
"resource": "5a5602b07e9fe0036a541d16",
"start": "2025-12-01T23:00:00.000Z",
"end": "2025-12-03T23:00:00.000Z",
"notes": null,
"origin": "manual"
},
"reversible": "soft (isDeleted en BD, sin endpoint de restore)",
"warnings": []
}| Campo | Significado |
|---|---|
would_delete | El bloqueo que se borraría, tal como está ahora. En una ejecución real, este mismo bloque confirma lo que se borró. |
reversible | Aunque el borrado se guarda como blando en la base de datos, no hay forma de deshacerlo desde la API ni el panel: trátalo como definitivo. |
Errores propios de esta operación
| Situación | Respuesta |
|---|---|
El block_id no existe, ya está borrado o es una reserva real | success: false, error: "block_not_found". Para reservas reales no hay operación de borrado; es intencional. |
Consejos
- Consigue el
block_idconlist-blocksantes de borrar; no lo adivines. - Para limpiar de golpe los bloqueos huérfanos de un enlace iCal desconectado, contacta con el soporte de Buky en vez de borrarlos uno a uno.
