Guía
Usarlo en una app móvil
Sí. El widget es un cliente delgado sobre una API HTTP normal, y nada de esa API asume un navegador: sin cookies, sin redirecciones, entra JSON y sale JSON. Una app de iOS o Android habla con el mismo agente, del mismo plan, con la misma cuota. No hay un producto móvil aparte que comprar ni un SDK que instalar.
Lo que cambia es cómo la app demuestra quién es, y conviene acertarlo antes de publicar un binario que alguien puede desempaquetar.
Dos puertas de entrada, y cuál quieres
Si tu app ya tiene backend, úsalo. Tu servidor guarda el secreto del sitio y emite un token firmado de vida corta; la app le pide uno a tu servidor y nos lo envía. El secreto nunca viaja dentro de la app, un token expira en minutos, y tú decides cuál de tus usuarios recibe una conversación. Es el camino a seguir si tienes la opción.
Si tu app no tiene backend, puede llevar la clave pública del sitio — la misma clave que usa el widget de la web. Entiende lo que eso significa: la clave se puede extraer de cualquier binario de app, y a diferencia de una web no hay un dominio contra el que comprobarla. Tienes que activarlo deliberadamente, en el portal, en Also used from a mobile app de la pestaña Setup del sitio. Hasta que lo hagas, una petición sin origen de navegador se rechaza.
En ese caso también marca Require each app install to register, justo debajo. Tu app entonces llama a /v1/install una vez en la primera ejecución y guarda el id que recibe, enviándolo en todas las peticiones siguientes. Las peticiones tienen límite de tasa por instalación registrada, así que una clave extraída no le da a un solo llamador un camino sin restricciones a la cuota compartida del bot. Cuesta una llamada extra por instalación.
La secuencia de peticiones
URL base https://kavilo.cloud. Envía tu credencial como cabecera en cada petición — o Authorization: Bearer <token> o X-Kavilo-Key: kw_pub_….
POST /v1/install— una vez, en la primera ejecución, si marcaste el ajuste de arriba. Guarda elinstallIdque devuelve y envíalo comoX-Kavilo-Installa partir de entonces.POST /v1/session— abrir o reanudar. Envía{"conversationId": "…"}, vacío la primera vez. Te devuelve el id a guardar, un saludo, un cursor y el historial hasta ese momento.POST /v1/message— enviar un turno. Responde202al instante; la respuesta llega por el transporte que estés leyendo.POST /v1/poll— una de las dos maneras de recibir respuestas. Envía tu cursor y obtienes lo nuevo. Espera hasta 25 segundos antes de responder vacío, así que un bucle de estos es un long-poll, no una espera agotadora.GET /v1/stream— la alternativa al polling: recibe los mismos fotogramas como eventos server-sent.POST /v1/end— el visitante terminó. Envía la transcripción y cierra la conversación.
El polling y el stream leen el mismo búfer por el mismo cursor, así que puedes cambiar de uno a otro a mitad de conversación sin perder nada. En un móvil, el polling suele ser el más fácil de los dos: sobrevive a un cambio de red sin manejo especial, y no mantiene un socket abierto mientras el usuario lee.
Leer la respuesta
Cada fotograma tiene un seq, un kind y normalmente algo de text. Añade cada fotograma token a medida que llega. El turno termina en final, que trae la respuesta completa — tóma como autoritativa y reemplaza lo que acumulaste, para que una reconexión no te deje mostrando la respuesta dos veces. Un turno también puede terminar en error. Esos dos son los únicos finales; no hay un fotograma «done» aparte que esperar.
Un mensaje no siempre significa una respuesta. Si el visitante envía un segundo mensaje mientras el agente sigue respondiendo, se pliega en el mismo turno. Una app que se bloquee hasta contar una respuesta por mensaje acabará colgada; lee hasta final.
Segundo plano
Una conversación que se queda en silencio quince minutos se cierra y se envía su transcripción — la misma regla que aplica en la web, donde un visitante que cierra la pestaña se parece a uno que se toma un té. Un teléfono que se duerme cruza esa línea con facilidad.
Así que al volver al primer plano, llama de nuevo a /v1/session con el id que guardaste. Si la conversación sigue abierta, continúas; si se cerró, recibes una nueva, y en ambos casos la respuesta te da el historial para redibujar. Trata esa llamada como la forma en que se carga la pantalla, no como un manejo de errores.
Lo que aún no hay
Adjuntos. No hay un endpoint de subida en la API de chat, ni para apps ni para la web, así que un visitante no puede mandarte una foto de la pieza rota. Si para eso es tu app, dícelo — sube en la lista cuando alguien lo necesite de verdad.
Empieza aquí
Pídenos el cliente de referencia y te enviamos la secuencia completa en Swift y Kotlin — unas cien líneas cada una, y corta suficiente para leerla en lugar de confiar. Escribe a hello@kavilo.cloud y di en qué plataforma estás.