POSTSSE
/api/mod/ventas/{espacio}/conversations/stream/La misma conversación, por eventos
El mismo cuerpo que conversar, pero la respuesta llega como eventos (SSE): el aviso de privacidad, uno o dos mensajes, el paso a una persona y el cierre con el estado y la cotización.
- PERMISOlee (vale cualquier clave)
- CRÉDITOSgasta créditos
- AUTENTICACIÓNBearer bth_…
PARÁMETROS
| CAMPO | TIPO | REQUERIDO | QUÉ ES |
|---|---|---|---|
| espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Ventas. |
CUERPO · JSON
| CAMPO | TIPO | REQUERIDO | QUÉ ES |
|---|---|---|---|
| question | string | SÍ | Lo que escribió tu cliente, tal cual. De 1 a 4000 caracteres: fuera de ese rango no da error, responde 1001 con tu refusal_fuera_dominio. |
| session_id | string | SÍ, EN LA PRÁCTICA | Tu identificador de la conversación: uno por chat (el número del cliente en tu canal, el id del hilo…). Sin él responde 400. Con él, Ventas recuerda el carrito, la ciudad, el método de pago y el pedido abierto. |
| consent | boolean | no | true si tu cliente autorizó el seguimiento comercial. Solo así se guarda su contacto, y seudonimizado. Por defecto false. |
EVENTOS
200 con Content-Type: text/event-stream. Cada evento es una línea data: {…} seguida de una línea en blanco.
| CAMPO | TIPO | QUÉ ES |
|---|---|---|
| notice | { type, content } | Solo en el primer turno: tu aviso de privacidad. |
| chunk | { type, content } | Un mensaje para tu cliente, entero. Llegan uno o dos, en orden. |
| handoff | { type, reason } | Conviene pasar a una persona. reason dice por qué (soporte:pide_asesor, precio:sin_precio…): regístralo, no decidas por él. |
| done | { type, status_code, full_response, estado, cotizacion, sources } | Cierre normal, con los mismos campos que en conversar. |
| error | { type, content } | Algo falló después del 200. content trae un texto para tu cliente. |
ERRORES DE ESTA RUTA · SIEMPRE {"detail": …}
| STATUS | CUÁNDO | DETAIL LITERAL |
|---|---|---|
| 400 | Falta session_id | session_id es obligatorio. |
| 403 | El espacio no tiene el módulo Ventas | módulo no habilitado para este espacio. |
| 402 | Antes de abrir el stream: créditos agotados | — |
| 429 | El espacio mandó demasiadas peticiones seguidas: espera unos segundos | Demasiadas solicitudes; intenta en un momento. |
| 502 | Ventas no respondió a tiempo o no está disponible: reintenta con espera creciente | — |
| evento | Evento error: el turno falló después del 200 | No pude procesar tu mensaje en este momento. Intenta de nuevo, por favor. |
Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos.
CONVIENE SABER
- El mensaje no llega palabra a palabra: Ventas comprueba cada cifra antes de enviarla, así que manda el texto entero. Por esta ruta los eventos llegan juntos al terminar el turno.
- Todo lo que se rechaza antes (400, 402, 403, 429) llega como JSON normal, no como evento.
- Aquí no hay
msg_id: si tu canal reintenta mensajes, usa conversar. - Copia la ruta tal cual, con su barra final. Sin ella la respuesta es un 307 sin destino, no la conversación.