Centro de ayuda›Desarrolladores›Operaciones de productos de tienda

Operaciones de productos de tienda

Lista, consulta, crea, edita, borra e importa productos de tu tienda por API v1 o MCP.

Un producto de tienda es un artículo físico que vendes junto al resto de tu catálogo: camisetas, material, merchandising… A diferencia de una actividad, un alojamiento o un pack, no tiene fechas ni sesiones: vive en sus variaciones (por ejemplo, cada talla), cada una con su propio precio y su propio stock. Se muestra en tu tienda pública igual que el resto de productos. Más sobre cómo lo ve tu cliente en Cómo se ve tu tienda (catálogo público).

Operaciones de esta página: list-shop-products, get-shop-product, create-shop-product, update-shop-product, delete-shop-product, import-shop-products (solo lectura: list-shop-products, get-shop-product; escritura: el resto).

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-shop-products: lista los productos de tu tienda

Devuelve los productos de tienda: identificador, título, categorías, impuestos, si está desactivado o borrado, sus variaciones (precio y stock) y el stock total. Admite filtro de texto, por estado y por fecha de creación, y tres niveles de detalle. Es de solo lectura: vale con cualquier token.

Cómo llamarla

curl "https://api.bukyapp.com/v1/ops/list-shop-products?q=camiseta" \
  -H "Authorization: Bearer bk_TU_TOKEN"
curl -X POST https://api.bukyapp.com/v1/ops/list-shop-products \
  -H "Authorization: Bearer bk_TU_TOKEN" -H "Content-Type: application/json" \
  -d '{"detail": "descriptive", "lang": "es"}'

Por MCP: «Enséñame los productos de mi tienda» o «Busca camisetas en la tienda».

Parámetros

ParámetroTipoNivelQué hace
qtextoopcionalFiltro por título (contiene el texto, sin acentos), igual que el buscador del panel de Tienda.
disabledbooleanoopcionaltrue trae solo los productos desactivados; false, solo los activos. Si lo omites, salen todos.
include_deletedbooleanoopcionaltrue incluye también los productos que ya no se ven en el panel ni en la tienda (el soporte de Buky puede recuperarlos).
created_from / created_tofechaopcionalRango sobre la fecha de creación, igual que el filtro de fecha del panel.
detailtextoopcionalNivel de detalle: "compact" (por defecto) trae lo justo para identificar y enumerar; "descriptive" añade la ficha completa en texto plano.
langtextoopcionalSolo con detail: "descriptive": idioma de los textos (por ejemplo "es"). Sin lang, cada texto vuelve en todos los idiomas que tengas rellenos.
fullbooleanoopcionaltrue trae el documento completo de cada producto tal cual lo guarda el servidor. Respuesta pesada; gana a detail si pasas los dos.
limitnúmeroopcionalMáximo de productos devueltos. total refleja el total que cumple el filtro, no el recortado.

Qué devuelve

Ejecución real sobre la cuenta demo, que ahora mismo no tiene ningún producto de tienda dado de alta, vista compacta (por defecto):

{
  "operation": "list-shop-products",
  "success": true,
  "detail": "compact",
  "count": 0,
  "total": 0,
  "items": []
}

Con detail: "descriptive", misma tienda vacía:

{
  "operation": "list-shop-products",
  "success": true,
  "detail": "descriptive",
  "count": 0,
  "total": 0,
  "items": []
}
CampoSignificado
detailVista aplicada a items: compact, descriptive o full.
totalTotal de productos que cumplen los filtros, antes de aplicar limit.
countProductos que trae items (después de limit). Si count es menor que total, limit recortó resultados.
itemsEn vista compacta: _id, título, nombre interno, categorías e impuestos, si está desactivado o borrado, sus variaciones (etiqueta, SKU, precio y stock) y el stock total. En descriptive: lo mismo más la ficha completa en texto plano (descripción, categorías por título, métodos de pago…). En full: el documento tal cual lo guarda el servidor.

Consejos

  • Con la tienda vacía como en el ejemplo, es el primer sitio donde comprobar si ya has dado de alta algún producto antes de usar get-shop-product.
  • Para enumerar y decidir con qué producto seguir trabajando, la vista compacta (por defecto) es la más rápida. Pide full solo si necesitas el documento entero: es la respuesta más pesada.

get-shop-product: obtiene un producto por nombre o _id

Devuelve el documento completo y fresco de un producto de tienda, resuelto por nombre o _id. Es de solo lectura: es la forma de comprobar cómo quedó un producto tras crearlo o editarlo. También te da booker_url, el enlace público para comprarlo.

Cómo llamarla

curl "https://api.bukyapp.com/v1/ops/get-shop-product?shop_product=Camiseta%20Buky" \
  -H "Authorization: Bearer bk_TU_TOKEN"
