Widget Web #
Embebe el chat en cualquier sitio web con un snippet de JavaScript. Sin frameworks, sin dependencias.
widgetKey en Dashboard → Canales. Cada widget tiene su propia clave y configuración.Instalación básica
flowordr-chat.min.js para recibir la versión vigente. El archivo con versión flowordr-chat.v1.0.5.min.js queda fijo en esa versión.<!-- Antes de </body> -->
<script src="https://app.flowordr.com/widgets/flowordr-chat.min.js"
data-widget-key="wk_tu_key_aqui"
defer></script>Configuración avanzada
<script>
window.FlowOrdrConfig = {
widgetKey: "wk_tu_key_aqui",
position: "bottom-right", // bottom-right | bottom-left
primaryColor: "#2E4CFF",
darkMode: "auto", // auto | light | dark
welcomeMessage: "Hola, ¿en qué te ayudo?",
launcherLabel: "Chatear"
};
</script>
<script src="https://app.flowordr.com/widgets/flowordr-chat.min.js" defer></script>Opciones de configuración
| Opción | Tipo | Descripción |
|---|---|---|
| widgetKey | string | Tu clave del widget (obligatorio) |
| position | string | bottom-right | bottom-left |
| primaryColor | string | Color hex del launcher y burbujas |
| darkMode | string | auto | light | dark |
| welcomeMessage | string | Primer mensaje del bot al abrir |
| launcherLabel | string | Texto debajo del icono burbuja |
| showCitations | boolean | Mostrar las fuentes citadas en cada respuesta |
Capacidades
- Streaming en tiempo real (SSE) por defecto
- Markdown completo en respuestas (listas, código, tablas)
- Citas con enlace al chunk fuente
- Persistencia de conversación por sesión (localStorage)
- Adapta colores al tema del sitio anfitrión vía
darkMode: "auto" - Restringible por dominio (configurado en el dashboard)
API del widget (JavaScript)
// Abrir/cerrar programáticamente
window.FlowOrdr.open();
window.FlowOrdr.close();
// Enviar mensaje
window.FlowOrdr.send("¿Cuáles son tus horarios?");
// Escuchar eventos
window.FlowOrdr.on("message", (msg) => console.log(msg));
window.FlowOrdr.on("open", () => {});
window.FlowOrdr.on("close", () => {});
// Pasar contexto al asistente (notas fijadas)
window.FlowOrdr.setPinnedNotes("Cliente: María | Plan: Pro");/docs/assistants y parámetros RAG en /docs/settings.API pública del widget
export FLOWORDR_BASE_URL="https://app.flowordr.com"widgetKey o sessionToken en el body. No envíes la API key de tu servidor al navegador. El dominio de origen debe estar autorizado para el widget.POST /api/widget/chat
| Nombre | Tipo | Obligatorio | Valores aceptados / rango | Default | Descripción |
|---|---|---|---|---|---|
| widgetKey | body string | Si no hay sessionToken | Máximo 60 caracteres | — | Clave pública del widget. |
| sessionToken | body string | Si no hay widgetKey | Máximo 500 caracteres | — | Sesión del widget. |
| message | body string | Sí | Texto no vacío | — | Mensaje del visitante. |
| conversationId | body UUID | No | UUID devuelto por el widget | Nueva conversación | Continúa la conversación. |
| userName / userEmail | body string | No | 100 caracteres / email válido de hasta 200 | — | Datos opcionales del visitante. |
| ragOptions | body object | No | maxChunks, temperature, minScore, model (≤50 caracteres), documentIds | Configuración del widget | Opciones del mensaje. |
| Origin | header URL | Sí | Dominio autorizado para el widget | — | El navegador lo envía automáticamente. |
curl -X POST "$FLOWORDR_BASE_URL/api/widget/chat" -H "Origin: https://ejemplo.com" -H "Content-Type: application/json" -d '{"widgetKey":"<widget-key>","message":"¿Cuáles son sus horarios?"}'Respuesta: 200 respuesta y conversationId; 401 clave o sesión inválida; 403 dominio no autorizado; 429 límite.
POST /api/widget/chat/stream
| Nombre | Tipo | Obligatorio | Valores aceptados / rango | Default | Descripción |
|---|---|---|---|---|---|
| widgetKey | body string | Si no hay sessionToken | Máximo 60 caracteres | — | Clave pública del widget. |
| sessionToken | body string | Si no hay widgetKey | Máximo 500 caracteres | — | Sesión del widget. |
| message | body string | Sí | Texto no vacío | — | Mensaje del visitante. |
| conversationId | body UUID | No | UUID devuelto por el widget | Nueva conversación | Continúa la conversación. |
| userName / userEmail | body string | No | 100 caracteres / email válido de hasta 200 | — | Datos opcionales del visitante. |
| ragOptions | body object | No | maxChunks, temperature, minScore, model (≤50 caracteres), documentIds | Configuración del widget | Opciones del mensaje. |
| Origin | header URL | Sí | Dominio autorizado para el widget | — | El navegador lo envía automáticamente. |
curl -N -X POST "$FLOWORDR_BASE_URL/api/widget/chat/stream" -H "Origin: https://ejemplo.com" -H "Content-Type: application/json" -H "Accept: text/event-stream" -d '{"widgetKey":"<widget-key>","message":"¿Cuáles son sus horarios?"}'Respuesta: 200 SSE start, delta, done y meta; errores previos al stream en JSON.
GET /api/widget/config/{widgetKey}
| Nombre | Tipo | Obligatorio | Valores aceptados / rango | Default | Descripción |
|---|---|---|---|---|---|
| widgetKey | path string | Sí | Clave pública del widget | — | Busca configuración pública. |
| Origin | header URL | Sí | Dominio autorizado para el widget | — | En navegador se envía automáticamente. |
curl "$FLOWORDR_BASE_URL/api/widget/config/<widget-key>" -H "Origin: https://ejemplo.com"Respuesta: 200 configuración pública; 403 origen no permitido; 404 clave ausente.
GET /api/widget/{widgetKey}/suggested-questions
| Nombre | Tipo | Obligatorio | Valores aceptados / rango | Default | Descripción |
|---|---|---|---|---|---|
| widgetKey | path string | Sí | Clave pública del widget | — | Busca preguntas sugeridas. |
| Origin | header URL | Sí | Dominio autorizado | — | En navegador se envía automáticamente. |
| count | query integer | No | Se ajusta a 1–10 | 8 | Preguntas devueltas. |
| shuffle / regenerate | query boolean | No | true, false | true / false | Mezcla o regenera preguntas. |
curl "$FLOWORDR_BASE_URL/api/widget/<widget-key>/suggested-questions?count=8" -H "Origin: https://ejemplo.com"Respuesta: 200 preguntas sugeridas; 403 origen no permitido; 404 widget ausente.
Administración del widget con API key
Prepara tu terminal una vez
export FLOWORDR_BASE_URL="https://app.flowordr.com"
export FLOWORDR_API_KEY="<tu-api-key>"
export FLOWORDR_TENANT_ID="<tu-tenant-id>"Ejecuta este bloque antes de los cURL. Sustituye los valores entre ángulos por tus credenciales; ningún ejemplo contiene claves reales.
GET /api/widgets
| Nombre | Tipo | Obligatorio | Valores aceptados / rango | Default | Descripción |
|---|---|---|---|---|---|
| X-Api-Key (header) | string | Sí | Clave activa del tenant | — | Autenticación. |
| X-Tenant-Id (header) | UUID | Condicional | Tenant autorizado | Tenant de la clave | Necesario si la clave permite varios tenants. |
curl "$FLOWORDR_BASE_URL/api/widgets" -H "X-Api-Key: $FLOWORDR_API_KEY" -H "X-Tenant-Id: $FLOWORDR_TENANT_ID"Respuesta: 200 lista de widgets.
POST /api/widgets
| Nombre | Tipo | Obligatorio | Valores aceptados / rango | Default | Descripción |
|---|---|---|---|---|---|
| X-Api-Key (header) | string | Sí | Clave activa del tenant | — | Autenticación. |
| X-Tenant-Id (header) | UUID | Condicional | Tenant autorizado | Tenant de la clave | Necesario si la clave permite varios tenants. |
| name | body string | Al crear | Nombre del widget | — | Nombre interno; opcional al actualizar. |
| allowedOrigins | body string[] | Al crear | Al menos un origen válido; sin wildcard * | — | Dominios autorizados. |
| appearance | body object | No | Opciones de apariencia | Apariencia del widget | Colores y textos. |
| ragOptions.maxChunks / temperature / minScore | body number | No | 1–50 / 0–1 / 0–1 | Defaults del canal | Recuperación y generación. |
| ragOptions.maxHistoryTurns | body integer | No | 0–20; 0 sin historial | Default del canal | Turnos de contexto. |
| rateLimits.requestsPerMinutePerIP | body integer | No | 1–1000; alias requestsPerMinute | Default del canal | Límite por IP. |
| rateLimits.requestsPerMinuteTotal | body integer | No | 1–10000 | 500 | Límite global. |
| rateLimits.maxSessionsPerDay | body integer | No | 1–100000 | 1000 | Sesiones por día. |
| rateLimits.maxMessagesPerSession | body integer | No | 1–10000 | 100 | Mensajes por sesión. |
| rateLimits.requestsPerHour | body integer | No | Se acepta, pero no se guarda ni aplica | — | Campo de compatibilidad. |
curl -X POST "$FLOWORDR_BASE_URL/api/widgets" -H "X-Api-Key: $FLOWORDR_API_KEY" -H "X-Tenant-Id: $FLOWORDR_TENANT_ID" -H "Content-Type: application/json" -d '{"name":"Mi asistente","allowedOrigins":["https://ejemplo.com"]}'Respuesta: 201 widget creado; 400 si la configuración es inválida.
GET /api/widgets/{id}
| Nombre | Tipo | Obligatorio | Valores aceptados / rango | Default | Descripción |
|---|---|---|---|---|---|
| X-Api-Key (header) | string | Sí | Clave activa del tenant | — | Autenticación. |
| X-Tenant-Id (header) | UUID | Condicional | Tenant autorizado | Tenant de la clave | Necesario si la clave permite varios tenants. |
| id | path UUID | Sí | ID del widget | — | Widget del tenant. |
curl "$FLOWORDR_BASE_URL/api/widgets/<widget-id>" -H "X-Api-Key: $FLOWORDR_API_KEY" -H "X-Tenant-Id: $FLOWORDR_TENANT_ID"Respuesta: 200 widget; 400 según el controlador si no se encuentra.
PUT /api/widgets/{id}
| Nombre | Tipo | Obligatorio | Valores aceptados / rango | Default | Descripción |
|---|---|---|---|---|---|
| X-Api-Key (header) | string | Sí | Clave activa del tenant | — | Autenticación. |
| X-Tenant-Id (header) | UUID | Condicional | Tenant autorizado | Tenant de la clave | Necesario si la clave permite varios tenants. |
| id | path UUID | Sí | ID del widget | — | Widget del tenant. |
| name | body string | Al crear | Nombre del widget | — | Nombre interno; opcional al actualizar. |
| allowedOrigins | body string[] | Al crear | Al menos un origen válido; sin wildcard * | — | Dominios autorizados. |
| appearance | body object | No | Opciones de apariencia | Apariencia del widget | Colores y textos. |
| ragOptions.maxChunks / temperature / minScore | body number | No | 1–50 / 0–1 / 0–1 | Defaults del canal | Recuperación y generación. |
| ragOptions.maxHistoryTurns | body integer | No | 0–20; 0 sin historial | Default del canal | Turnos de contexto. |
| rateLimits.requestsPerMinutePerIP | body integer | No | 1–1000; alias requestsPerMinute | Default del canal | Límite por IP. |
| rateLimits.requestsPerMinuteTotal | body integer | No | 1–10000 | 500 | Límite global. |
| rateLimits.maxSessionsPerDay | body integer | No | 1–100000 | 1000 | Sesiones por día. |
| rateLimits.maxMessagesPerSession | body integer | No | 1–10000 | 100 | Mensajes por sesión. |
| rateLimits.requestsPerHour | body integer | No | Se acepta, pero no se guarda ni aplica | — | Campo de compatibilidad. |
curl -X PUT "$FLOWORDR_BASE_URL/api/widgets/<widget-id>" -H "X-Api-Key: $FLOWORDR_API_KEY" -H "X-Tenant-Id: $FLOWORDR_TENANT_ID" -H "Content-Type: application/json" -d '{"name":"Mi asistente","allowedOrigins":["https://ejemplo.com"]}'Respuesta: 200 widget actualizado; 400 si falla la validación.
DELETE /api/widgets/{id}
| Nombre | Tipo | Obligatorio | Valores aceptados / rango | Default | Descripción |
|---|---|---|---|---|---|
| X-Api-Key (header) | string | Sí | Clave activa del tenant | — | Autenticación. |
| X-Tenant-Id (header) | UUID | Condicional | Tenant autorizado | Tenant de la clave | Necesario si la clave permite varios tenants. |
| id | path UUID | Sí | ID del widget | — | Widget del tenant. |
curl -X DELETE "$FLOWORDR_BASE_URL/api/widgets/<widget-id>" -H "X-Api-Key: $FLOWORDR_API_KEY" -H "X-Tenant-Id: $FLOWORDR_TENANT_ID"Respuesta: 204 sin contenido; 400 si falla.
GET /api/widgets/{id}/integration
| Nombre | Tipo | Obligatorio | Valores aceptados / rango | Default | Descripción |
|---|---|---|---|---|---|
| X-Api-Key (header) | string | Sí | Clave activa del tenant | — | Autenticación. |
| X-Tenant-Id (header) | UUID | Condicional | Tenant autorizado | Tenant de la clave | Necesario si la clave permite varios tenants. |
| id | path UUID | Sí | ID del widget | — | Widget del tenant. |
curl "$FLOWORDR_BASE_URL/api/widgets/<widget-id>/integration" -H "X-Api-Key: $FLOWORDR_API_KEY" -H "X-Tenant-Id: $FLOWORDR_TENANT_ID"Respuesta: 200 snippet de integración.
POST /api/widgets/{id}/avatar
| Nombre | Tipo | Obligatorio | Valores aceptados / rango | Default | Descripción |
|---|---|---|---|---|---|
| X-Api-Key (header) | string | Sí | Clave activa del tenant | — | Autenticación. |
| X-Tenant-Id (header) | UUID | Condicional | Tenant autorizado | Tenant de la clave | Necesario si la clave permite varios tenants. |
| id | path UUID | Sí | ID del widget | — | Widget del tenant. |
| file | multipart file | Sí | PNG, JPEG o WebP; máximo 1 MiB | — | Avatar del widget. |
curl -X POST "$FLOWORDR_BASE_URL/api/widgets/<widget-id>/avatar" -H "X-Api-Key: $FLOWORDR_API_KEY" -H "X-Tenant-Id: $FLOWORDR_TENANT_ID" -F '[email protected]'Respuesta: 200 {url}; 400 tipo inválido; 413 mayor a 1 MiB; 502 almacenamiento.
DELETE /api/widgets/{id}/avatar
| Nombre | Tipo | Obligatorio | Valores aceptados / rango | Default | Descripción |
|---|---|---|---|---|---|
| X-Api-Key (header) | string | Sí | Clave activa del tenant | — | Autenticación. |
| X-Tenant-Id (header) | UUID | Condicional | Tenant autorizado | Tenant de la clave | Necesario si la clave permite varios tenants. |
| id | path UUID | Sí | ID del widget | — | Widget del tenant. |
curl -X DELETE "$FLOWORDR_BASE_URL/api/widgets/<widget-id>/avatar" -H "X-Api-Key: $FLOWORDR_API_KEY" -H "X-Tenant-Id: $FLOWORDR_TENANT_ID"Respuesta: 200/204 al eliminar el avatar.