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: Bearer para 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).

AspectoDetalle
Campoapi_key o apiKey en el body JSON
Dónde no vaNo en query string, no en header Authorization
Exclusividadapi_key o bot_id; nunca ambos (respuesta 422 si se viola)
Clave desarrolloPrefijo ecb_sk_dev_… → bot en PENDING o RUNNING; conversaciones marcadas como test
Clave producciónPrefijo ecb_sk_live_… → solo bot RUNNING
Cómo obtenerlaDashboard → 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 auth401 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.

CampoTipoRequeridoDescripción
promptstringMensaje del usuario
api_keystringSí*Clave secreta (ecb_sk_dev_… / ecb_sk_live_…)
bot_idintSí*Solo modo widget; no usar junto con api_key
session_idstring (UUID)NoReutilizar entre turnos; si se omite, el servicio genera uno y lo devuelve
current_page_urlstringNoURL de contexto para RAG e intenciones
calendar_contextstringNoContexto de calendario en flujos de citas
page_js_function_valuesobjectNoValores de variables JS de página (widget avanzado)
session_originstringNoIgnorado 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 de is_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: true y un content amigable.

Cómo leer el stream (cliente)

  1. Abrir conexión POST y leer el body como stream de texto.
  2. Procesar líneas que empiecen por data: .
  3. Concatenar los content de chunks con is_final: false.
  4. Detener cuando llegue is_final: true o done: 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?

EndpointCuándo usarlo
/chat/streamUI con efecto «escribiendo», respuestas largas, mejor experiencia en tiempo real
/chatIntegraciones 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.

CampoTipoDefaultDescripción
api_keystringIgual que en chat
session_idstringUUID de la conversación
limitint10Mensajes por página (1–50)
offsetint0Desplazamiento 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_id al iniciar la conversación en tu sistema (o deja que el servicio lo genere en el primer turno).
  • Reutiliza el mismo session_id en cada turno para mantener el historial y el estado de intenciones/acciones.
  • El servicio devuelve session_id en 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ódigoSignificado típico
422Body inválido: falta prompt, o api_key/bot_id mal combinados
401api_key inválida o revocada
403Bot no disponible (PENDING con clave prod, INACTIVE, etc.) o Origin no permitido
404Bot no encontrado
500Error 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.