Webhooks

O webhook da Graph API para a WhatsApp Cloud API é uma funcionalidade que permite receber notificações em tempo real sobre eventos e interações ocorrendo na plataforma do WhatsApp. Quando você configura um webhook, a Graph API enviará solicitações HTTP POST para uma URL especificada por você sempre que ocorrer um evento relevante. Ele é uma forma eficiente de receber atualizações instantâneas, como mensagens recebidas, mensagens enviadas, status de entrega, leitura de mensagens e outros eventos importantes relacionados à interação com os usuários do WhatsApp.

Para acessar o contrato atualizado do webhook da Graph API para a WhatsApp Cloud API, é necessário consultar a documentação oficial do Facebook para desenvolvedores. Lá, você encontrará todas as informações detalhadas sobre o formato das mensagens enviadas pelo webhook, a estrutura dos eventos, os parâmetros disponíveis e outras especificações técnicas relevantes.
Segue abaixo um modelo do contrato de webhook que contempla todos os tipos de webhooks atualmente suportados da Graph API v16, messages, message_template_status_update, template_performance_metrics e o template_category_update:

CONSIDERAÇÕES INICIAIS

Este documento apresenta os objetos dos eventos da Meta que são disparados via webhooks. Quando nosso sistema faz o redirecionamento para um webhook cadastrado, somente o objeto value é enviado. Observe o exemplo a seguir.

Payload que recebemos da Meta:

{  
  "object": "whatsapp_business_account",  
  "entry": \[  
    {  
      "id": "<WABA>",  
      "changes": \[  
        {  
          "value": {  
            "messaging_product": "whatsapp",  
            "metadata": {  
              "display_phone_number": "<WABA-PHONE>",  
              "phone_number_id": "<WABA-PHONE-ID>"  
            },  
            "statuses": [  
              {  
                "id": "<WAMID>",  
                "status": "sent",  
                "timestamp": "1702587110",  
                "recipient_id": "<RECEIVER-WA-ID>",  
                "conversation": {  
                  "id": "<CONVERSATION-ID>",  
                  "expiration_timestamp": "1702669320",  
                  "origin": {  
                    "type": "marketing"  
                  }  
                },  
                "pricing": {  
                  "billable": true,  
                  "pricing_model": "CBP",  
                  "category": "marketing"  
                }  
              }  
            ]  
          },  
          "field": "messages"  
        }  
      ]  
    }  
  ]  
}

Payload que é redirecionado para o webhook do cliente:

{  
  "messaging_product": "whatsapp",  
  "metadata": {  
    "display_phone_number": "<WABA-PHONE>",  
    "phone_number_id": "<WABA-PHONE-ID>"  
  },  
  "statuses": [  
    {  
      "id": "<WAMID>",  
      "status": "sent",  
      "timestamp": "1702587110",  
      "recipient_id": "<RECEIVER-WA-ID>",  
      "conversation": {  
        "id": "<CONVERSATION-ID>",  
        "expiration_timestamp": "1702669320",  
        "origin": {  
          "type": "marketing"  
        }  
      },  
      "pricing": {  
        "billable": true,  
        "pricing_model": "CBP",  
        "category": "marketing"  
      }  
    }  
  ]  
}

TIPOS DE EVENTOS TRATADOS

Os tipos tratados são aqueles eventos que estão disponíveis para recebimento via webhook, ou seja, o cliente pode se inscrever para recebe-los.

messages

Envio de mensagem com falha

{  
	"messaging_product": "whatsapp",  
	"metadata": {  
		"display_phone_number": "<WABA-PHONE>",  
		"phone_number_id": "<WABA-PHONE-ID>"  
	},  
	"statuses": \[  
		{  
			"id": "<WAMID>",  
			"status": "failed",  
			"timestamp": "1702586868",  
			"recipient_id": "<RECEIVER-WA-ID>",  
			"errors": [  
				{  
					"code": 131047,  
					"title": "Re-engagement message",  
					"message": "Re-engagement message",  
					"error_data": {  
						"details": "Message failed to send because more than 24 hours have passed since the customer last replied to this number."  
					},  
					"href": "<https://developers.facebook.com/docs/whatsapp/cloud-api/support/error-codes/>"  
				}  
			]  
		}  
	]  
}

