Para cada mensagem enviada da interface Kommo para o canal de chat, um webhook é enviado para um endereço especificado. Ao receber um webhook, é crucial processá-lo e enviar a mensagem para o mensageiro.
Cada webhook é enviado apenas uma vez; se a integração falhar ao processá-lo ou recebê-lo, ele não será reenviado.
O tempo de resposta para o webhook é limitado, portanto, recomenda-se verificar imediatamente a assinatura da solicitação ao recebê-la e lidar com a lógica de negócios em segundo plano. Por exemplo, você pode colocar a tarefa em uma fila para processamento e responder prontamente ao webhook.
Se uma mensagem não puder ser aceita pelo mensageiro integrado, você deve atualizar seu status para Erro. Em seguida, em modo assíncrono, você pode processar a mensagem, executar sua lógica de negócios e enviar a mensagem conforme necessário.
Atualmente, a janela de resposta para o webhook é de no máximo 5 segundos. Para que o webhook seja considerado enviado com sucesso, sua integração deve responder com um código HTTP 200.
A API de Chat utiliza mecanismos de priorização; se a integração demorar muito para responder ou falhar, ela poderá ser movida para um fluxo mais lento, resultando em atrasos na entrega do webhook. Essa prioridade é calculada dinamicamente com base em vários fatores, permitindo que a integração mude entre filas mais rápidas e mais lentas conforme necessário.
Além disso, eventos de “digitando” do gerente exigem assinaturas separadas de webhook para cada canal, que podem ser organizadas por meio do Suporte Técnico.
Webhook v2
A Kommo envia webhooks quando uma mensagem é enviada. Para recebê-los, você precisa especificar um URL de webhook no campo "webhook_url"
ao registrar um canal.
Cada webhook contém um cabeçalho X-Signature, gerado a partir do corpo da solicitação usando o método HMAC-SHA1. O segredo do canal serve como a chave secreta, permitindo que você verifique a autenticidade dos webhooks recebidos.
Para fazer isso, calcule o hash do corpo da solicitação recebida e compare-o com o valor no cabeçalho X-Signature.
Enviando uma mensagem
{
"account_id": "XXXXXXXX-d2eb-4bd8-b862-b57934927b38",
"time": 1670571014,
"message": {
"receiver": {
"id": "XXXXXXXX-a3ab-4695-832c-919dbfc598ea",
"name": "Diego",
"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": "Olá João! Vamos agendar uma chamada semana que vem",
"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": "Diego",
"phone": "+1234567890",
"client_id": "XXXXXXX-d95e-121212-3c0eeea9d897"
},
"sender": {
"id": "XXXXXXXXX-fadd-4995-8026-36fcc0c806bd",
"name": "Nick"
},
"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": "Diego",
"phone": "+18305803077",
"client_id": "XXXXXXXX-d95e-121212-3c0eeea9d897"
},
"sender": {
"id": "XXXXXXXX-fadd-4995-8026-36fcc0c806bd",
"name": "Nick"
},
"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": "Olá João! Como você está?",
"markup": {
"mode": "inline",
"buttons": [
[
{
"text": "Fine!"
}
],
[
{
"text": "I'm fine"
}
]
]
},
"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": "Olá {{contact.name}}! Como você está?",
"params": [
{
"key": "{{contact.name}}",
"value": "John"
}
]
}
}
}
}
{
"account_id": "XXXXXXXX-d75c-4ee0-a443-9adbb902f98d",
"time": 1730742708,
"message": {
"receiver": {
"id": "XXXXXXXX-1bc4-457f-b941-9b699c958165",
"name": "Diego",
"phone": "+18305803077",
"client_id": "XXXXXXXX-d95e-121212-3c0eeea9d897"
},
"sender": {
"id": "XXXXXXXXX-fadd-4995-8026-36fcc0c806bd",
"name": "Nick"
},
"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": "Olá!",
"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": "Lead #15926745 Texto da mensagem",
"markup": {
"list_message": {
"header": "Que tipo de serviço você deseja receber?",
"body": "Por favor, selecione uma das opções de resposta no menu clicando no botão abaixo.",
"footer": "Atenciosamente, Empresa Teste",
"button": "Serviços",
"sections": [
{
"title": "Serviços disponíveis",
"rows": [
{
"callback_data": "vG9ujre8N7",
"title": "Serviço 1",
"description": "Descrição do Serviço 1"
}
]
}
]
}
}
}
}
}
Parâmetros do corpo do webhook
Uma mensagem pode ser recebida junto com mídia, texto e botões simultaneamente. Quando vários anexos são enviados de uma vez, a mensagem será dividida em vários webhooks, mas todos compartilharão um
message[message][media_group_id]
comum.
Parâmetro | Tipo de dado | Descrição |
---|---|---|
account_id | string | ID da conta amojo |
time | int | Timestamp ao gerar o webhook no formato de Unix Timestamp |
message | obj | Um array contém os componentes da mensagem. |
message
Parâmetro | Tipo de dado | Descrição |
---|---|---|
receiver | obj | Receptor da mensagem |
sender | obj | Remetente da mensagem |
conversation | obj | Detalhes da conversa |
source | obj | Informações da origem do chat |
timestamp | int | Timestamp da mensagem no formato de Unix Timestamp |
msec_timestamp | int | Timestamp da mensagem em milissegundos |
message | obj | O conteúdo da mensagem |
message.receiver
Parâmetro | Tipo de dado | Descrição |
---|---|---|
id | string | ID do participante do chat no lado da integração |
name | string | Nome do participante do chat no lado da API de Chats |
phone | string | Número de telefone. O campo não é retornado se o perfil não foi passado |
string | Endereço de e-mail. O campo não é retornado se o perfil não foi passado | |
client_id | string | ID do participante do chat no lado da API de Chats |
message.sender
Parâmetro | Tipo de dado | Descrição |
---|---|---|
id | string | ID do participante do chat no lado da integração |
name | string | Nome do participante do chat no lado da API de Chats |
message.conversation
Parâmetro | Tipo de dado | Descrição |
---|---|---|
id | string | ID do chat na API de Chats |
client_id | string | ID do chat no lado da integração |
message.source
Parâmetro | Tipo de dado | Descrição |
---|---|---|
external_id | string | ID da origem do chat no lado da integração |
message.message
Parâmetro | Tipo de dado | Descrição |
---|---|---|
id | string | ID amojo da mensagem |
type | string | Tipo de mensagem, um dos seguintes: texto, arquivo, vídeo, imagem, voz, áudio, adesivo |
text | string | O campo é obrigatório para o tipo “text” , podendo estar vazio para outros tipos |
markup | obj | O objeto de teclado para exibição com a mensagem |
media | string | URL para o arquivo, vídeo, imagem, voz, áudio ou adesivo |
thumbnail | string | Link para a imagem de pré-visualização ou miniatura do vídeo |
file_name | string | Nome do arquivo do campo de URL “media” |
file_size | int | Tamanho dos dados no campo “media” |
template | obj | Objeto de modelo, se a mensagem foi enviada usando um modelo |
reply_to | obj | Objeto de mensagem de resposta |
forwards | arr of obj | Objeto de mensagem encaminhada |
message.message.markup
O objeto de marcação consiste em uma matriz de matrizes de botões organizados em um layout especificado
O método de organização é indicado no campo mode. Atualmente, para integrações, esse campo sempre contém o valor "inline"
.
O valor "inline"
indica que o teclado deve ser posicionado abaixo do texto da mensagem.
Neste momento, botões de diferentes tipos não podem ser incluídos no mesmo objeto.
Parâmetro | Tipo de dado | Descrição |
---|---|---|
mode | string | Layout do teclado. Valor possível:" inline" . |
button | obj | Matriz de objetos botoes |
list_message | obj | Objeto de mensagem do tipo WhatsApp List. Estrutura do objeto de mensagem de lista |
message.message.markup.buttons
Parâmetro | Tipo de dado | Descrição |
---|---|---|
text | string | Texto. Quando um usuário clica em um botão de texto, o mensageiro deve enviar uma mensagem com o texto desse botão para o chat. |
button | obj | Link. Quando um usuário clica em um botão de link, o mensageiro deve seguir esse link. A propriedade pode estar ausente se outro tipo de botão for passado. |
message.message.markup.list_message
Parâmetro | Tipo de dado | Descrição |
---|---|---|
header | string | Título da mensagem. Uma string de até 60 caracteres (suporta emojis). |
body | string | Corpo da mensagem. Uma string de até 1024 caracteres (suporta emojis e Markdown). |
footer | string | Rodapé da mensagem. Uma linha de até 60 caracteres (suporta emojis, links e Markdown). |
button | string | Nome do botão principal que será exibido ao usuário; ao clicar nesse botão, um menu com as seções transferidas é aberto. |
sections | array | Um array de objetos (1 a 10 elementos) descrevendo elementos interativos (seções). |
sections[0] | object | Um objeto descrevendo uma seção interativa. |
sections[0][title] | string | Nome da seção. Uma string de até 24 caracteres. |
sections[0][rows] | array | Um array de objetos (1 a 10 elementos) descrevendo botões individuais na seção. |
sections[0][rows][0] | object | Um objeto que descreve um único botão em uma seção. |
sections[0][rows][0][callback_data] | string | Um identificador único a ser passado para o WhatsApp e enviado com o botão selecionado pelo usuário na propriedade callback_data do objeto da mensagem. |
sections[0][rows][0][title] | string | Nome do botão |
sections[0][rows][0][description] | string | Descrição do botão |
message.message.template
Parâmetro | Tipo de dado | Descrição |
---|---|---|
id | string | ID do modelo na Kommo |
content | string | O texto do modelo sem interpretar os espaços reservados |
params | obj | Um objeto dos espaços reservados |
message.message.template.params
Parâmetro | Tipo de dado | Descrição |
---|---|---|
key | string | Chave do espaço reservado |
value | string | Valor do espaço reservado |
message.message.reply_to
Parâmetro | Tipo de dado | Descrição |
---|---|---|
message | obj | Objeto de mensagem de resposta. Descrição do objeto de mensagem incorporada |
message.message.reply_to.message (mensagem incorporada)
Parâmetro | Tipo de dado | Descrição |
---|---|---|
id | int | O ID da mensagem citada na API de Chats. Se passado, os demais campos não precisam ser preenchidos, pois serão determinados automaticamente. Em caso de passagem do ID, o deslocamento para a mensagem também funcionará se o chat estiver no mesmo cartão. |
msgid | int | O ID da mensagem citada no lado da integração. Se passado, os demais campos não precisam ser preenchidos, pois serão determinados automaticamente. Em caso de passagem do ID, o deslocamento para a mensagem também funcionará se o chat estiver no mesmo cartão. |
type | string | Obrigatório se nenhum ID for passado. O tipo de mensagem pode ser um dos seguintes: texto, contato, arquivo, vídeo, imagem, áudio, voz, adesivo, localização. |
text | string | Obrigatório para o tipo “texto” se nenhum ID for passado. Para outros tipos de mensagens, pode estar vazio. |
file_name | string | Opcional. Nome do arquivo |
file_size | int | Opcional. Tamanho do arquivo em bytes |
media_duration | int | Opcional. Duração para mensagens de vídeo/áudio/voz |
location | obj | Campo obrigatório para mensagens do tipo localização |
location[lon] | float | Longitude |
location[lat] | float | Latitude |
sender | obj | Informações do remetente da mensagem. Descrição do objeto de remetente |
message.message.reply_to.message.sender (usuário incorporado)
Parâmetro | Tipo de dado | Descrição |
---|---|---|
id | string | ID do remetente no lado da integração; se passado, os demais campos não precisam ser preenchidos, pois serão determinados automaticamente. |
ref_id | string | ID do remetente na API de Chats; se passado, os demais campos não precisam ser preenchidos, pois serão determinados automaticamente. |
name | string | Obrigatório se nenhum ID for passado. Nome do remetente |
Webhook de digitação
O webhook é enviado quando o gerente digita uma mensagem na interface da Kommo.
O webhook é enviado no máximo uma vez a 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 do corpo
Parâmetro | Tipo de dado | Descrição |
---|---|---|
account_id | string | ID da conta amojo |
time | int | Carimbo de data/hora ao gerar o webhook no formato de Carimbo de data/hora Unix |
action[typing][user][id] | string | ID do usuário que executa a escrita na API de bate-papo |
action[typing][conversation][id] | string | ID do bate-papo na API de bate-papo |
action[typing][conversation][client_id] | string | Campo opcional. ID do bate-papo no lado da integração. Se o bate-papo foi criado usando a função escrever primeiro, o campo estará ausente no gancho |
action[typing][expired_at] | int | Carimbo de data/hora em que achamos que o usuário não está mais digitando. Passamos o carimbo de data/hora do final da digitação como o horário atual de início da impressão + 5 segundos |
Webhook de reação
O webhook é acionado quando o usuário reage a uma mensagem ou remove sua reação na interface 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": "Diego",
"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 do corpo
Parâmetro | Tipo de dado | Descrição |
---|---|---|
account_id | string | ID da conta da API de bate-papo |
time | int | Hora de criação do webhook no formato de Carimbo de data/hora Unix |
action[reaction][message][id] | string | ID da mensagem da API de bate-papo |
action[reaction][message][client_id] | string | Campo opcional. ID da mensagem no lado da integração. Se a mensagem foi criada no lado do Kommo, o campo não estará no webhook |
action[reaction][message][receiver] | obj | Um objeto com informações sobre o destinatário da mensagem. |
action[reaction][message][sender] | obj | Um objeto com informações sobre o remetente da mensagem. |
action[reaction][message][timestamp] | int | Hora de criação da mensagem no formato de Carimbo de data/hora Unix |
action[reaction][message][msec_timestamp] | int | Hora de criação da mensagem no formato de Carimbo de data/hora Unix com milissegundos |
action[reaction][user] | obj | Um objeto com informações sobre o remetente da reação. |
action[reaction][conversation][id] | string | ID do bate-papo na API de bate-papo |
action[reaction][conversation][client_id] | string | Campo opcional. ID do bate-papo no lado da integração. Se o bate-papo foi criado usando a função escrever primeiro, o campo estará ausente no gancho |
action[reaction][type] | string | Tipo de evento: "react" , "unreact" |
action[reaction][emoji] | string | Campo opcional. Reação fornecida pelo usuário. Se o usuário remover a reação, o campo não estará no webhook |