Widget Web #

Embebe el chat en cualquier sitio web con un snippet de JavaScript. Sin frameworks, sin dependencias.

Disponible desde el plan Free. No requiere suscripción de pago.
Obtén tu widgetKey en Dashboard → Canales. Cada widget tiene su propia clave y configuración.

Instalación básica

Usa 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.
html
<!-- 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

html
<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ónTipoDescripción
widgetKeystringTu clave del widget (obligatorio)
positionstringbottom-right | bottom-left
primaryColorstringColor hex del launcher y burbujas
darkModestringauto | light | dark
welcomeMessagestringPrimer mensaje del bot al abrir
launcherLabelstringTexto debajo del icono burbuja
showCitationsbooleanMostrar 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)

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");
Más sobre presets disponibles en /docs/assistants y parámetros RAG en /docs/settings.

API pública del widget

bash
export FLOWORDR_BASE_URL="https://app.flowordr.com"
Esta API es pública y se autentica con 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

NombreTipoObligatorioValores aceptados / rangoDefaultDescripción
widgetKeybody stringSi no hay sessionTokenMáximo 60 caracteres—Clave pública del widget.
sessionTokenbody stringSi no hay widgetKeyMáximo 500 caracteres—Sesión del widget.
messagebody stringSíTexto no vacío—Mensaje del visitante.
conversationIdbody UUIDNoUUID devuelto por el widgetNueva conversaciónContinúa la conversación.
userName / userEmailbody stringNo100 caracteres / email válido de hasta 200—Datos opcionales del visitante.
ragOptionsbody objectNomaxChunks, temperature, minScore, model (≤50 caracteres), documentIdsConfiguración del widgetOpciones del mensaje.
Originheader URLSíDominio autorizado para el widget—El navegador lo envía automáticamente.
cURL
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

NombreTipoObligatorioValores aceptados / rangoDefaultDescripción
widgetKeybody stringSi no hay sessionTokenMáximo 60 caracteres—Clave pública del widget.
sessionTokenbody stringSi no hay widgetKeyMáximo 500 caracteres—Sesión del widget.
messagebody stringSíTexto no vacío—Mensaje del visitante.
conversationIdbody UUIDNoUUID devuelto por el widgetNueva conversaciónContinúa la conversación.
userName / userEmailbody stringNo100 caracteres / email válido de hasta 200—Datos opcionales del visitante.
ragOptionsbody objectNomaxChunks, temperature, minScore, model (≤50 caracteres), documentIdsConfiguración del widgetOpciones del mensaje.
Originheader URLSíDominio autorizado para el widget—El navegador lo envía automáticamente.
cURL
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}

NombreTipoObligatorioValores aceptados / rangoDefaultDescripción
widgetKeypath stringSíClave pública del widget—Busca configuración pública.
Originheader URLSíDominio autorizado para el widget—En navegador se envía automáticamente.
cURL
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

NombreTipoObligatorioValores aceptados / rangoDefaultDescripción
widgetKeypath stringSíClave pública del widget—Busca preguntas sugeridas.
Originheader URLSíDominio autorizado—En navegador se envía automáticamente.
countquery integerNoSe ajusta a 1–108Preguntas devueltas.
shuffle / regeneratequery booleanNotrue, falsetrue / falseMezcla o regenera preguntas.
cURL
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

Variables para bash o zsh
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

NombreTipoObligatorioValores aceptados / rangoDefaultDescripción
X-Api-Key (header)stringSíClave activa del tenant—Autenticación.
X-Tenant-Id (header)UUIDCondicionalTenant autorizadoTenant de la claveNecesario si la clave permite varios tenants.
cURL
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

