Referencia de la API del widget externo
URL base
La API del widget se sirve desde tu Salesforce Site, bajo la ruta /services/apexrest/redaai/chat/v1/:
https://<your-org>.my.salesforce-sites.com/chat/services/apexrest/redaai/chat/v1/
El host exacto depende del dominio de tu Site. Obtenlo desde Configuración › Sites; el script de carga que incrustas en tu sitio web usa la misma ruta en el atributo data-endpoint.
Autenticación
Cada solicitud requiere una clave de API. Pásala como encabezado HTTP o en el cuerpo de la solicitud — la API comprueba ambos:
| Dónde | Nombre |
|---|---|
| Encabezado HTTP | X-REDAAI-API-Key |
| Campo del cuerpo | clientKey |
Salesforce Sites puede eliminar los encabezados personalizados en algunas configuraciones, por lo que existe la alternativa en el cuerpo. Usa cualquiera de las dos; la forma del cuerpo es más confiable en CDN y proxies, y es la que usa de forma predeterminada el cargador del widget incluido.
Después de /init, cada solicitud posterior también necesita el token de sesión que devuelve /init:
| Dónde | Nombre |
|---|---|
| Encabezado HTTP | X-REDAAI-Session |
| Campo del cuerpo | sessionToken |
Consulta Administración de claves de API para generar, rotar y revocar claves.
CORS
La API refleja Access-Control-Allow-Origin para las llamadas desde el navegador. La definición de agente puede restringir las llamadas mediante el campo Orígenes permitidos (lista de orígenes separados por comas); déjalo en blanco para permitir cualquier origen. Cuando está configurado, solo los orígenes de la lista tienen éxito; los demás reciben un error ORIGIN_NOT_ALLOWED.
Cambiado en la V1.13. El origen se toma del encabezado Origin de la solicitud, no del cuerpo de la solicitud. Por lo tanto, una solicitud sin encabezado Origin — cualquier llamada de servidor a servidor — se rechaza cuando Orígenes permitidos está configurado. Consulta POST /chat/v1/init.
Endpoints
Cuatro endpoints, todos POST. Las solicitudes OPTIONS de verificación previa (pre-flight) se gestionan automáticamente.
| Ruta | Propósito |
|---|---|
POST /chat/v1/init | Inicia una nueva sesión de chat y devuelve un token de sesión. |
POST /chat/v1/message | Envía un mensaje del usuario y recibe la respuesta del agente. |
POST /chat/v1/action | Ejecuta una acción confirmada que el agente propuso. |
POST /chat/v1/history | Obtiene los mensajes de la conversación de la sesión activa. |
POST /chat/v1/continue | Pide al agente que relate el resultado de las acciones que ejecutó automáticamente en el turno anterior. No se envía ningún mensaje nuevo del usuario. |
POST /chat/v1/init
Valida la clave de API, comprueba el origen de la llamada y crea una sesión. Devuelve el token de sesión junto con los metadatos del agente que tu widget necesita para representar el estado de bienvenida.
Cuerpo de la solicitud
{
"clientKey": "<tu clave de API>"
}
Cambiado en la V1.13. El origen de la llamada ahora se toma del encabezado Origin de la solicitud — lo establece el navegador y no lo pueden sobrescribir los scripts de la página. Un campo origin en el cuerpo de la solicitud aún se acepta por compatibilidad con versiones anteriores, pero se ignora: un valor proporcionado por la llamada no puede usarse para restringir la llamada misma. Los widgets que aún lo envían siguen funcionando sin cambios.
Esto es importante para las llamadas que no provienen del navegador. Una solicitud de servidor a servidor no lleva encabezado Origin, por lo que se rechaza con ORIGIN_NOT_ALLOWED cuando el agente tiene configurado Orígenes permitidos. Si llamas a esta API desde tu propio backend, deja Orígenes permitidos en blanco y restringe el acceso de otra manera. Consulta Configuración de los orígenes permitidos.
Respuesta (200 OK)
{
"sessionToken": "<token de sesión opaco>",
"agentName": "support-assistant",
"displayName": "Support Assistant",
"welcomeMessage": "Hi! How can I help today?",
"mascotImage": "https://…/mascot.png",
"maxMessageLength": 2000
}
sessionToken— pásalo en cada solicitud posterior.agentName— el identificador del agente, útil para el análisis del lado del cliente.displayName— el nombre legible que se muestra en el encabezado del widget y en la sección principal de bienvenida.welcomeMessage— el texto de bienvenida externo configurado del agente. Cadena vacía cuando no está configurado.mascotImage— la URL de la mascota cuando hay una configurada. Cadena vacía cuando no la hay.maxMessageLength— el límite de longitud de los mensajes del usuario, en caracteres.
POST /chat/v1/message
Envía un único mensaje del usuario al agente. Devuelve la respuesta del agente una vez que se completa el bucle agéntico.
Cuerpo de la solicitud
{
"clientKey": "<tu clave de API>",
"sessionToken": "<from /init>",
"message": "What's open on the Acme account?"
}
Los mensajes que superan maxMessageLength (devuelto por /init) se rechazan con INVALID_INPUT.
Respuesta (200 OK)
{
"response": "<texto de respuesta del agente>",
"creditsUsed": 1.42,
"conversationId": "a0Q…",
"pendingActions": [],
"continuationPending": true,
"continuationDepth": 0
}
response— la respuesta del agente, incluidos los marcadores SUGGESTIONS o ACTION incrustados que analiza el renderizador del widget.creditsUsed— créditos consumidos en este turno.conversationId— el ID de Salesforce del registro de conversación. Útil para hacer referencias cruzadas con la transcripción de la Conversación en Salesforce.pendingActions— acciones pendientes de confirmación por el cliente. En el canal de widget externo siempre está vacío, porque las tarjetas de confirmación solo existen en el canal interno. Consulta POST /chat/v1/action más abajo.continuationPending—truecuando el agente ha ejecutado una o más acciones en este turno y todavía no ha narrado el resultado. Llama a/chat/v1/continuepara obtener esa narración.continuationDepth— cuántos turnos de continuación se han ejecutado ya. Devuélvelo en la siguiente llamada a/continue.
POST /chat/v1/action
Ejecuta bajo demanda una herramienta de Acción concreta. Solo se aceptan las herramientas de Acción asignadas al agente y con alcance al canal de widget externo.
El canal de widget externo no usa tarjetas de confirmación. Estas existen únicamente en el
canal interno. Cuando un agente de widget decide ejecutar una acción, REDA AI la ejecuta de
inmediato, captura el resultado real y marca continuationPending para que el agente
narre lo que hizo en la siguiente llamada a /continue. Nada espera a un clic.
Por tanto, este endpoint no es la segunda mitad de un intercambio de confirmación: existe para los widgets que gestionan su propia interfaz de acciones (tus propios botones, tu propio paso de confirmación) y quieren activar una herramienta concreta por su cuenta.
Asigna las herramientas de Acción a un agente de widget público de forma deliberada. Cualquier herramienta de Acción a la que el agente pueda acceder se ejecutará sin control humano. Da a un agente de cara al cliente solo las herramientas que aceptes que se ejecuten a petición de un visitante.
Cuerpo de la solicitud
{
"clientKey": "<tu clave de API>",
"sessionToken": "<from /init>",
"actionTool": "create_record",
"params": {
"object_name": "Case",
"field_values": { "Subject": "Issue with login", "…": "…" }
}
}
Respuesta (200 OK)
{
"success": true,
"result": "<tool execution result, JSON-serialised>"
}
La forma de result coincide con el resultado de la herramienta subyacente. Para las herramientas de acción integradas, eso significa una carga útil estructurada con al menos un indicador success, un message y (cuando corresponde) un recordId.
POST /chat/v1/continue
Pide al agente que narre el resultado de las acciones que ejecutó en el turno /message anterior.
No se envía ningún mensaje nuevo del usuario. Llámalo siempre que una respuesta vuelva con
continuationPending: true.
Cuerpo de la solicitud
{
"clientKey": "<tu clave de API>",
"sessionToken": "<de /init>",
"continuationDepth": 0
}
Respuesta (200 OK)
{
"response": "<narración del agente sobre lo ocurrido>",
"creditsUsed": 0.68,
"conversationId": "a0Q…",
"continuationPending": false,
"continuationDepth": 1
}
continuationPending sigue siendo true si el agente encadenó otra acción mientras
narraba, así que trátalo como un bucle: sigue llamando a /continue, devolviendo el
continuationDepth recibido, hasta que vuelva como false. El ajuste
Profundidad máxima de continuación del agente acota la cadena, de modo que siempre termina.
Una continuación es una llamada real al modelo. Consume créditos y ejecuta la misma
validación que /message — interruptor maestro, clave de API, sesión, límites de tasa por
sesión y por hora, y tope diario de créditos — por lo que puede devolver 429 con
RATE_LIMITED o CREDIT_LIMIT. También reinicia el temporizador de inactividad de la
sesión, igual que un mensaje.
POST /chat/v1/history
Devuelve hasta 100 mensajes de la conversación de la sesión, del más antiguo al más reciente. Útil cuando el widget se vuelve a conectar después de una actualización y necesita restaurar el hilo visible.
Cuerpo de la solicitud
{
"clientKey": "<tu clave de API>",
"sessionToken": "<from /init>"
}
Respuesta (200 OK)
{
"messages": [
{ "role": "user", "content": "…", "timestamp": "2026-04-25T08:55:12.000Z" },
{ "role": "assistant", "content": "…", "timestamp": "2026-04-25T08:55:14.000Z" }
]
}
Respuestas de error
Todos los errores comparten la misma forma:
{
"error": "<localised user-facing message>",
"code": "<machine-readable code>"
}
Usa code para las decisiones programáticas en tu cliente; muestra error al usuario final.
| HTTP | Código | Significado |
|---|---|---|
| 403 | DISABLED | El interruptor principal del Bot externo está desactivado. |
| 401 | INVALID_API_KEY | La clave de API falta, tiene un formato incorrecto o está revocada. |
| 403 | ORIGIN_NOT_ALLOWED | El origen de la llamada no está en la lista de Orígenes permitidos del agente. |
| 401 | SESSION_EXPIRED | El token de sesión no es válido o ha caducado (según los Minutos de tiempo de espera de sesión). |
| 429 | RATE_LIMITED | Se superó el límite de tasa de la sesión o del agente. |
| 429 | MAX_MESSAGES | La sesión alcanzó su tope de Máximo de mensajes por sesión. |
| 429 | CREDIT_LIMIT | Se agotó el Tope de crédito diario externo de la organización, o el presupuesto de créditos de la licencia. |
| 400 | INVALID_INPUT | Falta un parámetro del cuerpo, el mensaje es demasiado largo o la herramienta de acción es desconocida. |
| 404 | GENERIC_ERROR | Subruta desconocida bajo /chat/v1/. |
| 500 | GENERIC_ERROR | Un error inesperado. Los detalles se registran en el Registro de incidentes; la respuesta los oculta intencionalmente. |
Límites de tasa
Cada llamada pasa por varios limitadores de tasa en orden. Los dos primeros y el tope de mensajes se configuran por agente en la Definición de agente; el tope diario de créditos es de toda la organización, un ajuste de plataforma compartido por todos los agentes externos, de modo que un solo bot con mucho tráfico puede agotar el presupuesto del día para todos. Ponerlo en 0 significa ilimitado: no recomendable en un widget público.
| Límite | Origen | Predeterminado |
|---|---|---|
| Por sesión | Definición de agente › Límite de tasa por sesión | 10 llamadas por sesión |
| Por hora | Definición de agente › Límite de tasa por hora | 500 llamadas por agente por hora |
| Tope de crédito diario | Configuración de la plataforma › Tope de crédito diario externo | 500 créditos por día |
| Máximo de mensajes por sesión | Definición de agente › Máximo de mensajes por sesión | 50 mensajes |
Consulta Referencia de configuración de la plataforma para conocer los detalles del tope de crédito diario.
Ciclo de vida de la sesión
- Creación:
/initcrea una sesión vinculada a la IP del cliente que llama y al origen validado. - Validez: las sesiones permanecen válidas mientras se usen. La actividad en
/message,/actiono/historyreinicia la sesión. - Tiempo de espera: las sesiones inactivas caducan después de los Minutos de tiempo de espera de sesión del agente (30 de forma predeterminada). Las llamadas con un token de sesión caducado reciben
SESSION_EXPIRED; el widget debería volver a llamar a/init. - Límites estrictos: una sesión termina cuando alcanza el Máximo de mensajes por sesión. Las llamadas posteriores reciben
MAX_MESSAGEShasta que se crea una nueva sesión.
Configuración requerida en el agente
Varios campos de la Definición de agente determinan el comportamiento del widget:
| Campo | Propósito |
|---|---|
| Canal | Debe ser External Widget para un agente de cara al exterior. |
| Clave de API externa | La clave que el widget pasa como clientKey. Se genera desde la pestaña de administración. |
| Orígenes permitidos | Lista de orígenes permitidos separados por comas (p. ej., https://www.example.com). En blanco = se permite cualquier origen. |
| Longitud máxima del mensaje | Límite de la longitud del mensaje del usuario en caracteres. |
| Minutos de tiempo de espera de sesión | Tiempo de espera por inactividad de las sesiones. |
| Límite de tasa por sesión | Límite de llamadas por sesión. |
| Límite de tasa por hora | Límite por hora por agente en todas las sesiones. |
| Máximo de mensajes por sesión | Límite estricto de mensajes por sesión. |
| Mensaje de bienvenida externo | Devuelto por /init como welcomeMessage. |
| Imagen de mascota | Devuelto por /init como mascotImage. |
Postura de seguridad
- Ejecución como usuario invitado. La API se ejecuta como el usuario invitado del Salesforce Site. Los permisos CRUD y FLS del perfil de ese usuario determinan lo que el agente y cualquier herramienta pueden leer o escribir.
- Clave de API con alcance a un solo agente. Cada agente externo tiene su propia clave; revócala y rótala por agente sin afectar a los demás.
- Orígenes en lista de permitidos. Configura Orígenes permitidos en cada agente de producción. En blanco significa que cualquier origen puede llamar — cómodo para pruebas, arriesgado en producción.
- Mensajes de error genéricos. La API nunca refleja errores internos a los clientes. Las fallas graves se registran en el Registro de incidentes para su investigación por parte del administrador.
- Tope de crédito diario. El Tope de crédito diario externo es el límite máximo de toda la organización que impide que un bot público descontrolado agote el presupuesto de la licencia.
Prácticas recomendadas
Usa el cargador incluido a menos que tengas un motivo para no hacerlo. El cargador se encarga de la invalidación de caché, las alternativas de encabezados, la representación de errores y los atributos de datos de Personalización de la interfaz del widget. Crear tu propio cliente solo tiene sentido para las llamadas que no provienen del navegador (aplicaciones móviles, integraciones de servidor).
Trata code como la fuente de verdad. La cadena error está localizada para los usuarios finales y puede cambiar entre versiones. El code es estable.
Reinicia las sesiones ante SESSION_EXPIRED, no ante cualquier error. El cargador del widget lo hace; los clientes personalizados también deberían hacerlo. No trates RATE_LIMITED ni CREDIT_LIMIT como problemas de sesión — requieren una recuperación diferente (espera con retroceso y atención del administrador, respectivamente).
Configura Orígenes permitidos en cada agente de cara al público. Dejarlo en blanco en producción elimina una capa de defensa en profundidad.
Vigila el tope de crédito diario. Es la red de seguridad para los bots de cara al público; ajústalo después de observar el tráfico real.
Cambios incluidos en 1.16000
El límite horario por agente también se aplica durante la última hora UTC del día. Las API externa y de Comunidad utilizan un código estable de límite de créditos para que la respuesta HTTP 429 no dependa del mensaje traducido.
Lista de actualización del cliente
Preguntas frecuentes
No. Los cuatro endpoints son el contrato público. Puedes crear tu propio cliente — móvil, de escritorio, de voz, web personalizado — contra la misma API.
No lo hagas. Las sesiones están diseñadas para turnos secuenciales. Las llamadas en paralelo sobre la misma sesión pueden entrar en conflicto con los limitadores de tasa y el registro de Conversación. Espera la respuesta de cada /message antes de enviar el siguiente.
Durante los Minutos de tiempo de espera de sesión configurados (30 de forma predeterminada) de inactividad. Cada llamada correcta reinicia el temporizador. Las sesiones también terminan cuando se alcanza el Máximo de mensajes por sesión.
Porque la infraestructura de Salesforce Sites puede eliminar los encabezados personalizados en ciertas configuraciones de proxy y CDN. La alternativa en el cuerpo es más confiable; la forma con encabezado es cómoda cuando tú controlas la ruta de red.
Los cuatro endpoints documentados aquí cubren el flujo conversacional. La carga de archivos desde widgets externos sigue las convenciones de gestión de archivos de la plataforma; consulta la configuración Permitir carga de archivos del agente y la guía Carga de archivos.
La conversación persiste en Salesforce. Las nuevas sesiones del mismo usuario final inician una conversación nueva; la plataforma no encadena automáticamente las sesiones entre sí para los usuarios invitados.
Genera la nueva clave, actualiza tu script de carga y revoca la clave anterior. Las sesiones que se iniciaron con la clave anterior continúan mientras no hagan una nueva llamada después de la revocación; las nuevas llamadas con la clave anterior fallan con INVALID_API_KEY. Consulta Administración de claves de API.
Próximos pasos
Lee Administración de claves de API para la emisión de claves, o Referencia de la API de Comunidad para su equivalente en el portal autenticado.