curl -X POST https://api.bukyapp.com/v1/ops/get-shop-product \
  -H "Authorization: Bearer bk_TU_TOKEN" -H "Content-Type: application/json" \
  -d '{"shop_product": "Camiseta Buky"}'

Por MCP: «Enséñame el producto Camiseta Buky de la tienda». O, para pasarle el enlace a un cliente: «Dame el enlace de compra de Camiseta Buky».

Parámetros

ParámetroTipoNivelQué hace
shop_producttextoobligatorioNombre o _id (24 caracteres hexadecimales) del producto. Se resuelve contra el catálogo real.
id / shop_product_idtextoopcionalAlias de shop_product (algunos asistentes usan uno u otro nombre).

El manual marca shop_product como «recomendado», pero al omitirlo la operación responde con un error, no con una lista: es obligatorio en la práctica.

Qué devuelve

Ejecución real: la cuenta demo no tiene productos de tienda dados de alta, así que buscar por un nombre cualquiera no encuentra nada:

{
  "operation": "get-shop-product",
  "success": false,
  "error": "shop_product_unresolved",
  "details": "el customer no tiene ninguna entidad de este tipo configurada",
  "candidates": [],
  "hint": "El customer no tiene ningún producto de tienda configurado todavía."
}

Con un producto real, el manual documenta que la respuesta trae, además, _id (el identificador del producto), resolved (qué producto se eligió y por qué) e item con el documento completo: título, variaciones, impuesto y categorías, y booker_url. La cuenta demo no tiene productos, así que no he podido ver una respuesta con producto real: lo que sigue es lo que documenta el manual.

CampoSignificado
_idIdentificador del producto.
resolvedQué producto se eligió y por qué.
itemDocumento completo y fresco del producto.
booker_urlPágina pública del producto en tu motor de reservas (con tu dominio propio, si lo tienes). Es el enlace para comprarlo.

Comprar no existe como operación de la API ni del asistente: para vender el producto, remite al cliente a booker_url.

Errores propios de esta operación

SituaciónRespuesta
Falta shop_product (y sus alias)200 con success: false, error: "shop_product_intent_required".
Nombre que no coincide con ningún producto200 con success: false, error: "shop_product_unresolved" y candidates con las coincidencias (vacío si la tienda no tiene ningún producto de ese tipo).

create-shop-product: da de alta un producto físico

Crea un producto de tienda con título, impuesto y una o varias variaciones vendibles (precio y stock). Es de escritura: pruébala siempre en seco antes de pedirle al asistente que la ejecute de verdad.

Cómo llamarla

curl -X POST https://api.bukyapp.com/v1/ops/create-shop-product \
  -H "Authorization: Bearer bk_TU_TOKEN" -H "Content-Type: application/json" \
  -d '{"title": "Camiseta Buky", "price_eur": 25, "stock": 10, "tax": "default", "dry_run": true}'

Por MCP: «Crea un producto de tienda llamado Camiseta Buky a 25 euros con 10 unidades de stock».

Parámetros

ParámetroTipoNivelQué hace
titletextoobligatorioTítulo público del producto (en español; el resto de idiomas queda sin traducir hasta que los edites).
price_eur + stocknúmeroobligatorio (forma simple)Precio en euros y stock (entero, 0 o más) de la variación única «Estándar». stock es obligatorio en cuanto das price_eur.
variationslistaobligatorio (forma multi)Alternativa a price_eur/stock: una fila { label, price_eur, stock, sku? } por talla o combinación.
skutextoopcionalSKU de la variación única (solo forma simple).
taxtextorecomendadoImpuesto: "default" (el primero de tu cuenta), un porcentaje, un nombre o un _id. Si lo omites, el producto queda sin impuesto.
descriptiontextoopcionalDescripción del producto (en español).
categorieslistaopcionalNombres o identificadores de categorías (ver Operaciones de categorías). Sin categoría, el producto puede no salir en tu catálogo público, aunque se crea igual.

El manual marca price_eur/stock y variations como «recomendados», pero hace falta al menos uno de los dos: sin ninguno, la operación falla con variations_required.

Qué devuelve

Prueba en seco, forma simple:

{
  "operation": "create-shop-product",
  "dry_run": true,
  "success": true,
  "resolved_tax": { "id": "69a181ce5d6272575493bcfd", "reason": "default (primer tax del customer)" },
  "variations": [
    { "label": "Estándar", "sku": null, "price_cents": 2500, "stock": 10 }
  ],
  "warnings": [
    "sin categoría: el producto puede no aparecer en el catálogo público de la tienda (reservable por enlace directo)."
  ]
}

Prueba en seco, forma multi (dos tallas):