Envio de mensagem com sucesso (sent)

{  
  "messaging_product": "whatsapp",  
  "metadata": {  
    "display_phone_number": "<WABA-PHONE>",  
    "phone_number_id": "<WABA-PHONE-ID>"  
  },  
  "statuses": [  
    {  
      "id": "<WAMID>",  
      "status": "sent",  
      "timestamp": "1702587110",  
      "recipient_id": "<RECEIVER-WA-ID>",  
      "conversation": {  
        "id": "<CONVERSATION-ID>",  
        "expiration_timestamp": "1702669320",  
        "origin": {  
          "type": "marketing"  
        }  
      },  
      "pricing": {  
        "billable": true,  
        "pricing_model": "CBP",  
        "category": "marketing"  
      }  
    }  
  ]  
}

Entrega de mensagem (delivered)

{  
  "messaging_product": "whatsapp",  
  "metadata": {  
    "display_phone_number": "<WABA-PHONE>",  
    "phone_number_id": "<WABA-PHONE-ID>"  
  },  
  "statuses": [  
    {  
      "id": "<WAMID>",  
      "status": "delivered",  
      "timestamp": "1702587111",  
      "recipient_id": "<RECEIVER-WA-ID>",  
      "conversation": {  
        "id": "<CONVERSATION-ID>",  
        "origin": {  
          "type": "marketing"  
        }  
      },  
      "pricing": {  
        "billable": true,  
        "pricing_model": "CBP",  
        "category": "marketing"  
      }  
    }  
  ]  
}

Leitura de mensagem (read)

{  
  "messaging_product": "whatsapp",  
  "metadata": {  
    "display_phone_number": "<WABA-PHONE>",  
    "phone_number_id": "<WABA-PHONE-ID>"  
  },  
  "statuses": [  
    {  
      "id": "<WAMID>",  
      "status": "read",  
      "timestamp": "1702587111",  
      "recipient_id": "<RECEIVER-WA-ID>"  
    }  
  ]  
}

Mensagem de texto recebida - cliente enviando para loja

{  
  "messaging_product": "whatsapp",  
  "metadata": {  
    "display_phone_number": "<WABA-PHONE>",  
    "phone_number_id": "<WABA-PHONE-ID>"  
  },  
  "contacts": [  
    {  
      "profile": {  
        "name": "<RECEIVER-NAME>"  
      },  
      "wa_id": "<RECEIVER-WA-ID>"  
    }  
  ],  
  "messages": [  
    {  
      "from": "<RECEIVER-WA-ID>",  
      "id": "<WAMID>",  
      "timestamp": "1702641067",  
      "text": {  
        "body": "Olá! 👋"  
      },  
      "type": "text"  
    }  
  ]  
}

Reação à mensagem (reaction)

{  
  "messaging_product": "whatsapp",  
  "metadata": {  
    "display_phone_number": "<WABA-PHONE>",  
    "phone_number_id": "<WABA-PHONE-ID>"  
  },  
  "contacts": [  
    {  
      "profile": {  
        "name": "<RECEIVER-NAME>"  
      },  
      "wa_id": "<RECEIVER-WA-ID>"  
    }  
  ],  
  "messages": [  
    {  
      "from": "<PHONE>",  
      "id": "<WAMID-FROM-CONTEXT>",  
      "timestamp": "1702587705",  
      "type": "reaction",  
      "reaction": {  
        "message_id": "<WAMID>",  
        "emoji": "👍🏽"  
      }  
    }  
  ]  
}

Resposta à mensagem

{  
  "messaging_product": "whatsapp",  
  "metadata": {  
    "display_phone_number": "<WABA-PHONE>",  
    "phone_number_id": "<WABA-PHONE-ID>"  
  },  
  "contacts": [  
    {  
      "profile": {  
        "name": "<RECEIVER-NAME>"  
      },  
      "wa_id": "<RECEIVER-WA-ID>"  
    }  
  ],  
  "messages": [  
    {  
      "context": {  
        "from": "<PHONE>",  
        "id": "<WAMID-FROM-CONTEXT>"  
      },  
      "from": "<RECEIVER-WA-ID>",  
      "id": "<WAMID>",  
      "timestamp": "1702587836",  
      "text": {  
        "body": "Certo! Tudo bom 🙏"  
      },  
      "type": "text"  
    }  
  ]  
}