NombreTipoObligatorioValores aceptados / rangoDefaultDescripción
X-Api-Key (header)stringSíClave activa del tenant—Autenticación.
X-Tenant-Id (header)UUIDCondicionalTenant autorizadoTenant de la claveNecesario si la clave permite varios tenants.
namebody stringAl crearNombre del widget—Nombre interno; opcional al actualizar.
allowedOriginsbody string[]Al crearAl menos un origen válido; sin wildcard *—Dominios autorizados.
appearancebody objectNoOpciones de aparienciaApariencia del widgetColores y textos.
ragOptions.maxChunks / temperature / minScorebody numberNo1–50 / 0–1 / 0–1Defaults del canalRecuperación y generación.
ragOptions.maxHistoryTurnsbody integerNo0–20; 0 sin historialDefault del canalTurnos de contexto.
rateLimits.requestsPerMinutePerIPbody integerNo1–1000; alias requestsPerMinuteDefault del canalLímite por IP.
rateLimits.requestsPerMinuteTotalbody integerNo1–10000500Límite global.
rateLimits.maxSessionsPerDaybody integerNo1–1000001000Sesiones por día.
rateLimits.maxMessagesPerSessionbody integerNo1–10000100Mensajes por sesión.
rateLimits.requestsPerHourbody integerNoSe acepta, pero no se guarda ni aplica—Campo de compatibilidad.
cURL
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}

NombreTipoObligatorioValores aceptados / rangoDefaultDescripción
X-Api-Key (header)stringSíClave activa del tenant—Autenticación.
X-Tenant-Id (header)UUIDCondicionalTenant autorizadoTenant de la claveNecesario si la clave permite varios tenants.
idpath UUIDSíID del widget—Widget del tenant.
cURL
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}

NombreTipoObligatorioValores aceptados / rangoDefaultDescripción
X-Api-Key (header)stringSíClave activa del tenant—Autenticación.
X-Tenant-Id (header)UUIDCondicionalTenant autorizadoTenant de la claveNecesario si la clave permite varios tenants.
idpath UUIDSíID del widget—Widget del tenant.
namebody stringAl crearNombre del widget—Nombre interno; opcional al actualizar.
allowedOriginsbody string[]Al crearAl menos un origen válido; sin wildcard *—Dominios autorizados.
appearancebody objectNoOpciones de aparienciaApariencia del widgetColores y textos.
ragOptions.maxChunks / temperature / minScorebody numberNo1–50 / 0–1 / 0–1Defaults del canalRecuperación y generación.
ragOptions.maxHistoryTurnsbody integerNo0–20; 0 sin historialDefault del canalTurnos de contexto.
rateLimits.requestsPerMinutePerIPbody integerNo1–1000; alias requestsPerMinuteDefault del canalLímite por IP.
rateLimits.requestsPerMinuteTotalbody integerNo1–10000500Límite global.
rateLimits.maxSessionsPerDaybody integerNo1–1000001000Sesiones por día.
rateLimits.maxMessagesPerSessionbody integerNo1–10000100Mensajes por sesión.
rateLimits.requestsPerHourbody integerNoSe acepta, pero no se guarda ni aplica—Campo de compatibilidad.
cURL
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}

NombreTipoObligatorioValores aceptados / rangoDefaultDescripción
X-Api-Key (header)stringSíClave activa del tenant—Autenticación.
X-Tenant-Id (header)UUIDCondicionalTenant autorizadoTenant de la claveNecesario si la clave permite varios tenants.
idpath UUIDSíID del widget—Widget del tenant.
cURL
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

NombreTipoObligatorioValores aceptados / rangoDefaultDescripción
X-Api-Key (header)stringSíClave activa del tenant—Autenticación.
X-Tenant-Id (header)UUIDCondicionalTenant autorizadoTenant de la claveNecesario si la clave permite varios tenants.
idpath UUIDSíID del widget—Widget del tenant.
cURL
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

NombreTipoObligatorioValores aceptados / rangoDefaultDescripción
X-Api-Key (header)stringSíClave activa del tenant—Autenticación.
X-Tenant-Id (header)UUIDCondicionalTenant autorizadoTenant de la claveNecesario si la clave permite varios tenants.
idpath UUIDSíID del widget—Widget del tenant.
filemultipart fileSíPNG, JPEG o WebP; máximo 1 MiB—Avatar del widget.
cURL
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

NombreTipoObligatorioValores aceptados / rangoDefaultDescripción
X-Api-Key (header)stringSíClave activa del tenant—Autenticación.
X-Tenant-Id (header)UUIDCondicionalTenant autorizadoTenant de la claveNecesario si la clave permite varios tenants.
idpath UUIDSíID del widget—Widget del tenant.
cURL
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.