Leer el catálogo funciona con la conexión básica. Escribir no: hace falta
catalog_write en la URL con la que conectaste. El grupo de escritura arrastra
el suyo de lectura, así que dentro del catálogo nunca escribes a ciegas — pero
una lista explícita reemplaza al set por defecto, así que ?features=catalog_write
a secas te deja sin conversaciones ni manual. Con ?features=all lo tienes todo.
Los cuatro parámetros, en La URL de conexión.Las cuatro herramientas
Eso es todo. No hay una herramienta que suba un CSV ni que se conecte a tu
tienda: quien lee el fichero o la tienda es tu asistente, y luego escribe el
resultado con
upsert_products.
La regla que evita desastres
upsert_products no es un parche. Cada producto que mandas es una fila
completa que reemplaza a la que había, igual que la subida de un CSV: una
celda que no mandas se escribe vacía.
Por eso el orden correcto es siempre el mismo:
1
Leer
get_product con el id del producto. Te devuelve la fila entera.2
Cambiar solo lo tuyo
Sobre esa fila, tocar únicamente lo que pediste cambiar.
3
Escribir
upsert_products con la fila completa, no con el campo suelto.4
Verificar
Releer con
get_product o list_products y comprobar el resultado.upsert_products revisa que
cada fila declare:
namedescription(valenull, pero la clave tiene que estar)activeyvisibility- su forma:
has_variantsenfalseconsku,priceycurrency, ohas_variantsentruecon todas sus variantes completas.
get_product. No es burocracia: sin description
el catálogo borraría la descripción, y sin active reactivaría un producto que
tenías apagado.
Frases para copiar y pegar
Cargar un catálogo desde un fichero que le pasas al asistente:Cargar un catálogo de cero
- Máximo 100 productos por llamada. Si tienes 400, son cuatro llamadas.
- Los errores llegan fila a fila. La llamada puede responder que fue bien y
traer dentro cinco filas fallidas. Pide siempre
created,updatedyerrors. - Cada fila que sale bien te devuelve su
product_idenresults. Ese id vale tal cual paraget_product. - Nombres claros y únicos: el identificador interno sale del nombre.
Si tu catálogo viene sincronizado de una tienda
Los productos que entran a OptiMind sincronizados desde una tienda son de solo lectura para el puente.upsert_products los rechaza con
producto sincronizado (solo lectura) y delete_product también. Se leen
bien; no se editan desde aquí.
Precios y monedas
La moneda vive en cada variante, no en el negocio. Un mismo catálogo puede tener productos en soles y productos en dólares. Al leer un producto con varias variantes,get_product te da un resumen, no la
verdad completa:
pricees el mínimo entre sus variantes.currencyes la de la primera variante. Si esa variante no tiene moneda guardada, leesPENaunque nadie lo haya escrito nunca.
variants.
Precio por cantidad
Un producto puede llevar una escala de precios (price_tiers): tramos exactos
{qty, total}, un tramo abierto beyond con {min_qty, unit} y una promoción
con fecha de fin. Reglas que verifica el sistema al escribir:
- La escala exige moneda uniforme entre las variantes del producto. Con dos monedas, la fila rebota.
- Un tramo exacto que quede tapado por el tramo abierto rebota con un mensaje que te dice cuál.
- Los precios por unidad con más de dos decimales rebotan: no se pueden cobrar.
El límite de dos decimales vale tanto para el
totalde cada tramo como para elunitdel tramo abierto. - Hace falta un tramo de una unidad, las cantidades no se repiten y los totales tienen que crecer de tramo en tramo.
- Mandar
price_tiersennullborra la escala. No mandar la clave la deja como estaba.
get_product. list_products no la trae, así que
«no la veo en la lista» no significa que no exista.
Variantes
Una variante es cada versión vendible: talla, sabor, presentación. Su identidad es unid propio, y ese id es lo que enlaza tus pedidos y tu stock.
Cuando actualizas un producto con variantes, mandas todas:
- Una variante que existe y no mandas se elimina.
- Una variante que mandas sin su
idcrea otra nueva y borra la vieja: los pedidos y el stock que apuntaban a ella se quedan sin referencia. Hay una sola excepción: una única variante entrante contra un producto que tiene una sola variante se adopta (es el reenvío del producto simple). Con dos o más, elides obligatorio. - Cada variante va completa:
sku,title,price,currencyyoptions.nullvale; ausente borra.
has_variants: false, con su SKU y
su precio al nivel raíz. Reenviarlo así no rompe referencias —la variante se
adopta y conserva su id—, pero borra su título y sus opciones: la fila simple
no los lleva. Si esa variante tiene título u opciones que importan, reenvíala
como has_variants: true con su id, title y options leídos de
get_product.
Stock: el catálogo no lo escribe
La cantidad no se toca desde aquí. Vive en el libro de Inventario y solo se mueve registrando un movimiento en el panel. Aunque mandes una cantidad enupsert_products, no se escribe.
Lo que sí lees:
inventory_qtycon número: la suma de las variantes que llevan control.inventory_qtyennull: el producto no lleva control de stock. Así se representa el «stock infinito»: no es un cero, es la ausencia de control, y el agente lo sigue ofreciendo igual.
Encender o apagar el control de stock de un producto tampoco se puede hacer
desde el asistente:
upsert_products no tiene ese campo. Eso se declara en el
panel, en Inventario.orders en tu conexión (con
?features=all, o nombrándolo en una lista que incluya todo lo que uses), hay
una lectura aparte, list_stock, con el saldo por almacén. Ojo: el contador del
catálogo y el total del libro de inventario pueden no coincidir, y la
herramienta te devuelve los dos precisamente para que lo veas.
Activo y visible no son lo mismo
Son dos interruptores distintos, y solo uno hace lo que esperas:active: falsedeja el producto fuera de lo que tu agente encuentra cuando busca en el catálogo. Es la forma de retirar algo sin borrarlo.visibility: hiddenfiltra la herramientalist_products, pero la búsqueda del agente de WhatsApp no mira ese campo. Ocultar un producto no impide que el agente lo ofrezca.
active: false.
Entrega digital
Un infoproducto entrega por variante: un archivo de tu Librería (access_file_id) o un enlace (access_url). Aquí la regla de «lo que no
mandas se borra» no aplica: si la fila no menciona esas dos claves, la
entrega se conserva. Mandar null explícito sí la apaga.
Imágenes
get_product te las lista, pero upsert_products no las toca: subir un
lote no borra ni cambia las fotos de tus productos. Las imágenes se gestionan
en el panel.
Borrar es definitivo
delete_product borra el producto con sus variantes e imágenes. No hay
papelera. Consecuencias reales:
- Si una variante está atada a un checkout activo, el borrado rebota con error. Es una protección, no un fallo.
- Las ventas y pedidos pasados que apuntaban a esas variantes pierden la referencia a qué se vendió.
active: false, no borrar. Tu asistente te pedirá
confirmación —la herramienta está marcada como destructiva—, y ese es el momento
de pensarlo.
Trampas verificadas
- Un lote «exitoso» puede traer filas rotas. Los errores viajan dentro de la
respuesta, no como fallo de la llamada. Revisa
errorssiempre. - Un producto simple sin SKU no se puede reenviar tal cual.
get_productte lo devuelve comonull, pero la fila simple no aceptanullahí. Que tu asistente mande una cadena vacía. - El tipo de producto que no se reconoce se ignora en silencio. Solo valen
physical,serviceydigital(o «físico», «servicio», «digital», «infoproducto»). Escribir «Colchón» no da error: simplemente no cambia nada. - Los textos del catálogo llegan marcados como datos, no como órdenes. Si un
nombre o una descripción puede confundirse con una instrucción, viaja entre
delimitadores tipo
<<<UNTRUSTED_DATA_…>>>. Si tu asistente intenta reescribirlos con esos delimitadores dentro, la escritura rebota: tiene que mandar el texto de dentro, limpio. Es a propósito. - El puente nunca cobra. Editar el catálogo no emite links de pago ni toca tu pasarela. Los detalles en Seguridad.