Operaciones de actividades
Lista, consulta, crea, edita y borra actividades por API v1 o MCP: tarifas, cupos, sesiones, personal y publicación.
Una actividad es el producto base de Buky: una clase, salida o experiencia reservable con fecha, hora, aforo y, opcionalmente, personal asignado. Es lo que tus clientes ven y reservan en el motor de reservas, y lo que tú organizas en sesiones desde el panel. Más sobre el concepto en Qué es una actividad en BukyApp.
Operaciones de esta página: list-activities, get-activity, create-activity, update-activity, delete-activity (solo lectura: list-activities, get-activity; escritura: create-activity, update-activity, delete-activity).
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.
list-activities: lista las actividades del centro
Devuelve el catálogo de actividades del centro. Es el paso previo natural para encontrar el identificador exacto de una actividad antes de editarla o borrarla, y admite tres niveles de detalle según lo que necesites ver. Es de solo lectura: vale con cualquier token.
Cómo llamarla
curl "https://api.bukyapp.com/v1/ops/list-activities?q=surf" \
-H "Authorization: Bearer bk_TU_TOKEN"curl -X POST https://api.bukyapp.com/v1/ops/list-activities \
-H "Authorization: Bearer bk_TU_TOKEN" \
-H "Content-Type: application/json" \
-d '{"q": "surf", "detail": "descriptive", "lang": "es"}'Por MCP: «Enséñame las actividades que tengo» o «Busca las actividades que tengan "surf" en el nombre».
Parámetros
| Parámetro | Tipo | Nivel | Qué hace |
|---|---|---|---|
q | texto | opcional | Filtra por título o nombre interno (contiene, sin tildes). Es la búsqueda del panel. |
detail | texto (compact/descriptive) | opcional | Nivel de detalle de cada actividad. compact (por defecto): lo justo para identificar y enumerar. descriptive: textos en plano y categorías resueltas a su nombre, sin tarifas ni flags internos. |
lang | texto | opcional | Solo con detail: "descriptive": cada texto vuelve en un único idioma (por ejemplo "es"; si falta, cae a español o al primero disponible). Sin lang, cada texto es un objeto {idioma: texto} con los idiomas rellenos. |
full | booleano | opcional | true devuelve el documento completo de cada actividad (tarifas, idiomas, personal…), más pesado. Gana a detail si mandas los dos. |
private | booleano | opcional | true solo actividades de sesiones privadas (no admiten más reservas tras la primera); false solo compartidas. Por defecto, todas. |
disabled | booleano | opcional | true solo desactivadas, false solo activas. Por defecto, todas. |
created_from, created_to | fecha | opcional | Rango sobre la fecha de creación. |
limit | número | opcional | Máximo de resultados, tras aplicar los filtros. |
Qué devuelve
Vista compact (por defecto), ejemplo real recortado:
{
"success": true,
"detail": "compact",
"count": 13,
"total": 13,
"items": [
{ "_id": "5b98cbdc749e2af7dda1da69", "title": "Actividad", "internalName": null, "categories": [], "is_disabled": false, "private": false, "pax_min": 1, "pax_max": null },
{ "_id": "69dba4e53f831f958dbdff7c", "title": "Surf Avanzado", "internalName": null, "categories": [], "is_disabled": false, "private": false, "pax_min": 1, "pax_max": null }
]
}Vista descriptive con lang: "es", ejemplo real recortado:
{
"success": true,
"detail": "descriptive",
"count": 13,
"total": 13,
"items": [
{
"_id": "5b98cbdc749e2af7dda1da69",
"title": "Actividad",
"internalName": null,
"short_description": null,
"description": "descripción de la actividad",
"included": [], "not_included": [], "requirements": [],
"alert_text": "La hora de la clase puede variar según las condiciones meteorológicas",
"level": null,
"meeting_point": null,
"cancellation_policy_mode": "general",
"cancellation_policy": null,
"categories": [],
"payment_mode": "none",
"payment_advance_mode": "percent",
"payment_advance_percent": 20,
"payment_advance_fixed": 0,
"need_pax_data": false,
"is_disabled": false,
"private": false,
"by_request": false,
"not_bookable_standalone": false,
"pax_min": 1,
"pax_max": null,
"duration_min": 60
}
]
}| Campo | Significado |
|---|---|
detail | La vista que se aplicó: compact, descriptive o full. |
count | Cuántas actividades se devuelven en items. |
total | Cuántas cumplen los filtros antes de aplicar limit. Si count es menor que total, limit recortó resultados. |
items[]._id | El identificador que necesitas para get-activity, update-activity, etc. |
items[].internalName | Nombre interno del listado admin. Puede venir vacío: no se deriva del título. |
items[].is_disabled, .private | Estado y privacidad, como los filtros del panel. Presentes en compact y descriptive. |
items[].categories | En compact, identificadores; en descriptive, nombres ya resueltos. |
items[].description, .alert_text (solo descriptive) | Con lang, un texto plano en ese idioma; sin lang, un objeto {idioma: texto}. |
items[].payment_mode, .need_pax_data, .by_request, .not_bookable_standalone (solo descriptive) | Condiciones de pago y de reserva de la actividad. |
Las actividades borradas no aparecen aquí.
Consejos
- Con dos actividades con el mismo título (pasa: en la cuenta de ejemplo hay dos «surf de prueba c1»), pide
full:trueo cruza porinternalNamepara no operar sobre la que no toca. detail:"descriptive"es el punto intermedio entrecompactyfull: sirve para mostrarle el catálogo a un cliente o revisar textos, sin cargar tarifas ni flags internos.
get-activity: detalle completo de una actividad
Devuelve el documento completo y fresco de una actividad: tarifas, impuesto, capacidad, modo de reserva, personal, todo. Es la forma de comprobar cómo quedó una actividad tras crearla o editarla, y de conseguir su identificador exacto. Es de solo lectura: vale con cualquier token.
Cómo llamarla
curl "https://api.bukyapp.com/v1/ops/get-activity?activity=Surf%20Principiante%20en%20piscina" \
-H "Authorization: Bearer bk_TU_TOKEN"curl -X POST https://api.bukyapp.com/v1/ops/get-activity \
-H "Authorization: Bearer bk_TU_TOKEN" \
-H "Content-Type: application/json" \
-d '{"activity": "Surf Principiante en piscina"}'Por MCP: «Enséñame el detalle de la actividad Surf Principiante en piscina».
Parámetros
| Parámetro | Tipo | Nivel | Qué hace |
|---|---|---|---|
activity (alias id, activity_id) | texto | recomendado | Nombre, nombre interno o identificador de la actividad. Si el nombre no resuelve a una sola, la respuesta trae los candidatos. |
Qué devuelve
Ejemplo real, recortado (esta actividad concreta hereda sus sesiones de otra, ver más abajo):
{
"success": true,
"_id": "6aa3db20f4b405ea4e3dfc20",
"resolved": { "id": "6aa3db20f4b405ea4e3dfc20", "reason": "match exacto por nombre 'Surf Principiante en piscina'" },
"item": {
"_id": "6aa3db20f4b405ea4e3dfc20",
"title": { "es": "Surf Principiante en piscina" },
"activities_capacity": 6,
"activities_duration": 60,
"activities_bookingMode": "scheduled_in_other_activity",
"activities_useSessionsFrom": "69dba4d4b227f96a4e3b21a8",
"activities_private": false,
"notBookableStandalone": false,
"haveRatesByPersonRange": false,
"priceFrom": 6000,
"taxes": ["69a181ce5d6272575493bcfd"],
"rates": [
{ "description": { "name": "Adulto" }, "price": 6000, "season": null, "_id": "6aa3dc3601ec3b760f91c62d" },
{ "description": { "name": "Temporada 2027" }, "price": 7500, "season": { "start": "2027-01-01", "end": "2027-06-21", "active": true }, "_id": "6aa3dc3697a76a5a4a6279a2" }
]
}
}| Campo | Significado |
|---|---|
_id | Identificador de la actividad resuelta. |
resolved | Qué actividad se eligió a partir de tu texto y por qué. Compruébalo cuando el nombre sea ambiguo. |
item.activities_capacity | Plazas por sesión. |
item.activities_duration | Duración por defecto, en minutos, de las sesiones nuevas. |
item.activities_bookingMode | Cómo gestiona sus sesiones: scheduled (normal, tiene sesiones propias), scheduled_in_other_activity (no tiene sesiones propias: hereda las de la actividad de activities_useSessionsFrom, útil para vender el mismo horario con otro precio o nombre), TimePeriod, date_enquiry, no_date. |
item.priceFrom | Precio «desde» en céntimos, el que se muestra en el catálogo público. |
item.rates[] | Tarifas activas: nombre, precio en céntimos y, si aplica, temporada. |
item.taxes[] | Impuesto aplicado (identificador). |
Errores propios
| Situación | Respuesta |
|---|---|
| Nombre que no coincide con ninguna actividad, o coincide con varias | success: false, error: "activity_unresolved" y activity_candidates con las opciones. Repite con el nombre exacto o el _id. |
create-activity: crea una actividad nueva
Crea una actividad con su modo de precio, personal y calendario. Es una operación de escritura: consulta siempre primero list-activities para no duplicar por error, y prueba en seco antes de confirmar.
Cómo llamarla
curl -X POST https://api.bukyapp.com/v1/ops/create-activity \
-H "Authorization: Bearer bk_TU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Prueba documentación",
"internal_name": "prueba-documentacion",
"price_eur": 30,
"color": "#1273de",
"capacity": 6,
"dry_run": true
}'Por MCP: «Crea una actividad llamada Prueba documentación a 30€, con 6 plazas y color azul».
Parámetros
Modo de precio: elige uno de estos tres (mandar más de uno da error):
| Parámetro | Tipo | Nivel | Qué hace |
|---|---|---|---|
price_eur | número | recomendado | Modo plano: una sola tarifa base, en euros. |
rate_ranges | array | recomendado | Modo por tamaño de grupo: [{from, to, price, name?}], una tarifa distinta según cuántas personas reserven. Es el patrón habitual en clases de surf. |
rates | array | recomendado | Modo tarifas avanzado: [{name, price_eur, season?, quantity?, pax?, color?}], para combinar temporadas, cantidades y rangos de personas en una sola tabla. |
variations | array | opcional | Modo por tipo de persona (adulto/niño…): [{name, price}]. |
no_price | booleano | opcional | Actividad sin tarifa (bloqueo administrativo). Incompatible con cualquier otro parámetro de precio. |
pricing_mode | texto | opcional | Fuerza el modo (flat/group_range/person_type) si prefieres no dejarlo a la inferencia. |
Datos básicos y sesiones:
| Parámetro | Tipo | Nivel | Qué hace |
|---|---|---|---|
title | texto | obligatorio | Título público. |
internal_name | texto | recomendado | Nombre interno del listado admin. Si lo omites, queda vacío: no se deriva del título. |
capacity | número | recomendado | Plazas por sesión. Por defecto, 6. |
duration | número | recomendado | Duración por defecto de las sesiones, en minutos. Por defecto, 60. |
color | texto | recomendado | Color del calendario, en hex (#1273de). Si lo omites, se hereda el color por defecto de la paleta. Solo se aplica en modos con calendario propio. |
tax | texto | recomendado | Impuesto: "default", "21%", "IVA" o un identificador. Por defecto, el impuesto por defecto del centro. |
description | texto | opcional | Descripción pública. |
booking_mode | texto | opcional | Por defecto scheduled (la actividad gestiona sus propias sesiones). Con scheduled_in_other_activity la actividad no tiene sesiones propias y hereda las de otra (exige useSessionsFrom). |
useSessionsFrom | texto | opcional | Solo con booking_mode: "scheduled_in_other_activity": la actividad de la que se heredan las sesiones. |
price_from_eur | número | opcional | Precio «desde» que se muestra en el catálogo. Si lo omites, se calcula solo a partir de las tarifas. |
rate_name | texto | opcional | Nombre de la tarifa base en modo plano. Por defecto, «Adulto». |
Personal y publicación (opcionales; se resumen porque son muchos):
| Parámetro | Tipo | Nivel | Qué hace |
|---|---|---|---|
staff | array | opcional | Personal que puede servir la actividad (nombres o identificadores). Su sola presencia activa el control de personal. |
staff_mode, staff_control_avail, staff_random_assign, staff_min | texto/booleano/número | opcional | Cómo se usa ese personal: solo listarlo (available, por defecto), exigir disponibilidad (strict, con staff_min de mínimo libre) o asignarlo al azar (random, exige strict activado). |
private | booleano | opcional | Actividad privada. Por defecto, false. |
not_bookable_standalone | booleano | opcional | true: la actividad solo se vende dentro de un pack, desaparece de las búsquedas y de la ficha pública. |
categories, extras | array | opcional | Categorías y extras asociados (nombres o identificadores). |
ships, ships_excluded | array | opcional | Solo actividades de buceo/travesías: barcos admitidos o excluidos. |
thumb | texto | opcional | Foto destacada: identificador de un archivo ya subido (el que te da el chat al adjuntar una imagen) o una URL pública. Se aplica tras crear la actividad. Ver Operaciones de imágenes. |
gallery | array | opcional | Galería: lista de imágenes, cada una identificador de un archivo ya subido o una URL pública. |
Qué devuelve
Prueba en seco real:
{
"success": true,
"dry_run": true,
"applied_defaults": { "activities_capacity": 6, "activities_bookingMode": "scheduled", "activities_color": "#1273de" },
"resolved_tax": { "id": "69a181ce5d6272575493bcfd", "reason": "default (primer tax del customer)" },
"resolved_pricing": { "mode": "flat", "base": { "name": "Adulto", "price_cents": 3000, "via": "priceFrom (sin rates, como el front)" } },
"payload_preview": { "title": { "es": "Prueba documentación" }, "activities_capacity": 6, "internalName": "prueba-documentacion", "priceFrom": 3000, "activities_color": "#1273de" },
"warnings": [
"ACTIVIDAD AÚN NO VENDIBLE: se creó con priceFrom pero SIN tarifas. PASO 2 OBLIGATORIO: update-activity con rates:[{name,price_eur,quantity:1}]."
]
}| Campo | Significado |
|---|---|
applied_defaults | Los valores que se aplicaron porque no los diste (capacidad, modo de reserva, color). |
resolved_tax | El impuesto que se aplicó y por qué. |
resolved_pricing | El modo de precio detectado y la tarifa resultante. |
payload_preview | Lo que se enviaría al servidor si no fuera una prueba en seco. |
warnings | Avisos a leer siempre. |
Consejos
- En modo plano (`price_eur`), la actividad se crea sin tarifa todavía vendible: solo queda el precio «desde» (
priceFrom), y la respuesta lo avisa conwarnings. Para que sea reservable de verdad, sigue conupdate-activitymandandorates: [{"name": "Adulto", "price_eur": 30, "quantity": 1}]. Esto no lo dice el manual de forma explícita: se ha comprobado en la ejecución. capacity,durationycolorson la base de las sesiones que se generen para esta actividad; si trabajas con sesiones sueltas, revisa también Operaciones de sesiones.- Antes de crear, ejecuta
list-activitiescon el nombre que vas a usar para comprobar que no exista ya. - Con
thumbogallery, una URL pública queda a la espera de subida: la prueba en seco lo muestra enimages_pending(verificado en ejecución). Una ruta de archivo local ya no funciona: la operación no la reconoce ni como identificador ni como URL.
update-activity: edita una actividad existente
Cambia solo los campos que le pases: el resto de la actividad queda intacto. Es una operación de escritura.
Cómo llamarla
curl -X POST https://api.bukyapp.com/v1/ops/update-activity \
-H "Authorization: Bearer bk_TU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"activity": "Prueba documentación",
"title": "Prueba documentación editada",
"price_eur": 32,
"capacity": 8,
"dry_run": true
}'Por MCP: «Cambia el título de Prueba documentación a "Prueba documentación editada" y súbele el precio a 32€».
Parámetros
| Parámetro | Tipo | Nivel | Qué hace |
|---|---|---|---|
activity | texto | obligatorio | Actividad a editar: nombre, nombre interno o identificador. |
title | texto | recomendado | Nuevo título público. No afecta a otros idiomas. |
price_eur | número | recomendado | Nuevo precio de la tarifa base (la primera). Conserva su identificador; reenvía el resto de tarifas tal cual. |
capacity | número | recomendado | Nuevas plazas por sesión. |
El resto son opcionales (se agrupan por bloque porque son muchos; cada uno reemplaza el valor anterior salvo que se indique lo contrario):
| Bloque | Parámetros | Qué hacen |
|---|---|---|
| Datos básicos | description, internal_name, duration, color, alert_text, tags, thumb, gallery | Descripción, nombre interno, duración por defecto de sesión, color del calendario, aviso público y etiquetas. thumb (foto destacada) y gallery (galería) aceptan identificador de archivo ya subido o URL pública, igual que en create-activity; gallery sustituye la galería entera. |
| Tarifas e impuestos | rate_name, rates, have_rates_by_person_range, tax, rates_by_full_group | rates reemplaza la tabla de tarifas entera (no se puede combinar con price_eur/rate_name); tax cambia el impuesto. |
| Cupos y condiciones de reserva | pax_min, pax_max, min_sessions, max_sessions, min_per_day, max_per_day, min_time_to_book, complete_sessions, need_pax_data, checkin_mode | Personas y sesiones mínimas/máximas por reserva, antelación mínima y modo de check-in online. |
| Personal | staff, staff_mode, staff_control_avail, staff_random_assign, staff_min | Igual que en create-activity; pasa staff: [] para vaciar el pool. |
| Visibilidad y publicación | not_bookable_standalone, hide_public_avail, show_location, show_origin_count, group_by_customer, staff_per_person, let_advanced_front | Cómo se muestra la actividad y sus sesiones en el booker y en el panel. |
| Catálogo | categories, extras | Reemplazan el conjunto entero de categorías o extras asociados. |
Qué devuelve
Prueba en seco real:
{
"success": true,
"dry_run": true,
"_id": "6aa3db20f4b405ea4e3dfc20",
"changes": {
"title": { "es": "Prueba documentación editada" },
"activities_capacity": 8,
"rates": [
{ "description": { "name": "Adulto" }, "price": 3200, "season": null, "_id": "6aa3dc3601ec3b760f91c62d" },
{ "description": { "name": "Temporada 2027" }, "price": 7500, "season": { "start": "2027-01-01", "end": "2027-06-21" }, "_id": "6aa3dc3697a76a5a4a6279a2" }
]
},
"note": "PUT parcial: solo estos campos cambian."
}| Campo | Significado |
|---|---|
changes | Exactamente lo que va a cambiar, ya resuelto (por ejemplo, price_eur se traduce a la tarifa base dentro de rates, conservando el resto de tarifas que ya tuviera). |
note | Recuerda que es un cambio parcial: los campos que no mandaste no se tocan. |
Consejos
- Al cambiar
price_eur, la respuesta reenvía la tabla de tarifas completa (rates) aunque solo hayas tocado la primera: es la actividad real, no un cálculo aparte. Compruébala si la actividad tiene tarifas por temporada. - Cambiar el
titlese propaga a las sesiones futuras de esa actividad. - Con
thumbogallery, la prueba en seco confirma la URL enimages_checkantes de aplicarla (verificado en ejecución); si mandas una ruta local en vez de un identificador o una URL, no la reconoce.
delete-activity: borra una actividad
La actividad deja de verse en el panel y en la tienda. No puedes deshacerlo desde la API ni desde el asistente, pero el soporte de Buky puede recuperarla si lo necesitas. Antes de borrar, avisa de las sesiones futuras y de si tienen reservas. Es una operación de escritura.
Cómo llamarla
curl -X POST https://api.bukyapp.com/v1/ops/delete-activity \
-H "Authorization: Bearer bk_TU_TOKEN" \
-H "Content-Type: application/json" \
-d '{"activity": "Prueba documentación", "confirm": true, "dry_run": true}'Por MCP: «Borra la actividad Prueba documentación» (el asistente te pedirá confirmación antes de marcar confirm: true).
Parámetros
| Parámetro | Tipo | Nivel | Qué hace |
|---|---|---|---|
activity | texto | obligatorio | Actividad a borrar: nombre, nombre interno o identificador. |
confirm | booleano | recomendado | Tiene que ser true para que la operación se ejecute de verdad; sin él, se queda en prueba en seco. Es una salvaguarda propia de esta operación, además de la del script de esta página. |
Qué devuelve
Prueba en seco real, con confirm: true:
{
"success": true,
"dry_run": true,
"would_delete": { "_id": "6a35694ba0cc4a3ec76347cd", "name": "surf de test 4" },
"soft_deleted": false,
"reversible": true,
"dependencies": {
"future_sessions": 0,
"future_sessions_with_bookings": 0,
"note": "El server NO borra estas sesiones ni bloquea: quedarán apuntando a la actividad borrada. Las reservas existentes siguen vivas (libéralas vía Order)."
},
"warnings": []
}| Campo | Significado |
|---|---|
dependencies.future_sessions | Cuántas sesiones futuras tiene la actividad. |
dependencies.future_sessions_with_bookings | Cuántas de esas sesiones tienen reservas. Si hay alguna, revísalo antes de confirmar: las reservas existentes no se cancelan ni se avisa al cliente, y las sesiones quedan apuntando a una actividad borrada. |
reversible | true: el soporte de Buky puede recuperarla si lo pides. |
Errores propios
| Situación | Respuesta |
|---|---|
| Nombre que coincide con varias actividades (pasa con títulos duplicados, como «surf de prueba c1» en la cuenta de ejemplo) | success: false, error: "activity_unresolved" y activity_candidates con las opciones para desambiguar por identificador. |
Consejos
- Si
dependencies.future_sessions_with_bookingses mayor que 0, gestiona esas reservas antes de borrar: el borrado no las toca ni las libera.