{
  "success": true,
  "resolved_tax": { "id": "69a181ce5d6272575493bcfd", "reason": "default (primer tax del customer)" },
  "variations": [
    { "label": "Talla S", "sku": null, "price_cents": 2500, "stock": 5 },
    { "label": "Talla M", "sku": "CAM-M", "price_cents": 2500, "stock": 8 }
  ]
}
CampoSignificado
resolved_taxImpuesto que se aplicará y por qué se eligió. null si omitiste tax.
variationsLas variaciones que se crearían, ya con el precio pasado a céntimos.
warningsAvisos que no bloquean la creación: por ejemplo, sin categoría el producto no sale en el catálogo público (pero sí es reservable por enlace directo).

Con un producto real (dry_run en false), la respuesta trae además _id: el identificador del producto creado.

Errores propios de esta operación

SituaciónRespuesta
Falta title400 con error: "invalid_params" y el campo en details.
Ni price_eur/stock ni variations200 con success: false, error: "variations_required".
price_eur sin stock200 con success: false, error: "variations_invalid" y code: "stock_invalid".

Consejos

  • Si vendes el mismo artículo en varias tallas, usa variations desde el principio: es un array que se reemplaza entero en update-shop-product, así que empezar bien evita tener que reescribirlo luego.
  • Añade siempre una categoría si quieres que el producto aparezca en tu catálogo público sin depender de un enlace directo.

update-shop-product: edita un producto existente

Edita un producto de tienda ya creado: solo viajan los campos que aportas. Es de escritura.

Cómo llamarla

curl -X POST https://api.bukyapp.com/v1/ops/update-shop-product \
  -H "Authorization: Bearer bk_TU_TOKEN" -H "Content-Type: application/json" \
  -d '{"product": "Camiseta Buky", "stock": 50, "dry_run": true}'

Por MCP: «Pon el stock de Camiseta Buky a 50 unidades».

Parámetros

ParámetroTipoNivelQué hace
producttextoobligatorioProducto a editar: título o _id. Sin coincidencia, la respuesta trae candidatos.
title / descriptiontextoopcionalNuevo título o descripción (en español).
taxtextoopcionalNuevo impuesto ("default", porcentaje, nombre o _id).
categorieslistaopcionalReemplaza las categorías del producto.
variationslistaopcionalReemplaza todas las variaciones: [{ label, price_eur, stock, sku? }]. Excluyente con price_eur/stock/sku.
price_eur / stock / skunúmero / textoopcionalAtajo: cambia solo la primera variación (conserva su identificador y su etiqueta). Excluyente con variations.

Qué devuelve

Prueba en seco sobre un producto ficticio (la tienda demo no tiene ninguno dado de alta ahora mismo, así que la resolución falla en vez de mostrar una vista previa de cambios):

{
  "operation": "update-shop-product",
  "dry_run": true,
  "success": false,
  "error": "product_unresolved",
  "details": "sin match para 'Camiseta Buky Demo'",
  "candidates": [],
  "hint": "Especifica uno de candidates (por título exacto o _id)."
}

Con un producto real, el manual documenta que la respuesta trae _id y changes con la lista de campos modificados.

Errores propios de esta operación

SituaciónRespuesta
Falta product400 con error: "invalid_params".
Nombre o _id que no coincide con ningún producto200 con success: false, error: "product_unresolved" y candidates con las coincidencias.

Consejos

  • Si solo quieres reponer stock o cambiar un precio y el producto tiene una única variación, usa el atajo price_eur/stock/sku: es más simple que reenviar variations entero.
  • Con varias tallas, pasa siempre el array variations completo: lo que no incluyas desaparece.

delete-shop-product: borra un producto

El producto 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 recuperarlo si lo necesitas. Es de escritura.

Cómo llamarla

curl -X POST https://api.bukyapp.com/v1/ops/delete-shop-product \
  -H "Authorization: Bearer bk_TU_TOKEN" -H "Content-Type: application/json" \
  -d '{"product": "Camiseta Buky", "dry_run": true}'

Por MCP: «Borra el producto Camiseta Buky de la tienda».

Parámetros

ParámetroTipoNivelQué hace
producttextoobligatorioProducto a borrar: título o _id. Sin coincidencia, la respuesta trae candidatos.

Qué devuelve

Prueba en seco sobre un producto ficticio (misma tienda vacía):

{
  "operation": "delete-shop-product",
  "dry_run": true,
  "success": false,
  "error": "product_unresolved",
  "details": "sin match para 'Camiseta Buky Demo'",
  "candidates": []
}

Con un producto real, el manual documenta que la respuesta trae _id y confirma el borrado: las órdenes ya hechas con ese producto no se ven afectadas.

Consejos

  • El borrado no toca las reservas u órdenes que ya incluyen ese producto: solo deja de estar disponible para nuevas ventas.

import-shop-products: sube tu tienda entera desde filas

