Para cada mensaje enviado desde la interfaz de Kommo al canal de chat, se envía un webhook a una dirección especificada. Al recibir un webhook, es crucial procesarlo y enviar un mensaje al mensajero.
Cada webhook se envía solo una vez; si la integración no puede procesarlo o recibirlo, no se volverá a intentar.
El tiempo de respuesta para el webhook está limitado, por lo que se recomienda verificar la firma de la solicitud inmediatamente al recibirla y manejar la lógica de negocio en segundo plano. Por ejemplo, puedes añadir la tarea a la fila de procesamiento y responder al webhook de manera inmediata.
Si un mensaje no puede ser aceptado por el mensajero integrado, deberías actualizar su estado a Error. Luego, de manera asincrónica, puedes procesar el mensaje, ejecutar la lógica de negocio y enviar el mensaje según sea necesario.
Actualmente, la ventana de respuesta para el webhook es de un máximo de 5 segundos. Para considerar que el webhook se ha enviado con éxito, tu integración debe responder con un código HTTP 200.
La API de Chat emplea mecanismos de priorización; si la integración tarda demasiado en responder o no responde, puede ser movida a una fila más lenta, lo que resultará en una entrega demorada de los webhooks. Esta prioridad se calcula dinámicamente en función de varios factores, lo que permite que la integración cambie entre filas más rápidas y más lentas según sea necesario.
Además, los eventos de “escribiendo” del administrador requieren suscripciones de webhook separadas para cada canal, las cuales pueden ser gestionadas a través del soporte técnico.
Webhook v2
Kommo te envía webhooks cuando un mensaje es enviado. Para recibirlos, debes especificar una URL de webhook en el campo "webhook_url"
al registrar un canal.
Cada webhook contiene un encabezado X-Signature, que se genera a partir del cuerpo de la solicitud utilizando el método HMAC-SHA1. El secreto del canal actúa como la clave secreta, lo que te permite verificar la autenticidad de los webhooks entrantes.
Para hacerlo, calcula el hash a partir del cuerpo de la solicitud entrante y compáralo con el valor en el encabezado X-Signature.
Enviar un mensaje
{
"account_id": "XXXXXXXX-d2eb-4bd8-b862-b57934927b38",
"time": 1670571014,
"message": {
"receiver": {
"id": "XXXXXXXX-a3ab-4695-832c-919dbfc598ea",
"name": "John",
"phone": "+123456789",
"email": "[email protected]",
"client_id": "XXXXXXXX-ec21-4463-965f-1fe1d4cd5a90"
},
"sender": {
"id": "XXXXXXX-ec21-4463-965f-1fe1d4cd5b89",
"name": "Gerente"
},
"conversation": {
"id": "XXXXXXXX-c40d-4efc-9f78-9625adac414c",
"client_id": "XXXXXXX-80c5-403d-93d9-bada6302810d"
},
"source": {
"external_id": "ChatSourceId"
},
"timestamp": 1670571014,
"msec_timestamp": 1670571014414,
"message": {
"id": "XXXXXXXX-2aa3-464c-b6e4-4386d0f8f3ca",
"type": "text",
"text": "¡Hola Agustín! Agendemos una llamada para la próxima semana",
"markup": null,
"tag": "",
"media": "",
"thumbnail": "",
"file_name": "",
"file_size": 0
}
}
}
{
"account_id": "XXXXXXXX-d75c-4ee0-a443-9adbb902f98d",
"time": 1730732453,
"message": {
"receiver": {
"id": "XXXXXXX-1bc4-457f-b941-9b699c958165",
"name": "John Johnson",
"phone": "+1234567890",
"client_id": "XXXXXXX-d95e-121212-3c0eeea9d897"
},
"sender": {
"id": "XXXXXXXXX-fadd-4995-8026-36fcc0c806bd",
"name": "Nicky"
},
"source": {
"external_id": "chatapi2externalid"
},
"conversation": {
"id": "XXXXXXXXX-4ccc-48a5-8bf3-68fed3cc74ba",
"client_id": "12-122131"
},
"timestamp": 1730732453,
"msec_timestamp": 1730732453229,
"message": {
"id": "XXXXXXXXXXX-2d28-4853-baec-5f8f7e5e4f8a",
"type": "picture",
"text": "",
"markup": null,
"tag": "",
"media": "https://drive-g.kommo.com/download/XXXXXXXX-fc00-5826-901a-6c9c06f128f0/1261ee39-232a-4433-a245-00b29ffbca97/a521d24e-52c2-4f99-9a3b-7741567f0529/Screenshot-1.png",
"thumbnail": "https://drive-g.kommo.com/download/XXXXXXXX-fc00-5826-901a-6c9c06f128f0/1261ee39-232a-4433-a245-00b29ffbca97/a521d24e-52c2-4f99-9a3b-7741567f0529/13fcba3b-d8c2-4ac9-b2b0-270a1a9f5671/Screenshot-1_320_130.png",
"file_name": "Screenshot_1.png",
"file_size": 24246
}
}
}
{
"account_id": "XXXXXX-d75c-4ee0-a443-9adbb902f98d",
"time": 1730734321,
"message": {
"receiver": {
"id": "XXXXXX-1bc4-457f-b941-9b699c958165",
"name": "John 1",
"phone": "+18305803077",
"client_id": "XXXXXXXX-d95e-121212-3c0eeea9d897"
},
"sender": {
"id": "XXXXXXXX-fadd-4995-8026-36fcc0c806bd",
"name": "Nicky"
},
"source": {
"external_id": "chatapi2externalid"
},
"conversation": {
"id": "XXXXXXXX-4ccc-48a5-8bf3-68fed3cc74ba",
"client_id": "XXXXXXX-adlw23d21-sad21d-221svr"
},
"timestamp": 1730734321,
"msec_timestamp": 1730734321314,
"message": {
"id": "XXXXXXX-81b4-4880-9f39-c890a1c011a9",
"type": "picture",
"text": "¡Hola Juan!¿Cómo estas?",
"markup": {
"mode": "inline",
"buttons": [
[
{
"text": "¡Bien!"
}
],
[
{
"text": "Estoy muy bien"
}
]
]
},
"tag": "",
"media": "https://drive-g.kommo.com/download/XXXXXXX-fc00-5826-901a-6c9c06f128f0/b4b1fc59-1825-48af-b378-ab433aa7f53a/9c882236-6825-4269-a527-b11534f8561b/Screenshot-1.png",
"thumbnail": "https://drive-g.kommo.com/download/XXXXXXXX-fc00-5826-901a-6c9c06f128f0/b4b1fc59-1825-48af-b378-ab433aa7f53a/9c882236-6825-4269-a527-b11534f8561b/0c349685-3a7c-4e16-91b1-114eb93ccd3b/Screenshot-1_320_130.png",
"file_name": "picture.png",
"file_size": 24249,
"template": {
"id": 34788,
"content": "¡Hola {{contact.name}}!¿Cómo estas",
"params": [
{
"key": "{{contact.name}}",
"value": "Juan"
}
]
}
}
}
}
{
"account_id": "XXXXXXXX-d75c-4ee0-a443-9adbb902f98d",
"time": 1730742708,
"message": {
"receiver": {
"id": "XXXXXXXX-1bc4-457f-b941-9b699c958165",
"name": "John",
"phone": "+18305803077",
"client_id": "XXXXXXXX-d95e-121212-3c0eeea9d897"
},
"sender": {
"id": "XXXXXXXXX-fadd-4995-8026-36fcc0c806bd",
"name": "Nicky"
},
"source": {
"external_id": "chatapi2externalid"
},
"conversation": {
"id": "XXXXXXX-4ccc-48a5-8bf3-68fed3cc74ba",
"client_id": "XXXXXXX-adlw23d21-sad21d-221svr"
},
"timestamp": 1730742708,
"msec_timestamp": 1730742708539,
"message": {
"id": "XXXXXXXX-628c-41ac-bdaa-a26b0372c27a",
"type": "text",
"text": "¡Hola!",
"markup": null,
"tag": "",
"media": "",
"thumbnail": "",
"file_name": "",
"file_size": 0,
"reply_to": {
"message": {
"id": "XXXXXXXX-832f-413b-b3f8-019fa2a5d274",
"msgid": "XXXXXXX-2sd21we12-f45665432",
"type": "text",
"text": "Hi!",
"timestamp": 1730367735,
"msec_timestamp": 1730367735000,
"sender": {
"id": "XXXXXX-1bc4-457f-b941-9b699c958165",
"name": "John",
"phone": "+18305803077",
"client_id": "XXXXXXXX-d95e-121212-3c0eeea9d897"
}
}
}
}
}
}
{
"account_id": "52e591f7-c98f-4255-8495-827210138c81",
"time": 1639572261,
"message": {
"receiver": {
"id": "2ed64e26-70a1-4857-8382-bb066a076219",
"phone": "79161234567",
"email": "[email protected]",
"client_id": "my_int-1376265f-86df-4c49-a0c3-a4816df41af8"
},
"sender": {
"id": "76fc2bea-902f-425c-9a3d-dcdac4766090"
},
"conversation": {
"id": "8e4d4baa-9e6c-4a88-838a-5f62be227bdc",
"client_id": "my_int-d5a421f7f218"
},
"source": {
"external_id": "78001234567"
},
"timestamp": 1639572260,
"msec_timestamp": 1639572260980,
"message": {
"id": "0371a0ff-b78a-4c7b-8538-a7d547e10692",
"type": "text",
"text": "Mensaje de texto del lead #15926745",
"markup": {
"list_message": {
"header": "¿Qué tipo de servicio deseas recibir?",
"body": "Por favor, selecciona una de las opciones de respuesta del menú haciendo clic en el botón de abajo.",
"footer": "Atentamente, Compañía de prueba",
"button": "Services",
"sections": [
{
"title": "Servicios disponibles",
"rows": [
{
"callback_data": "vG9ujre8N7",
"title": "Servicio 1",
"description": "Descripción de servicio 1"
}
]
}
]
}
}
}
}
}
Parámetros del cuerpo del webhook
Un mensaje puede recibirse junto con medios, texto y botones al mismo tiempo. Cuando se envían varios archivos adjuntos de una sola vez, el mensaje se dividirá en varios webhooks, pero todos compartirán un
message[message][media_group_id]
común.
Parámetro | Tipo de dato | Descripción |
---|---|---|
account_id | string | ID de cuenta de amojo. |
time | int | Marca de tiempo al generar el webhook en el formato de Unix Timestamp. |
message | obj | Un arreglo que contiene los componentes del message. |
message
Parámetro | Tipo de dato | Descripción |
---|---|---|
receiver | obj | Destinatario del mensaje. |
sender | obj | Remitente del mensaje. |
conversation | obj | Detalles de la conversación. |
source | obj | Información de la fuente del chat. |
timestamp | int | Marca de tiempo del mensaje en formato Unix Timestamp. |
msec_timestamp | int | Marca de tiempo del mensaje en milisegundos. |
message | obj | Contenido del mensaje. |
message.receiver
Parámetros | Tipo de dato | Descripción |
---|---|---|
id | string | ID del participante en el chat en el lado de la integración. |
name | string | Nombre del participante en el chat en el lado de la API de Chats. |
phone | string | Número de teléfono. El campo no se devuelve si no se pasó el perfil. |
string | Dirección de correo electrónico. El campo no se retorna si no se pasó el perfil. | |
client_id | string | ID del participante en el chat en el lado de la API de Chats. |
message.sender
Parámetros | Tipo de dato | Descripción |
---|---|---|
id | string | ID del participante en el chat en el lado de la integración. |
name | string | ombre del participante en el chat en el lado de la API de Chats. |
message.conversation
Parámetro | Tipo de dato | Descripción |
---|---|---|
id | string | ID del chat en la API de Chats. |
client_id | string | ID del chat en el lado de la integración. |
message.source
Parámetro | Tipo de dato | Descripción |
---|---|---|
external_id | string | ID de la fuente del chat en el lado de la integración. |
message.message
Parámetro | Tipo de dato | Descripción |
---|---|---|
id | string | ID amojo del mensaje. |
type | string | Tipo de mensaje, uno de los siguientes: text, file, video, picture, voice, audio, sticker. |
text | string | El campo es obligatorio para el tipo “text” , puede estar vacío para otros tipos. |
markup | obj | El objeto teclado que se muestra con el mensaje. |
media | string | URL al archivo, video, imagen, nota de voz, audio o sticker |
thumbnail | string | Enlace a la vista previa de la imagen o miniatura del video. |
file_name | string | Nombre del archivo desde la URL del campo “media” . |
file_size | int | Tamaño de los datos en el campo “media” . |
template | obj | Objeto de plantilla, si el mensaje fue enviado mediante una plantilla. |
reply_to | obj | Objeto del mensaje de respuesta. |
forwards | arr of obj | Objeto de mensaje reenviado. |
message.message.markup
El objeto markup consiste en un arreglo de arreglos de botones organizados en un diseño específico.
La forma de organización se indica en el campo mode. Actualmente, para las integraciones, este campo siempre contiene el valor "inline"
.
El valor "inline"
indica que el teclado debe mostrarse debajo del texto del mensaje.
Por el momento, no se pueden incluir botones de diferentes tipos en el mismo objeto.
Parámetros | Tipo de dato | Descripción |
---|---|---|
mode | string | Diseño del teclado. Valor posible:" inline" . |
button | obj | Arreglo de los objetos de botón. |
list_message | obj | Objeto de tipo mensaje List Message de WhatsApp. Estructura del objeto List Message. |
message.message.markup.buttons
Parámetros | Tipo de dato | Descripción |
---|---|---|
text | string | Texto. Cuando un usuario hace clic en un botón de texto, el mensajero debe enviar un mensaje con el texto de este botón al chat. |
button | obj | Enlace. Cuando un usuario hace clic en un botón de enlace, el mensajero debe seguir ese enlace. La propiedad puede no estar presente si se pasó otro tipo de botón. |
message.message.markup.list_message
Parametro | Tipo de dato | Descripción |
---|---|---|
header | string | Título del mensaje. Una cadena de hasta 60 caracteres (se admiten emojis). |
body | string | Cuerpo del mensaje. Una cadena de hasta 1024 caracteres (se admiten emojis y Markdown). |
footer | string | Parte inferior del mensaje. Línea de hasta 60 caracteres (se admiten emojis, enlaces y Markdown). |
button | string | Nombre del botón principal que se mostrará al usuario; cuando se haga clic en este botón, se abrirá un menú con las secciones transferidas. |
sections | array | Un arreglo de objetos (de 1 a 10 elementos) que describen elementos interactivos (secciones). |
sections[0] | object | Un objeto que describe una sección interactiva. |
sections[0][title] | string | Nombre de la sección. Una cadena de hasta 24 caracteres. |
sections[0][rows] | array | Un arreglo de objetos (de 1 a 10 elementos) que describen los botones individuales en la sección. |
sections[0][rows][0] | object | Un objeto que describe un solo botón en una sección. |
sections[0][rows][0][callback_data] | string | Un identificador único que se pasará a WhatsApp y se enviará con el botón seleccionado por el usuario en la propiedad callback_data del objeto mensaje. |
sections[0][rows][0][title] | string | Nombre del botón. |
sections[0][rows][0][description] | string | Descripción del botón. |
message.message.template
Parámetro | Tipo de dato | Descripción |
---|---|---|
id | string | El ID de la plantilla en Kommo. |
content | string | El texto de la plantilla sin interpretar los marcadores de posición. |
params | obj | Un objeto de placeholders. |
message.message.template.params
Parámetro | Tipo de dato | Descripción |
---|---|---|
key | string | Clave del placeholder. |
value | string | Valor del placeholder. |
message.message.reply_to
Parámetro | Tipo de dato | Descripción |
---|---|---|
message | obj | Objeto de mensaje de respuesta. Descripción del objeto de mensaje incrustado. |
message.message.reply_to.message (mensaje incrustado)
Parámetro | Tipo de dato | Descripción |
---|---|---|
id | int | El ID del mensaje citado en la API de Chats. Si se pasa este valor, no es necesario llenar los campos restantes; se determinarán automáticamente. En caso de pasar el ID, el desplazamiento hacia el mensaje también funcionará si el chat está en la misma tarjeta. |
msgid | int | El ID del mensaje citado en el lado de la integración. Si se pasa este valor, no es necesario llenar los campos restantes; se determinarán automáticamente. En caso de pasar el ID, el desplazamiento hacia el mensaje también funcionará si el chat está en la misma tarjeta.. |
type | string | Obligatorio si no se pasa un ID. El tipo de mensaje puede ser uno de los siguientes: text, contact, file, video, picture, voice, audio, sticker, location. |
text | string | Obligatorio para el tipo "text" si no se pasa un ID. Para otros tipos de mensajes, puede estar vacío. |
file_name | string | Opcional. Nombre del archivo. |
file_size | int | Opcional. Tamaño del archivo en bytes. |
media_duration | int | Opcional. Duración para mensajes de video/audio/voz. |
location | obj | Campo obligatorio para mensajes de tipo ubicación. |
location[lon] | float | Longitud. |
location[lat] | float | Latitud. |
sender | obj | Información del remitente del mensaje. Descripción del objeto Sender. |
message.message.reply_to.message.sender (usuario incrustado)
Parámetro | Tipo de dato | Descripción |
---|---|---|
id | string | ID del remitente en el lado de la integración. Si se pasa, no es necesario llenar los campos restantes; se determinarán automáticamente. |
ref_id | string | ID del remitente en la API de Chats. Si se pasa, no es necesario llenar los campos restantes; se determinarán automáticamente. |
name | string | Obligatorio si no se pasa un ID. Nombre del remitente. |
Webhook de escritura
El webhook se envía cuando el gestor está escribiendo un mensaje en la interfaz de Kommo.
El webhook se envía no más de una vez cada 5 segundos.
{
"account_id": "XXXXXXXX-d2eb-4bd8-b862-b57934927b38",
"time": 1670585310,
"action": {
"typing": {
"user": {
"id": "XXXXXXXX-ec21-4463-965f-1fe1d4cd5b89"
},
"conversation": {
"id": "XXXXXXX-9f3c-4d3f-8101-60327e14dc48",
"client_id": "XXXXXXXX-80c5-403d-93d9-bada6302810f"
},
"expired_at": 1670585315
}
}
}
Parámetros del cuerpo
Parámetros | Tipo de dato | Descripción |
---|---|---|
account_id | string | ID de cuenta amojo. |
time | int | Marca de tiempo al generar el webhook en formato de Unix Timestamp. |
action[typing][user][id] | string | ID del usuario que está escribiendo en la API de Chat. |
action[typing][conversation][id] | string | ID del chat en la API de Chats. |
action[typing][conversation][client_id] | string | Campo opcional. ID del chat en el lado de la integración. Si el chat fue creado utilizando la función Escribir primero, el campo no estará presente en el webhook. |
action[typing][expired_at] | int | Marca de tiempo cuando pensamos que el usuario ya no está escribiendo. Pasamos el tiempo final de escritura como el tiempo de inicio actual + 5 segundos. |
Webhook de reacción
El webhook se activa cuando el usuario reacciona a un mensaje o elimina su reacción dentro de la interfaz de Kommo.
{
"account_id": "XXXXXX-8952-4785-abe2-c8d93f5fcc7d",
"time": 1637087558,
"action": {
"reaction": {
"message":{
"id": "XXXXXXX-9e04-4e1d-bee9-37c71924cd11",
"client_id": "64ff3a9baeb11",
"sender":{
"id": "XXXXX-f502-4165-9377-8575c55c5ebd",
"name": "John Smith",
"phone": "+123456789",
"client_id": "14255551212"
},
"timestamp": 1694448283,
"msec_timestamp": 1694448283000
},
"user": {
"id": "XXXXXX-9e04-4e1d-bee9-37c71924cdc2"
},
"conversation": {
"id": "XXXXXXXX-f502-4165-9377-8575c55c5ebd",
"client_id": "c1234456"
},
"type": "react",
"emoji": "😍"
}
}
}
Parámetros del cuerpo
Parámetros | Tipo de dato | Descripción |
---|---|---|
account_id | string | ID de cuenta de la API de Chat. |
time | int | Hora de creación del webhook en formato de Unix Timestamp. |
action[reaction][message][id] | string | ID del mensaje en la API de Chat. |
action[reaction][message][client_id] | string | Campo opcional. ID del mensaje en el lado de la integración. Si el mensaje fue creado en el lado de Kommo, el campo no estará presente en el webhook. |
action[reaction][message][receiver] | obj | Un objeto con información sobre el destinatario del mensaje. |
action[reaction][message][sender] | obj | Un objeto con información sobre el remitente del mensaje. |
action[reaction][message][timestamp] | int | Hora de creación del mensaje en formato Unix Timestamp. |
action[reaction][message][msec_timestamp] | int | Hora de creación del mensaje en formato Unix Timestamp con milisegundos. |
action[reaction][user] | obj | Un objeto con información sobre el remitente de la reacción. |
action[reaction][conversation][id] | string | ID del chat en la API de Chat. |
action[reaction][conversation][client_id] | string | Campo opcional. ID del chat en el lado de la integración. Si el chat fue creado utilizando la función Escribir primero, el campo no estará presente en el webhook |
action[reaction][type] | string | Tipo de evento: "react" , "unreact" . |
action[reaction][emoji] | string | Campo opcional. Reacción proporcionada por el usuario. Si el usuario elimina la reacción, el campo no estará presente en el webhook. |