API del Stream
Integra el chatbot de EasyChatBot en tu propia interfaz — WhatsApp, app móvil, backend propio — sin el widget embebido.
Volver al índice de documentación
Introducción
La API del Stream Service es el punto de entrada para enviar mensajes al chatbot y recibir respuestas. Tú construyes la interfaz; EasyChatBot se encarga del RAG, las intenciones, el historial y la generación con IA.
Base URL del servicio Stream:
https://stream.easychatbot.app
En producción, esta URL la configura el equipo de EasyChatBot. En desarrollo local suele ser http://localhost:8000 (variable STREAM_SERVICE_URL / stream.service.url).
Headers comunes
Content-Type: application/json— obligatorio en todas las peticiones POST.- No uses
Authorization: Bearerpara el chat: la clave va en el cuerpo JSON (ver siguiente sección).
El widget embebido (easychatbot.js) usa bot_id y validación de dominio del navegador. Esta documentación se centra en la integración servidor con api_key, ideal para backends, apps móviles, etc.
Para Rocket.Chat Omnichannel (Livechat, WhatsApp conectado a RC) usa el endpoint webhook dedicado documentado en Integración Rocket.Chat — no requiere api_key del cliente.
Para Chatwoot (WhatsApp, web widget, email, etc.) usa el webhook dedicado documentado en Integración Chatwoot — tampoco requiere api_key del cliente.
Autenticación con api_key
Para integraciones desde tu servidor, envía la clave secreta del bot en el body JSON. También acepta el alias apiKey (camelCase).
| Aspecto | Detalle |
|---|---|
| Campo | api_key o apiKey en el body JSON |
| Dónde no va | No en query string, no en header Authorization |
| Exclusividad | api_key o bot_id; nunca ambos (respuesta 422 si se viola) |
| Clave desarrollo | Prefijo ecb_sk_dev_… → bot en PENDING o RUNNING; conversaciones marcadas como test |
| Clave producción | Prefijo ecb_sk_live_… → solo bot RUNNING |
| Cómo obtenerla | Dashboard → Mis Chatbots → modal Instalar → sección «API del Stream» → generar clave dev o prod (solo se muestra una vez; guárdala en tu gestor de secretos) |
| Errores de auth | 401 clave inválida o revocada; 403 bot no disponible o Origin no permitido (clave prod con dominio configurado) |
Ejemplo mínimo de petición
{
"api_key": "ecb_sk_live_xxxxxxxx",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"prompt": "¿Cuáles son sus horarios?"
}
Parámetros de petición
Los endpoints /chat y /chat/stream comparten el mismo body (ChatRequest). Debes indicar exactamente uno de api_key o bot_id.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
prompt | string | Sí | Mensaje del usuario |
api_key | string | Sí* | Clave secreta (ecb_sk_dev_… / ecb_sk_live_…) |
bot_id | int | Sí* | Solo modo widget; no usar junto con api_key |
session_id | string (UUID) | No | Reutilizar entre turnos; si se omite, el servicio genera uno y lo devuelve |
current_page_url | string | No | URL de contexto para RAG e intenciones |
calendar_context | string | No | Contexto de calendario en flujos de citas |
page_js_function_values | object | No | Valores de variables JS de página (widget avanzado) |
session_origin | string | No | Ignorado cuando se usa api_key |
* Exactamente uno de api_key o bot_id.
POST /chat/stream (streaming)
https://stream.easychatbot.app/chat/stream
Devuelve la respuesta del asistente en tiempo real mediante SSE (Server-Sent Events). Ideal para interfaces con efecto «escribiendo» o respuestas largas.
Respuesta
- Content-Type:
text/event-stream - Formato: cada evento es una línea
data: {json}seguida de una línea en blanco (\n\n)
Tipos de eventos
Fragmentos de texto (mientras el LLM genera):
{
"content": "fragmento de texto",
"is_final": false,
"bot_id": 123,
"session_id": "550e8400-e29b-41d4-a716-446655440000"
}
Metadata RAG (opcional, antes del streaming de texto; útil para depuración):
{
"content": "",
"is_final": false,
"bot_id": 123,
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"event_type": "rag_context",
"rag_chunks": [],
"rag_detected_intents": []
}
Chunk final (fin del turno):
{
"content": "",
"is_final": true,
"bot_id": 123,
"session_id": "550e8400-e29b-41d4-a716-446655440000"
}
Casos especiales
- Saldo de tokens agotado: evento con mensaje amigable y
"done": true(en lugar deis_final). - Handoff humano: chunk final con mensaje de aviso o
"takeover_active": true; el LLM deja de responder en esa sesión. - Errores dentro del stream: no siempre son HTTP error; pueden llegar como chunk final con
is_final: truey uncontentamigable.
Cómo leer el stream (cliente)
- Abrir conexión POST y leer el body como stream de texto.
- Procesar líneas que empiecen por
data:. - Concatenar los
contentde chunks conis_final: false. - Detener cuando llegue
is_final: trueodone: true.
POST /chat (sin streaming)
https://stream.easychatbot.app/chat
Mismos parámetros de entrada que /chat/stream, pero la respuesta llega en un único JSON. Ideal para webhooks, backends simples o integraciones que no necesitan efecto «escribiendo».
Respuesta — éxito normal
{
"response": "Texto completo del asistente",
"bot_id": 123,
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-27T22:00:00",
"rag_context": {
"event_type": "rag_context",
"rag_chunks": []
}
}
Handoff humano
{
"response": "Un agente humano atenderá tu conversación.",
"suppress_response": false,
"bot_id": 123,
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-27T22:00:00"
}
Saldo de tokens agotado
HTTP 200 con mensaje amigable en response (no es un error HTTP):
{
"response": "Lo siento, actualmente no hay fondos disponibles...",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"msg_id": 789
}
¿Stream o sin stream?
| Endpoint | Cuándo usarlo |
|---|---|
/chat/stream | UI con efecto «escribiendo», respuestas largas, mejor experiencia en tiempo real |
/chat | Integraciones simples, webhooks, backends que esperan un JSON completo de una sola vez |
POST /chat/history
https://stream.easychatbot.app/chat/history
Consulta el historial paginado de una conversación. Usa la misma api_key que en los endpoints de chat.
| Campo | Tipo | Default | Descripción |
|---|---|---|---|
api_key | string | — | Igual que en chat |
session_id | string | — | UUID de la conversación |
limit | int | 10 | Mensajes por página (1–50) |
offset | int | 0 | Desplazamiento para paginación |
Respuesta
{
"bot_id": 123,
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"messages": [
{
"role": "USER",
"content": "Hola",
"created_at": "2026-06-27T12:00:00"
},
{
"role": "ASSISTANT",
"content": "¡Hola! ¿En qué puedo ayudarte?",
"created_at": "2026-06-27T12:00:01"
}
],
"offset": 0,
"limit": 10,
"total": 42,
"has_more": true
}
Los mensajes de cada página vienen ordenados del más reciente al más antiguo. Solo se devuelven roles USER y ASSISTANT.
Gestión de sesión
- Genera un UUID para
session_idal iniciar la conversación en tu sistema (o deja que el servicio lo genere en el primer turno). - Reutiliza el mismo
session_iden cada turno para mantener el historial y el estado de intenciones/acciones. - El servicio devuelve
session_iden cada respuesta; guárdalo en tu backend asociado al usuario o canal (p. ej. número de WhatsApp). - Con
api_key, el UUID que envías se respeta: no rota por huella del navegador (a diferencia del widget embebido).
sequenceDiagram
participant App as TuBackend
participant Stream as StreamAPI
participant LLM as ModeloLLM
App->>Stream: POST /chat o /chat/stream
Note over App,Stream: Body JSON con api_key + session_id + prompt
Stream->>Stream: Validar api_key y estado del bot
Stream->>LLM: Generar respuesta con RAG
Stream-->>App: SSE chunks o JSON completo
App->>Stream: POST /chat/history opcional
Stream-->>App: Mensajes paginados
Errores HTTP
| Código | Significado típico |
|---|---|
| 422 | Body inválido: falta prompt, o api_key/bot_id mal combinados |
| 401 | api_key inválida o revocada |
| 403 | Bot no disponible (PENDING con clave prod, INACTIVE, etc.) o Origin no permitido |
| 404 | Bot no encontrado |
| 500 | Error interno; en /chat el mensaje va en detail; en stream puede ir dentro del SSE final |
Formato de validación (422):
{
"detail": [
{
"type": "value_error",
"loc": ["body", "api_key"],
"msg": "Indica bot_id (embed) o api_key (integración servidor).",
"input": {}
}
]
}
Ejemplos con curl
Sustituye la clave y el session_id por valores reales. En streaming usa -N (o --no-buffer) para ver los eventos en tiempo real.
1. Chat con streaming
curl -N -X POST 'https://stream.easychatbot.app/chat/stream' \
-H 'Content-Type: application/json' \
-d '{
"api_key": "ecb_sk_live_xxxxxxxx",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"prompt": "¿Cuáles son sus horarios?"
}'
2. Chat sin streaming
curl -X POST 'https://stream.easychatbot.app/chat' \
-H 'Content-Type: application/json' \
-d '{
"api_key": "ecb_sk_live_xxxxxxxx",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"prompt": "¿Cuáles son sus horarios?"
}'
3. Historial de conversación
curl -X POST 'https://stream.easychatbot.app/chat/history' \
-H 'Content-Type: application/json' \
-d '{
"api_key": "ecb_sk_live_xxxxxxxx",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"limit": 10,
"offset": 0
}'
Notas operativas
- Consumo de tokens: el saldo del propietario del bot debe ser mayor que cero. Si no hay fondos, la API responde con un mensaje amigable sin llamar al LLM.
- OpenAPI interactivo: el Stream Service expone documentación Swagger en https://stream.easychatbot.app/docs (útil para explorar schemas adicionales).
- Generar claves: inicia sesión en el dashboard → Mis Chatbots → Instalar → «API del Stream».
- Endpoints internos (
/rag/*,/internal/*, etc.) no forman parte de la API pública para integradores; están pensados para el dashboard y operaciones internas.