Resposta à mensagem interativa (button_reply)

{  
  "messaging_product": "whatsapp",  
  "metadata": {  
    "display_phone_number": "<WABA-PHONE>",  
    "phone_number_id": "<WABA-PHONE-ID>"  
  },  
  "contacts": [  
    {  
      "profile": {  
        "name": "<RECEIVER-NAME>"  
      },  
      "wa_id": "<RECEIVER-WA-ID>"  
    }  
  ],  
  "messages": [  
    {  
      "context": {  
        "from": "551135440417",  
        "id": "<WAMID-FROM-CONTEXT>"  
      },  
      "from": "<RECEIVER-WA-ID>",  
      "id": "<WAMID>",  
      "timestamp": "1702642905",  
      "type": "interactive",  
      "interactive": {  
        "type": "button_reply",  
        "button_reply": {  
          "id": "#SUBSCRIBE.",  
          "title": "Cadastrar"  
        }  
      }  
    }  
  ]  
}

Resposta à mensagem interativa (list_reply)

{  
  "messaging_product": "whatsapp",  
  "metadata": {  
    "display_phone_number": "<WABA-PHONE>",  
    "phone_number_id": "<WABA-PHONE-ID>"  
  },  
  "contacts": [  
    {  
      "profile": {  
        "name": "<RECEIVER-NAME>"  
      },  
      "wa_id": "<RECEIVER-WA-ID>"  
    }  
  ],  
  "messages": [  
    {  
      "context": {  
        "from": "<PHONE-FROM-CONTEXT>",  
        "id": "<WAMID-FROM-CONTEXT>"  
      },  
      "from": "<RECEIVER-WA-ID>",  
      "id": "<WAMID>",  
      "timestamp": "1702643231",  
      "type": "interactive",  
      "interactive": {  
        "type": "list_reply",  
        "list_reply": {  
          "id": "SECTION_1_ROW_1_ID",  
          "title": "SECTION_1_ROW_1_TITLE",  
          "description": "SECTION_1_ROW_1_DESCRIPTION"  
        }  
      }  
    }  
  ]  
}

message_template_status_update

Atualização de status do modelo de mensagem.

Modelo aprovado

{  
  "event": "APPROVED",  
  "message_template_id": 663263435974730,  
  "message_template_name": "modelo_carossel",  
  "message_template_language": "pt_BR",  
  "reason": "NONE"  
}

Modelo atualizado

Ao atualizar o modelo, ocorre um evento de message_template_status_update indicando o seu status.

{  
  "event": "APPROVED",  
  "message_template_id": <TEMPLATE-ID>,  
  "message_template_name": "modelo_carossel",  
  "message_template_language": "pt_BR",  
  "reason": "NONE"  
}

Modelo de mensagem com exclusão pendente

Ocorre quando há uma tentativa de excluir o modelo.

{  
  "event": "PENDING_DELETION",  
  "message_template_id": <TEMPLATE-ID>,  
  "message_template_name": "modelo_carossel",  
  "message_template_language": "pt_BR",  
  "reason": "NONE"  
}

Modelo rejeitado

{  
  "event": "REJECTED",  
  "message_template_id": <TEMPLATE-ID>,  
  "message_template_name": "beta_textwithparams_v1_2",  
  "message_template_language": "pt_BR",  
  "reason": "INCORRECT_CATEGORY"  
}

Observações

Nos testes exploratórios, a Meta não retornou webhook de atualização e exclusão para os templates do tipo authentication.

template_category_update

Atualização de nova categoria do template

{  
  "message_template_id": <TEMPLATE-ID>,  
  "message_template_name": "beta_textwithparams_v1_2",  
  "message_template_language": "pt_BR",  
  "previous_category": "UTILITY",  
  "new_category": "MARKETING"  
}