Recibir webhooks del chat

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ámetroTipo de datoDescripción
account_idstringID de cuenta de amojo.
timeintMarca de tiempo al generar el webhook en el formato de Unix Timestamp.
messageobjUn arreglo que contiene los componentes del message.

message

ParámetroTipo de datoDescripción
receiverobjDestinatario del mensaje.
senderobjRemitente del mensaje.
conversationobjDetalles de la conversación.
sourceobjInformación de la fuente del chat.
timestampintMarca de tiempo del mensaje en formato Unix Timestamp.
msec_timestampintMarca de tiempo del mensaje en milisegundos.
messageobjContenido del mensaje.

message.receiver

ParámetrosTipo de datoDescripción
idstringID del participante en el chat en el lado de la integración.
namestringNombre del participante en el chat en el lado de la API de Chats.
phonestringNúmero de teléfono. El campo no se devuelve si no se pasó el perfil.
emailstringDirección de correo electrónico. El campo no se retorna si no se pasó el perfil.
client_idstringID del participante en el chat en el lado de la API de Chats.

message.sender

ParámetrosTipo de datoDescripción
idstringID del participante en el chat en el lado de la integración.
namestringombre del participante en el chat en el lado de la API de Chats.

message.conversation

ParámetroTipo de datoDescripción
idstringID del chat en la API de Chats.
client_idstringID del chat en el lado de la integración.

message.source

ParámetroTipo de datoDescripción
external_idstringID de la fuente del chat en el lado de la integración.

message.message

ParámetroTipo de datoDescripción
idstringID amojo del mensaje.
typestringTipo de mensaje, uno de los siguientes: text, file, video, picture, voice, audio, sticker.
textstringEl campo es obligatorio para el tipo “text”, puede estar vacío para otros tipos.
markupobjEl objeto teclado que se muestra con el mensaje.
mediastringURL al archivo, video, imagen, nota de voz, audio o sticker
thumbnailstringEnlace a la vista previa de la imagen o miniatura del video.
file_namestringNombre del archivo desde la URL del campo “media”.
file_sizeintTamaño de los datos en el campo “media”.
templateobjObjeto de plantilla, si el mensaje fue enviado mediante una plantilla.
reply_toobjObjeto del mensaje de respuesta.
forwardsarr of objObjeto 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ámetrosTipo de datoDescripción
modestringDiseño del teclado. Valor posible:" inline".
buttonobjArreglo de los objetos de botón.
list_messageobjObjeto de tipo mensaje List Message de WhatsApp. Estructura del objeto List Message.

message.message.markup.buttons

ParámetrosTipo de datoDescripción
textstringTexto. 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.
buttonobjEnlace. 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

ParametroTipo de datoDescripción
headerstringTítulo del mensaje. Una cadena de hasta 60 caracteres (se admiten emojis).
bodystringCuerpo del mensaje. Una cadena de hasta 1024 caracteres (se admiten emojis y Markdown).
footerstringParte inferior del mensaje. Línea de hasta 60 caracteres (se admiten emojis, enlaces y Markdown).
buttonstringNombre 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.
sectionsarrayUn arreglo de objetos (de 1 a 10 elementos) que describen elementos interactivos (secciones).
sections[0]objectUn objeto que describe una sección interactiva.
sections[0][title]stringNombre de la sección. Una cadena de hasta 24 caracteres.
sections[0][rows]arrayUn arreglo de objetos (de 1 a 10 elementos) que describen los botones individuales en la sección.
sections[0][rows][0]objectUn objeto que describe un solo botón en una sección.
sections[0][rows][0][callback_data]stringUn 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]stringNombre del botón.
sections[0][rows][0][description]stringDescripción del botón.

message.message.template

ParámetroTipo de datoDescripción
idstringEl ID de la plantilla en Kommo.
contentstringEl texto de la plantilla sin interpretar los marcadores de posición.
paramsobjUn objeto de placeholders.

message.message.template.params

ParámetroTipo de datoDescripción
keystringClave del placeholder.
valuestringValor del placeholder.

message.message.reply_to

ParámetroTipo de datoDescripción
messageobjObjeto de mensaje de respuesta. Descripción del objeto de mensaje incrustado.

message.message.reply_to.message (mensaje incrustado)

ParámetroTipo de datoDescripción
idintEl 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.
msgidintEl 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..
typestringObligatorio 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.
textstringObligatorio para el tipo "text" si no se pasa un ID. Para otros tipos de mensajes, puede estar vacío.
file_namestringOpcional. Nombre del archivo.
file_sizeintOpcional. Tamaño del archivo en bytes.
media_durationintOpcional. Duración para mensajes de video/audio/voz.
locationobjCampo obligatorio para mensajes de tipo ubicación.
location[lon]floatLongitud.
location[lat]floatLatitud.
senderobjInformación del remitente del mensaje. Descripción del objeto Sender.

message.message.reply_to.message.sender (usuario incrustado)

ParámetroTipo de datoDescripción
idstringID 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_idstringID del remitente en la API de Chats. Si se pasa, no es necesario llenar los campos restantes; se determinarán automáticamente.
namestringObligatorio 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ámetrosTipo de datoDescripción
account_idstringID de cuenta amojo.
timeintMarca de tiempo al generar el webhook en formato de Unix Timestamp.
action[typing][user][id]stringID del usuario que está escribiendo en la API de Chat.
action[typing][conversation][id]stringID del chat en la API de Chats.
action[typing][conversation][client_id]stringCampo 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]intMarca 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ámetrosTipo de datoDescripción
account_idstringID de cuenta de la API de Chat.
timeintHora de creación del webhook en formato de Unix Timestamp.
action[reaction][message][id]stringID del mensaje en la API de Chat.
action[reaction][message][client_id]stringCampo 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]objUn objeto con información sobre el destinatario del mensaje.
action[reaction][message][sender]objUn objeto con información sobre el remitente del mensaje.
action[reaction][message][timestamp]intHora de creación del mensaje en formato Unix Timestamp.
action[reaction][message][msec_timestamp]intHora de creación del mensaje en formato Unix Timestamp con milisegundos.
action[reaction][user]objUn objeto con información sobre el remitente de la reacción.
action[reaction][conversation][id]stringID del chat en la API de Chat.
action[reaction][conversation][client_id]stringCampo 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]stringTipo de evento: "react", "unreact".
action[reaction][emoji]stringCampo opcional. Reacción proporcionada por el usuario. Si el usuario elimina la reacción, el campo no estará presente en el webhook.