Importa varios productos a la vez, agrupando las filas del mismo título en variaciones (por ejemplo, una fila por talla). Es de escritura, y va siempre en dos pasos: primero una prueba en seco que arma la lista de lo que se crearía junto con un manifest_hash, y solo repitiendo la llamada con ese valor como confirm_hash se ejecuta. Es reanudable: si se corta a mitad, una segunda pasada con el mismo confirm_hash omite los títulos que ya se crearon.

Cómo llamarla

Paso 1, prueba en seco, con filas inline:

curl -X POST https://api.bukyapp.com/v1/ops/import-shop-products \
  -H "Authorization: Bearer bk_TU_TOKEN" -H "Content-Type: application/json" \
  -d '{"rows": [{"title": "Sudadera Buky", "price_eur": "29,90", "stock": "5", "variation": "M"}], "tax": "default"}'

Paso 2, con el manifest_hash que te dio el paso 1:

curl -X POST https://api.bukyapp.com/v1/ops/import-shop-products \
  -H "Authorization: Bearer bk_TU_TOKEN" -H "Content-Type: application/json" \
  -d '{"rows": [...], "tax": "default", "confirm_hash": "<manifest_hash del paso 1>"}'

Por MCP: sube el CSV o Excel a la conversación y pide «Importa estos productos a mi tienda»; el asistente lee el fichero, lo convierte en filas y hace las dos llamadas.

Formato de las filas

Claves (o columnas, si vienes de un CSV): title (obligatoria), price_eur (obligatoria), stock (obligatoria, entero), sku, variation (agrupa varias filas del mismo título en variaciones de un solo producto), tax (por fila; si la omites, se usa el parámetro tax de la llamada), category, description. Máximo 1000 filas por llamada: con más, trocea y repite los dos pasos por cada trozo (los títulos ya creados se omiten solos). Los decimales admiten punto o coma.

Parámetros

ParámetroTipoNivelQué hace
rowslistaobligatorioFilas: array de objetos, una clave por columna. Es la única forma de pasar los datos, tanto por la API como por MCP; no se acepta una ruta de fichero.
taxtextorecomendadoImpuesto por defecto para las filas sin columna tax. Sin él, esas filas quedan sin impuesto.
categorytextoopcionalCategoría por defecto para las filas sin columna category.
confirm_hashtextoopcionalEl manifest_hash que te dio la prueba en seco. Solo con él se ejecuta de verdad, y solo si las filas no han cambiado desde entonces.

Qué devuelve

Prueba en seco real con tres filas por rows (una sudadera en dos tallas y una gorra):

{
  "operation": "import-shop-products",
  "dry_run": true,
  "success": true,
  "manifest": {
    "source": "rows inline (3)",
    "products_total": 2,
    "products_to_create": 2,
    "variations_total": 3,
    "skipped_existing": 0,
    "manifest_hash": "bdd221b566c5783f"
  },
  "sample": [
    {
      "title": "Sudadera Buky",
      "variations": [
        { "label": "M", "sku": null, "price_cents": 2990, "stock": 5 },
        { "label": "L", "sku": null, "price_cents": 2990, "stock": 3 }
      ],
      "taxes": ["69a181ce5d6272575493bcfd"],
      "categories": null
    }
  ],
  "skipped": [],
  "warnings": [],
  "hint": "Para ejecutar: repite con confirm_hash: \"bdd221b566c5783f\"."
}
CampoSignificado
manifest.products_total / products_to_createProductos distintos detectados y cuántos son nuevos (a los que ya existen se les resta).
manifest.skipped_existingTítulos que ya tenías dados de alta y que la importación se saltaría.
manifest.manifest_hashEl valor a repetir como confirm_hash para ejecutar. Cambia si cambian las filas.
sampleLos productos que se crearían, ya agrupados en variaciones y con el precio pasado a céntimos. Recortado a un ejemplo en importaciones grandes.
skippedFilas descartadas y por qué.
hintRepite literalmente la llamada que hace falta para el paso 2.

Repetí la misma llamada con confirm_hash: "bdd221b566c5783f", pero el script de esta guía fuerza siempre dry_run:true en las operaciones de escritura, así que no se puede provocar la ejecución real desde aquí. El manual documenta que, con confirm_hash y dry_run en falso, la respuesta trae created, skipped (títulos que ya existían) y failed.

Errores propios de esta operación

SituaciónRespuesta
Falta rows200 con success: false, error: "rows_missing".

Consejos

  • Por MCP, sube el fichero (CSV o Excel) a la conversación y deja que el asistente lo convierta en rows: es la única vía de importación, esté donde esté corriendo la operación.
  • Si se corta a mitad, repite la llamada tal cual con el mismo confirm_hash: los títulos ya creados se saltan solos y no se duplican.

¿Te ha resultado útil este artículo?