Ventas: cómo funciona
Ventas es tu agente de ventas por chat. Atiende a cada cliente, resuelve sus dudas con los documentos del espacio, le cotiza el envío, arma el pedido y, si lo conectas al cobro, crea la orden y recibe el comprobante de pago. Ninguna cifra la inventa: precios, envíos y totales salen de tu catálogo, tus tarifas o tus reglas. Si no puede cotizar algo, lo dice y avisa de que conviene pasar la conversación a una persona.
Por la API lo conectas a tu canal (WhatsApp, el chat de tu web, tu CRM): mandas cada mensaje del cliente y recibes la respuesta, en qué punto va la venta, la cotización y si hace falta alguien de tu equipo. También lees tus leads, ajustas lo que dice el agente y mantienes sus tarifas de envío y su inventario.
También puedes hacerlo desde la consola: en el Estudio de un espacio con el módulo activo, el panel Ventas edita las frases del agente (su guion) y enseña el embudo de leads.
Antes de empezar
- El espacio tiene que tener el módulo Ventas:
ventassale en sus módulos enGET /api/companies. Si no, cada ruta responde 403módulo no habilitado para este espacio. - Conversar y enviar comprobantes vale con cualquier clave, también una lee. Cambiar la configuración, mover leads, reiniciar conversaciones, cotizar a mano y tocar tarifas o inventario pide una clave escribe. Leer vale con cualquiera.
- Las rutas cuelgan de
/api/mod/ventas/{espacio}/, con la misma clave y los mismos límites que el resto de la API. - Copia cada ruta tal cual, con su barra final si la lleva (
conversations/,leads/,inventory/). Sin ella la respuesta es un 307 vacío. - Conversar gasta créditos de la bolsa de tu cuenta: ver créditos.
Una conversación, paso a paso
- Elige un
session_idpor chat (el número del cliente en tu canal, el id del hilo) y úsalo en todos sus mensajes. Con él, Ventas recuerda el carrito, la ciudad, el método de pago y el pedido abierto. - Manda cada mensaje a conversar con
question,session_idy elmsg_idde tu canal. Si tu webhook reintenta, el mismomsg_iddevuelve la misma respuesta sin repetir el turno. - Contesta a tu cliente con
responses(uno o dos mensajes, en orden). En el primer turno llega ademásaviso_privacidad: enséñaselo. Si vieneopciones, puedes pintarlas como botones. - Pásale
consent: truecuando tu cliente autorice el seguimiento comercial: solo así se guarda su contacto. - Si llega
handoff: true, pasa la conversación a alguien de tu equipo (ver abajo). - Si el cliente manda una imagen o un PDF (el comprobante de pago), pásalo a comprobante con el mismo
session_id. - Para empezar de cero (un botón «nueva conversación», una prueba), reinicia la sesión. Sin eso, una sesión olvida su estado tras unas 48 h sin mensajes.
Si prefieres eventos, conversar por SSE recibe el mismo cuerpo. El mensaje no llega palabra a palabra: Ventas comprueba cada cifra antes de enviarla y manda el texto entero.
En un espacio con Ventas, la ruta del núcleo POST conversations también llega a este agente, con question, session_id y consent. La del módulo añade msg_id.
Estados de la conversación
Cada respuesta trae su estado. Lo decide el código, no el texto: puedes apoyarte en él para tus métricas o tu CRM.
saludo → descubrimiento → rag_producto
↘ recoleccion_slots → cotizacion → cierre
cualquiera → handoff (conviene que siga una persona)| ESTADO | QUÉ PASA |
|---|---|
saludo | Primer contacto. |
descubrimiento | Charla o preguntas generales, sin intención de compra clara. |
rag_producto | Respondió sobre un producto con lo que dicen tus documentos. |
recoleccion_slots | Le faltan datos para seguir (producto, cantidad, ciudad, método de pago, datos de envío) y los está pidiendo. |
cotizacion | Acaba de cotizar: las cifras están en cotizacion. |
cierre | Confirma el pedido, pide el pago o sigue un pedido abierto. |
handoff | Conviene que siga una persona. |
status_code es aparte: "1000" respondió; "1001" no tenía información para eso y contestó con tu refusal_fuera_dominio.
Cuándo pasa a una persona
El agente no improvisa lo que no sabe. Marca handoff: true cuando no hay tarifa para ese destino o ese producto, cuando un producto no tiene precio, cuando el cliente pide hablar con alguien, en las gestiones de posventa (estado de un pedido, devoluciones, garantías, quejas) o cuando falla el cobro. El mensaje para el cliente ya lo dice, con tu mensaje_handoff o la frase de soporte que toque.
Lo que te toca: avisar a tu equipo y, si tu canal lo permite, pausar las respuestas automáticas en esa conversación. Por SSE, el evento handoff trae además un reason corto para tus registros.
El agente: su configuración
GET leads-config te da todo lo que define al agente y PATCH leads-config cambia solo lo que mandes. Los cambios valen desde el siguiente mensaje.
- Quién es:
name,saludo,modo_venta(atención o venta consultiva) y sus instrucciones (system_prompt,system_prompt_venta). - Con qué se conecta: tus documentos (
cerebro_activo), Comercial para envíos y métodos de pago (comercial_activo), Marca para la voz (marca_activa), Comprensión (comprension_activa), el cobro (facturacion_activo) y el stock (inventario_activo,inventario_delegado). - Cómo vende: carrito de varios productos (
carrito_activo), botones para elegir (whatsapp_botones_combo_activo), aviso de stock bajo, alternativas a lo agotado, el enlace a tu catálogo (catalogo_url).
Las frases del agente
Todo lo que el agente dice sin redactar lo escribes tú: los campos mensaje_*, msg_*, cta_* y pregunta_*. Las cifras nunca van en la frase: entran por sus variables, con el valor que calcula Ventas.
saludo ¡Hola! Soy el asistente de {name}. …
mensaje_precio El precio de {nombre} es {precio}. ✨
mensaje_carrito_agregado ¡Anotado! Llevas: {resumen}. ¿Sumamos algo más o vamos con el pago? 🛒
mensaje_cotizacion_envio El envío a {destino} cuesta {envio}: tu pedido quedaría en {total} …
mensaje_checkout ¡Perfecto! El total de tu pedido es {total}. … {cuentas} … vence {expira}.
mensaje_catalogo Aquí puedes ver todo nuestro catálogo: {url}- Usa solo las variables que la frase trae por defecto (míralas en GET). Una llave sin cerrar o una variable que la frase no conoce puede dejarla sin enviar o con la llave a la vista.
- Si una frase termina en pregunta, que siga terminando en pregunta: el agente decide el siguiente paso según eso. Las preguntas de cierre («¿vamos con el pago?») son las que tu cliente suele copiar al responder; cámbialas con cuidado.
- La respuesta de GET trae además ajustes de afinado del agente. No te apoyes en ellos ni los cambies.
Leads y su embudo
El agente registra un lead cuando un cliente cotiza o compra. Su lead_id llega en la respuesta del turno que lo registró: guárdalo junto a tu conversación.
nuevo → contactado → ganado | cerrado
ganado lo pone Ventas sola al confirmarse el pago del pedido- Lista los leads (por estado si quieres) y muévelos cuando tu equipo los contacte o los cierre.
- El contacto nunca sale en claro:
contacto_maskeddice qué datos dejó (nombre=<PERSON>; telefono=<PHONE>), y solo si dio su consentimiento. Para hablar con él, usa tu conversación.
Tarifas de envío
Sin el módulo Comercial, el envío se cotiza con tus tablas de tarifas. Una tabla es una versión: entra como borrador, la revisas y la activas. Solo la versión validada cotiza, y solo hay una.
subir (draft) → revisar filas → corregir o borrar → recargos → activar (validada)
activar otra → la anterior pasa a retirada- Sube la tabla en CSV, XLSX o PDF. Guarda su
version_id. - Revísala fila por fila. Las filas con tarifa 0 o sin días son las que no se pudieron leer: corrígelas o bórralas.
- Si hace falta, añade recargos (un seguro, el recaudo contra entrega).
- Actívala. Desde ese momento el agente cotiza con ella; puedes comprobarlo con cotizar.
La primera fila del archivo son los encabezados. Reconoce, sin importar mayúsculas ni tildes:
| COLUMNA | ENCABEZADOS QUE ACEPTA |
|---|---|
| Zona (obligatoria) | zona, ciudad, destino, departamento, región, ubicación |
| Tarifa (obligatoria) | tarifa, flete, envío, valor, precio, costo, coste |
| Días | días, tiempo, entrega, plazo. 4, 4-6 o 4 a 6 días. |
| Producto | producto, artículo, item, sku. Sin él, la fila vale para todos. |
| Cantidad | cantidad, rango, unidades. 1-10, 11+ o 5. |
Los importes se leen en formato colombiano: $12.500 es doce mil quinientos y 1.200,50 lleva decimales. Un destino que coincide con varias zonas no se adivina: el agente pregunta cuál.
Inventario
Con inventario_activo, el agente mira el stock antes de ofrecer: avisa de lo agotado, propone alternativas y puede decir que quedan pocas unidades. El stock puede vivir en dos sitios:
- En el módulo Productos (
inventario_delegado: true): lo llevas allí. Aquí, disponibilidad y registrar venta le preguntan a Productos. - En el inventario propio de Ventas: lo cargas con un archivo o artículo por artículo, sin borrador: entra directo. Cada cambio de cantidad queda como movimiento.
El archivo de inventario necesita una columna de cantidad (cantidad, stock, existencias, disponible, unidades, saldo) y otra de nombre (producto, artículo, descripción, nombre) o de SKU (sku, referencia, código, EAN). Opcionales: unidad, bodega (almacén, ubicación) y umbral (mínimo, punto de reorden), que marca desde dónde hay stock bajo.
Las ventas que cierra el agente descuentan solas al confirmarse el pago. Las que haces fuera del chat, regístralas con registrar venta y una sale_ref: un reintento con la misma referencia no descuenta dos veces.
Créditos
- Conversar, por JSON o por SSE, y enviar comprobantes gastan créditos de la bolsa de tu cuenta. Lo que gasta cada mensaje depende de lo que tenga que hacer el agente.
- Con la bolsa agotada, esas rutas responden 402 (
bolsa_agotada). La configuración, los leads, las tarifas y el inventario siguen funcionando. - Un mensaje repetido con el mismo
msg_idno vuelve a gastar. - Lo que gastó Ventas en el espacio, en consumo; el saldo de la cuenta, en la bolsa de créditos.
Rutas
| MÉTODO | RUTA | PARA QUÉ | PERMISO |
|---|---|---|---|
| CONVERSAR | |||
| POST | /conversations/ | Conversa con un cliente · gasta créditos | lee |
| SSE | /conversations/stream/ | La misma conversación, por eventos · gasta créditos | lee |
| POST | /conversations/evidence | Recibe una imagen del cliente · gasta créditos | lee |
| DEL | /sessions/{sesion} | Reinicia una conversación | escribe |
| AGENTE | |||
| GET | /leads-config | La configuración del agente | lee |
| PATCH | /leads-config | Cambia la configuración del agente | escribe |
| LEADS | |||
| GET | /leads/ | Los leads del espacio | lee |
| GET | /leads/{lead} | Un lead | lee |
| PATCH | /leads/{lead} | Mueve un lead en el embudo | escribe |
| TARIFAS DE ENVÍO | |||
| POST | /pricing/tables | Sube una tabla de tarifas de envío | escribe |
| GET | /pricing/versions | Las versiones de la tabla de tarifas | lee |
| GET | /pricing/drafts/{tabla} | Una versión, fila por fila | lee |
| PATCH | /pricing/drafts/{tabla}/rates/{tarifa} | Corrige una fila del borrador | escribe |
| DEL | /pricing/drafts/{tabla}/rates/{tarifa} | Borra una fila del borrador | escribe |
| POST | /pricing/drafts/{tabla}/surcharges | Añade un recargo | escribe |
| POST | /pricing/versions/{tabla}/activate | Valida y activa una versión | escribe |
| POST | /pricing/versions/{tabla}/retire | Retira una versión | escribe |
| POST | /pricing/quote | Cotiza un envío | escribe |
| INVENTARIO | |||
| POST | /inventory/upload | Carga el inventario desde un archivo | escribe |
| GET | /inventory/ | El inventario del espacio | lee |
| GET | /inventory/summary | El resumen del inventario | lee |
| GET | /inventory/low-stock | Lo que está por agotarse | lee |
| GET | /inventory/export | Descarga el inventario en CSV | lee |
| GET | /inventory/availability | ¿Hay stock para este pedido? | lee |
| GET | /inventory/items/{sku} | Un artículo del inventario | lee |
| POST | /inventory/items | Crea o fija un artículo | escribe |
| PATCH | /inventory/items/{sku} | Ajusta la cantidad de un artículo | escribe |
| DEL | /inventory/items/{sku} | Borra un artículo | escribe |
| POST | /inventory/sale | Registra una venta confirmada | escribe |
| CONSUMO | |||
| GET | /consumo | Lo que gastó Ventas, en créditos | lee |