Sobre a função
O Hi Broker é o componente responsável por intermediar a comunicação entre a Hi Platform e a Meta (WhatsApp Business Platform). Ele processa disparos de mensagens, captura status de entrega e recebimento e encaminha eventos para os Webhooks configurados pelo cliente.
Com esse recurso, é possível acompanhar toda a jornada de mensagens enviadas e recebidas via WhatsApp, além de manter a rastreabilidade dos eventos e conteúdos trocados.
1. Visão Geral
A API pública do Hi Broker atua como camada de integração entre sistemas clientes e a WhatsApp Cloud API / Business Management API da Meta.
Em vez de cada integração gerenciar sua própria autenticação com a Meta, o Hi Broker centraliza:
- A autorização do tenant autenticado.
- O vínculo com a WhatsApp Business Account (WABA) e os números de telefone associados.
- A execução das chamadas contra a Meta, usando o contexto do tenant identificado.
Fluxo de uma chamada típica
Cliente → [Authorization Header] → Hi Broker (HsmBackend)
↓
Resolve TenantId
↓
wabaId (da rota) + TenantId
↓
Chama a Meta API com token gerenciado
↓
Retorna resposta ao cliente
2. Base URL e Swagger
URL Base
https://whatsapp-connect.hiplatform.com/hsmservices/api/public
Swagger (quando habilitado no ambiente)
| Recurso | URL |
|---|---|
| Interface interativa | https://whatsapp-connect.hiplatform.com/hsmservices/swagger |
| Documento OpenAPI JSON | https://whatsapp-connect.hiplatform.com/hsmservices/swagger/public-v1/swagger.json |
O documento Swagger público é registrado como public-v1 com o título Hi Broker API.
3. Autenticação
Todos os endpoints exigem autenticação. Dois esquemas são suportados:
3.1 Basic Authentication
Credenciais codificadas em Base64 no formato username:password.
Authorization: Basic dXN1YXJpbzpzZW5oYQ==
Geração do valor em linha de comando:
echo -n "usuario:senha" | base64
# dXN1YXJpbzpzZW5oYQ==
3.2 DT-Fenix-Token
Token proprietário da plataforma Hi, usado quando a autenticação é feita via sistema integrado.
Authorization: DT-Fenix-Token P01_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Importante: O backend usa o resultado da autenticação para identificar o
TenantId. OwabaIdinformado na rota é combinado com esse tenant para validar e executar as chamadas contra a Meta.
4. Convenções e Padrões
| Aspecto | Regra |
|---|---|
Content-Type (padrão) |
application/json |
Content-Type (uploads) |
multipart/form-data |
wabaId |
ID da WhatsApp Business Account (parâmetro de rota) |
phoneNumberId |
ID do número de telefone WhatsApp Business (parâmetro de rota) |
mediaId |
ID da mídia na Meta (parâmetro de rota) |
id |
ID de recurso genérico na Meta — template, número de telefone etc. |
| Listas | Seguem o formato Meta com data e paging quando aplicável |
| Campos e valores | Seguem as regras da Meta WhatsApp Cloud API |
5. Tratamento de Erros
Códigos HTTP
| Status | Descrição |
|---|---|
400 Bad Request |
Payload inválido, campo obrigatório ausente ou erro de regra da Meta. |
401 Unauthorized |
Credencial ausente ou inválida. |
403 Forbidden |
Credencial válida, mas sem permissão para o recurso solicitado. |
404 Not Found |
Recurso não encontrado ou não acessível para o tenant/WABA informados. |
5xx |
Erro interno ou indisponibilidade de dependência externa. |
Formato de erro (origem Meta)
Quando o erro vem da Meta, o corpo preserva o formato da integração:
{
"error": {
"message": "Invalid parameter",
"type": "OAuthException",
"code": 100
}
}
6. Paginação
Endpoints de listagem usam paginação por cursor.
Parâmetros de query
| Parâmetro | Descrição |
|---|---|
limit |
Quantidade máxima de itens por página. Padrão: 25. |
after |
Cursor para avançar para a próxima página. |
before |
Cursor para retroceder para a página anterior. |
Formato da resposta paginada
{
"data": [
{ "...": "..." }
],
"paging": {
"cursors": {
"before": "QVFIUjhFY...",
"after": "QVFIUjhFY..."
},
"next": "https://{host}/api/public/...",
"previous": "https://{host}/api/public/..."
}
}
Como navegar páginas
# Primeira página
GET /api/public/message_templates/{wabaId}?limit=10
# Próxima página (usando cursor "after" retornado)
GET /api/public/message_templates/{wabaId}?limit=10&after=QVFIUjhFY...
7. Referência de Endpoints
7.1 WABAs
Buscar WABA por ID
Retorna dados básicos de uma WhatsApp Business Account.
GET /api/public/wabas/{wabaId}
Parâmetros de rota:
| Parâmetro | Obrigatório | Descrição |
|---|---|---|
wabaId |
Sim | ID da WABA. |
Exemplo de requisição:
curl -X GET "https://{host}/api/public/wabas/123455667710" \
-H "Authorization: Basic {credentials}"
Resposta 200:
{
"id": "123455667710",
"name": "Minha Empresa LTDA",
"marketing_messages_lite_api_status": "ONBOARDED",
"currency": "BRL"
}
7.2 Números de Telefone
Listar números de telefone
Retorna os números comerciais associados à WABA.
GET /api/public/phone_numbers/{wabaId}?limit=25&after={cursor}&before={cursor}
Exemplo de requisição:
curl -X GET "https://{host}/api/public/phone_numbers/123455667710?limit=10" \
-H "Authorization: Basic {credentials}"
Resposta 200:
{
"data": [
{
"id": "105981245678901",
"display_phone_number": "+55 11 99999-9999",
"verified_name": "Minha Empresa LTDA",
"quality_rating": "GREEN",
"status": "CONNECTED",
"code_verification_status": "VERIFIED",
"name_status": "APPROVED"
}
],
"paging": {
"cursors": {
"before": "QVFIUjhFY...",
"after": "QVFIUjhFY..."
}
}
}
Buscar número por ID
GET /api/public/phone_numbers/{wabaId}/{id}
Exemplo de requisição:
curl -X GET "https://{host}/api/public/phone_numbers/123455667710/105981245678901" \
-H "Authorization: Basic {credentials}"
Resposta 200:
{
"id": "105981245678901",
"display_phone_number": "+55 11 99999-9999",
"verified_name": "Minha Empresa LTDA",
"quality_rating": "GREEN",
"status": "CONNECTED",
"code_verification_status": "VERIFIED",
"name_status": "APPROVED"
}
Atualizar nome de exibição
Atualiza o nome de exibição do número comercial. O nome está sujeito à aprovação da Meta.
POST /api/public/phone_numbers/{wabaId}/{phoneNumberId}/display_name
Payload:
{
"name": "Minha Empresa Oficial"
}
Exemplo de requisição:
curl -X POST "https://{host}/api/public/phone_numbers/123455667710/105981245678901/display_name" \
-H "Authorization: Basic {credentials}" \
-H "Content-Type: application/json" \
-d '{"name": "Minha Empresa Oficial"}'
Resposta 200:
{
"success": true
}
7.3 Perfis Comerciais
Buscar perfil comercial
GET /api/public/business_profiles/{wabaId}/{phoneNumberId}?fields={campos}
O parâmetro fields é opcional. Valores aceitos separados por vírgula: about, address, description, email, profile_picture_url, websites, vertical.
Exemplo — buscar todos os campos:
curl -X GET "https://{host}/api/public/business_profiles/123455667710/105981245678901?fields=about,address,description,email,profile_picture_url,websites,vertical" \
-H "Authorization: Basic {credentials}"
Resposta 200:
{
"data": [
{
"about": "Atendimento todos os dias das 8h às 20h",
"address": "Av. Paulista, 1000 - Bela Vista, São Paulo/SP, 01310-100",
"description": "Canal oficial de atendimento, vendas e suporte da empresa.",
"email": "contato@empresa.com",
"profile_picture_url": "https://lookaside.fbsbx.com/whatsapp_business_profile_photo.jpg",
"websites": [
"https://www.empresa.com",
"https://instagram.com/empresa"
],
"vertical": "PROF_SERVICES",
"messaging_product": "whatsapp"
}
]
}
Atualizar perfil comercial
POST /api/public/business_profiles/{wabaId}/{phoneNumberId}
Para atualizar a foto de perfil, primeiro faça upload via Uploads Resumíveis e use o
handleretornado no campoprofile_picture_handle.
Payload completo:
{
"about": "Atendimento todos os dias das 8h às 20h",
"address": "Av. Paulista, 1000 - Bela Vista, São Paulo/SP, 01310-100",
"description": "Canal oficial de atendimento, vendas e suporte da empresa.",
"email": "contato@empresa.com",
"profile_picture_handle": "4::aW1hZ2UvanBlZw==::ARaExampleHandle",
"vertical": "PROF_SERVICES",
"websites": [
"https://www.empresa.com",
"https://instagram.com/empresa"
]
}
Valores aceitos para vertical: UNDEFINED, OTHER, AUTO, BEAUTY, APPAREL, EDU, ENTERTAIN, EVENT_PLAN, FINANCE, GROCERY, GOVT, HOTEL, HEALTH, NONPROFIT, PROF_SERVICES, RETAIL, TRAVEL, RESTAURANT, NOT_A_BIZ.
Resposta 200:
{
"success": true
}
7.4 Mensagens
Enviar mensagem
Envia uma mensagem pelo número comercial informado.
POST /api/public/messages/{wabaId}/{phoneNumberId}
Campos comuns a todos os tipos:
| Campo | Obrigatório | Descrição |
|---|---|---|
messaging_product |
Sim | Sempre "whatsapp". |
recipient_type |
Não | Tipo do destinatário. Valor padrão: "individual". |
to |
Sim | Número do destinatário no formato E.164 (ex.: "5511999999999"). |
type |
Sim | Tipo da mensagem. Veja tabela abaixo. |
context |
Não | Objeto com message_id para responder a uma mensagem anterior. |
Tipos de mensagem suportados:
type |
Descrição |
|---|---|
text |
Texto simples |
template |
Template de mensagem pré-aprovado |
image |
Imagem (URL ou media_id) |
document |
Documento (URL ou media_id) |
video |
Vídeo (URL ou media_id) |
audio |
Áudio (URL ou media_id) |
sticker |
Figurinha |
contacts |
Cartão de contato |
reaction |
Reação com emoji |
interactive |
Mensagem interativa com botões ou lista |
location |
Localização geográfica |
Payload: Mensagem de texto
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "text",
"text": {
"body": "Olá! Seu pedido #12345 foi confirmado.",
"preview_url": false
}
}
Payload: Mensagem de imagem por URL
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "image",
"image": {
"link": "https://www.empresa.com/imagens/banner-promocao.jpg",
"caption": "Confira nossa promoção de verão! 🌞"
}
}
Payload: Mensagem de imagem por media_id
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "image",
"image": {
"id": "4490709327384033",
"caption": "Seu comprovante de pagamento."
}
}
Payload: Mensagem de documento
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "document",
"document": {
"link": "https://www.empresa.com/docs/contrato.pdf",
"filename": "Contrato_Servico.pdf",
"caption": "Segue seu contrato para assinatura."
}
}
Payload: Mensagem de áudio
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "audio",
"audio": {
"link": "https://www.empresa.com/audios/instrucoes.ogg"
}
}
Payload: Mensagem de vídeo
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "video",
"video": {
"link": "https://www.empresa.com/videos/tutorial.mp4",
"caption": "Veja como usar nosso aplicativo."
}
}
Payload: Reação a mensagem
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "reaction",
"reaction": {
"message_id": "wamid.HBgMNTUxMTk5OTk5OTk5FQIAERgSMkY4QTY4Q0I0QzQxRUI0AA==",
"emoji": "👍"
}
}
Payload: Localização
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "location",
"location": {
"longitude": -46.6333,
"latitude": -23.5505,
"name": "Av. Paulista, 1000",
"address": "Av. Paulista, 1000 - Bela Vista, São Paulo - SP, 01310-100"
}
}
Payload: Mensagem interativa — Botões
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "interactive",
"interactive": {
"type": "button",
"body": {
"text": "Você gostaria de confirmar seu agendamento para amanhã às 14h?"
},
"action": {
"buttons": [
{
"type": "reply",
"reply": {
"id": "confirm_yes",
"title": "✅ Confirmar"
}
},
{
"type": "reply",
"reply": {
"id": "confirm_no",
"title": "❌ Cancelar"
}
}
]
}
}
}
Payload: Mensagem interativa — Lista
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "interactive",
"interactive": {
"type": "list",
"header": {
"type": "text",
"text": "Escolha um departamento"
},
"body": {
"text": "Selecione o setor com o qual deseja falar:"
},
"footer": {
"text": "Horário de atendimento: 8h às 20h"
},
"action": {
"button": "Ver opções",
"sections": [
{
"title": "Atendimento",
"rows": [
{
"id": "dept_suporte",
"title": "Suporte técnico",
"description": "Problemas com produtos ou serviços"
},
{
"id": "dept_financeiro",
"title": "Financeiro",
"description": "Cobranças, faturas e pagamentos"
}
]
},
{
"title": "Vendas",
"rows": [
{
"id": "dept_comercial",
"title": "Comercial",
"description": "Novos contratos e propostas"
}
]
}
]
}
}
}
Payload: Mensagem de template
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "template",
"template": {
"name": "reserva_confirmada",
"language": {
"code": "pt_BR"
},
"components": [
{
"type": "body",
"parameters": [
{
"type": "text",
"text": "Maria Silva"
},
{
"type": "text",
"text": "15/07/2025 às 14h00"
}
]
}
]
}
}
Payload: Resposta a uma mensagem (contexto)
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "text",
"context": {
"message_id": "wamid.HBgMNTUxMTk5OTk5OTk5FQIAERgSMkY4QTY4Q0I0QzQxRUI0AA=="
},
"text": {
"body": "Claro! Posso te ajudar com isso.",
"preview_url": false
}
}
Resposta 200 (todos os tipos de mensagem):
{
"messaging_product": "whatsapp",
"contacts": [
{
"input": "5511999999999",
"wa_id": "5511999999999"
}
],
"messages": [
{
"id": "wamid.HBgMNTUxMTk5OTk5OTk5FQIAERgSMkY4QTY4Q0I0QzQxRUI0AA==",
"message_status": "accepted"
}
]
}
7.5 Mensagens de Marketing
Envia mensagens de template com foco em marketing. O endpoint segue o mesmo padrão de mensagens, mas é específico para campanhas.
POST /api/public/marketing_messages/{wabaId}/{phoneNumberId}
Payload:
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "template",
"template": {
"name": "campanha_verao_2025",
"language": {
"code": "pt_BR"
},
"components": [
{
"type": "header",
"parameters": [
{
"type": "image",
"image": {
"id": "4490709327384033"
}
}
]
},
{
"type": "body",
"parameters": [
{
"type": "text",
"parameter_name": "first_name",
"text": "Jessica"
},
{
"type": "text",
"parameter_name": "order_number",
"text": "SKBUP2-4CPIG9"
}
]
}
]
}
}
A resposta 200 segue o mesmo formato do endpoint de envio de mensagens.
7.6 Mídias
Enviar mídia (upload)
Faz upload de um arquivo de mídia para a Meta. O id retornado pode ser usado em envios de mensagens com mídia.
POST /api/public/media/{wabaId}/{phoneNumberId}
Content-Type: multipart/form-data
| Campo | Obrigatório | Descrição |
|---|---|---|
file |
Sim | Arquivo binário (imagem, vídeo, documento, áudio). |
Exemplo com curl:
curl -X POST "https://{host}/api/public/media/123455667710/105981245678901" \
-H "Authorization: Basic {credentials}" \
-F "file=@./banner-promocao.jpg"
Resposta 200:
{
"id": "4490709327384033"
}
Use o
idretornado no campoimage.id,document.id,video.idouaudio.idao enviar mensagens.
Buscar informações de mídia
GET /api/public/media/{wabaId}/{phoneNumberId}/{mediaId}
Exemplo:
curl -X GET "https://{host}/api/public/media/123455667710/105981245678901/4490709327384033" \
-H "Authorization: Basic {credentials}"
Resposta 200:
{
"id": "4490709327384033",
"url": "https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=4490709327384033",
"mime_type": "image/jpeg",
"sha256": "e3b0c44298fc1c149afbf4c8996fb924",
"file_size": 245612,
"messaging_product": "whatsapp"
}
Excluir mídia
DELETE /api/public/media/{wabaId}/{phoneNumberId}/{mediaId}
Exemplo:
curl -X DELETE "https://{host}/api/public/media/123455667710/105981245678901/4490709327384033" \
-H "Authorization: Basic {credentials}"
Resposta 200:
{
"success": true
}
7.7 Uploads Resumíveis
Cria uma sessão de upload na Meta e envia o arquivo. O handle retornado é necessário para operações que exigem referência a mídia, como a atualização de foto de perfil.
POST /api/public/uploads/{wabaId}/{phoneNumberId}
Content-Type: multipart/form-data
| Campo | Obrigatório | Descrição |
|---|---|---|
file |
Sim | Arquivo binário. |
Exemplo:
curl -X POST "https://{host}/api/public/uploads/123455667710/105981245678901" \
-H "Authorization: Basic {credentials}" \
-F "file=@./foto-perfil.jpg"
Resposta 200:
{
"h": "4::aW1hZ2UvanBlZw==::ARaExampleHandle"
}
Use o valor de
hno campoprofile_picture_handleao atualizar o perfil comercial, ou emheader_handleao criar templates com header de imagem, vídeo ou documento.
7.8 Templates de Mensagem
Listar templates
GET /api/public/message_templates/{wabaId}?name={name}&language={language}&status={status}&category={category}&limit=25&after={cursor}&before={cursor}
Filtros disponíveis:
| Parâmetro | Descrição | Exemplo |
|---|---|---|
name |
Nome do template | reserva_confirmada |
language |
Idioma | pt_BR, en_US |
status |
Status de aprovação | APPROVED, PENDING, REJECTED |
category |
Categoria | UTILITY, MARKETING, AUTHENTICATION |
limit |
Itens por página | 10 |
after / before |
Cursor de paginação | — |
Exemplo:
curl -X GET "https://{host}/api/public/message_templates/123455667710?status=APPROVED&category=UTILITY&limit=10" \
-H "Authorization: Basic {credentials}"
Resposta 200:
{
"data": [
{
"id": "1387372356726668",
"name": "reserva_confirmada",
"language": "pt_BR",
"status": "APPROVED",
"category": "UTILITY",
"parameter_format": "NAMED",
"components": [
{
"type": "BODY",
"text": "Sua reserva para {{number_of_guests}} pessoas está confirmada para {{date}} às {{time}}."
}
]
}
],
"paging": {
"cursors": {
"before": "QVFIU...",
"after": "QVFIU..."
}
}
}
Buscar template por ID
GET /api/public/message_templates/{wabaId}/{id}
Resposta 200:
{
"id": "1387372356726668",
"name": "reserva_confirmada",
"language": "pt_BR",
"status": "APPROVED",
"category": "UTILITY",
"parameter_format": "NAMED",
"components": [
{
"type": "BODY",
"text": "Sua reserva para {{number_of_guests}} pessoas está confirmada para {{date}} às {{time}}."
}
]
}
Criar template
POST /api/public/message_templates/{wabaId}
Resposta 200:
{
"id": "1387372356726668",
"status": "PENDING",
"category": "UTILITY"
}
Templates ficam com status PENDING até a análise da Meta. Após aprovação, o status passa para APPROVED.
Variações de payload — Criação de template
Template com parâmetros posicionais (texto)
Parâmetros no formato {{1}}, {{2}} etc. Use parameter_format: "POSITIONAL".
{
"name": "lembrete_cupom_expirar",
"parameter_format": "POSITIONAL",
"language": "pt_BR",
"category": "MARKETING",
"components": [
{
"type": "HEADER",
"format": "TEXT",
"text": "Corra, {{1}}!",
"example": {
"header_text": ["Ana"]
}
},
{
"type": "BODY",
"text": "Seu cupom {{1}} expira em {{2}} dias. Não perca!",
"example": {
"body_text": [["VERAO20", "3"]]
}
},
{
"type": "FOOTER",
"text": "Minha Empresa LTDA"
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "URL",
"text": "Ver ofertas",
"url": "https://www.empresa.com/ofertas"
},
{
"type": "QUICK_REPLY",
"text": "Não tenho interesse"
}
]
}
]
}
Template com parâmetros nomeados
Use parameter_format: "NAMED" com placeholders como {{customer_name}}.
{
"name": "confirmacao_reserva_nomeada",
"parameter_format": "NAMED",
"language": "pt_BR",
"category": "UTILITY",
"components": [
{
"type": "HEADER",
"format": "TEXT",
"text": "Reserva confirmada para {{customer_name}}",
"example": {
"header_text_named_params": [
{ "param_name": "customer_name", "example": "Carlos Souza" }
]
}
},
{
"type": "BODY",
"text": "Sua mesa para {{number_of_guests}} pessoas está reservada para {{date}} às {{time}}.",
"example": {
"body_text_named_params": [
{ "param_name": "number_of_guests", "example": "4" },
{ "param_name": "date", "example": "20 de julho de 2025" },
{ "param_name": "time", "example": "19h30" }
]
}
}
]
}
Template com header de imagem
Necessita de um header_handle gerado pelo endpoint de Uploads Resumíveis.
{
"name": "nova_campanha_imagem",
"parameter_format": "POSITIONAL",
"language": "pt_BR",
"category": "MARKETING",
"components": [
{
"type": "HEADER",
"format": "IMAGE",
"example": {
"header_handle": ["4::aW1hZ2UvanBlZw==::ARaExampleHandle"]
}
},
{
"type": "BODY",
"text": "Olá, {{1}}! Confira nossa nova campanha de verão.",
"example": {
"body_text": [["Ana"]]
}
}
]
}
Template com header de vídeo
{
"name": "novidades_semana_video",
"parameter_format": "POSITIONAL",
"language": "pt_BR",
"category": "MARKETING",
"components": [
{
"type": "HEADER",
"format": "VIDEO",
"example": {
"header_handle": ["4::dmlkZW8vbXA0::ARaExampleHandle"]
}
},
{
"type": "BODY",
"text": "Assista ao vídeo com as novidades desta semana."
}
]
}
Template com header de documento
{
"name": "documento_disponivel",
"parameter_format": "POSITIONAL",
"language": "pt_BR",
"category": "UTILITY",
"components": [
{
"type": "HEADER",
"format": "DOCUMENT",
"example": {
"header_handle": ["4::YXBwbGljYXRpb24vcGRm::ARaExampleHandle"]
}
},
{
"type": "BODY",
"text": "Seu documento está disponível para consulta."
}
]
}
Template com header de localização
{
"name": "localizacao_atendimento",
"parameter_format": "POSITIONAL",
"language": "pt_BR",
"category": "UTILITY",
"components": [
{
"type": "HEADER",
"format": "LOCATION"
},
{
"type": "BODY",
"text": "Use a localização abaixo para chegar ao nosso endereço de atendimento."
}
]
}
Template com URL dinâmica
Use {{1}} na URL para parte do link ser preenchida no momento do envio.
{
"name": "oferta_exclusiva_url_dinamica",
"parameter_format": "POSITIONAL",
"language": "pt_BR",
"category": "MARKETING",
"components": [
{
"type": "BODY",
"text": "Acesse sua oferta exclusiva personalizada."
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "URL",
"text": "Ver minha oferta",
"url": "https://www.empresa.com/ofertas/{{1}}",
"example": ["cliente-98765"]
}
]
}
]
}
Template com botão de telefone
{
"name": "contato_suporte_telefone",
"parameter_format": "POSITIONAL",
"language": "pt_BR",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "Precisa de ajuda? Nossa equipe está disponível para atender você."
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "PHONE_NUMBER",
"text": "Ligar agora",
"phone_number": "+5511999999999"
}
]
}
]
}
Template com botão de copiar código
{
"name": "cupom_desconto_copiar",
"parameter_format": "POSITIONAL",
"language": "pt_BR",
"category": "MARKETING",
"components": [
{
"type": "BODY",
"text": "Use o cupom abaixo para concluir sua compra com 20% de desconto."
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "COPY_CODE",
"text": "Copiar cupom"
}
]
}
]
}
Template com botão de detalhes do pedido
Requer que o fluxo de comércio da Meta esteja habilitado para a conta.
{
"name": "atualizacao_pedido",
"parameter_format": "POSITIONAL",
"language": "pt_BR",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "Seu pedido foi atualizado. Toque no botão abaixo para ver os detalhes."
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "ORDER_DETAILS",
"text": "Ver pedido"
}
]
}
]
}
Template de autenticação com botão OTP de copiar código
{
"name": "auth_login_otp_copycode_hmg_v1",
"language": "pt_BR",
"category": "AUTHENTICATION",
"components": [
{
"type": "BODY",
"add_security_recommendation": true,
"code_expiration_minutes": 5
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "OTP",
"otp_type" : "COPY_CODE",
"text": "Copiar código"
}
]
}
]
}
Template de autenticação com botão de OTP preenchimento automático com toque
{
"name": "authentication_code_autofill_buttonpt12",
"language": "pt_BR",
"category": "AUTHENTICATION",
"components": [
{
"type": "BODY",
"add_security_recommendation": true
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "OTP",
"otp_type" : "ONE_TAP",
"text": "Copy Code",
"autofill_text": "Autofill",
"package_name": "com.example.luckyshrub",
"signature_hash": "K8a/AINcGX7",
"supported_apps": [
{
"package_name": "com.example.luckyshrub",
"signature_hash": "K8a/AINcGX7"
}
]
}
]
}
]
}
Template de autenticação com botão OTP de preenchimento automático sem toque
{
"name": "zero_tap_auth_hmg_v1",
"language": "pt_BR",
"category": "AUTHENTICATION",
"message_send_ttl_seconds": 60,
"components": [
{
"type": "BODY",
"add_security_recommendation": true
},
{
"type": "FOOTER",
"code_expiration_minutes": 5,
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "OTP",
"otp_type" : "NO_TAP",
"text": "Copy Code",
"autofill_text": "Autofill",
"zero_tap_terms_accepted": true,
"supported_apps": [
{
"package_name": "com.example.luckyshrub",
"signature_hash": "K8a/AINcGX7"
}
]
}
]
}
]
}
Atualizar template
Permite atualizar os componentes de um template existente.
PATCH /api/public/message_templates/{wabaId}/{id}
Payload:
{
"components": [
{
"type": "HEADER",
"format": "TEXT",
"text": "Nossa {{1}} começou!",
"example": {
"header_text": ["Liquidação de Inverno"]
}
},
{
"type": "BODY",
"text": "Compre até {{1}} e use o código {{2}} para obter {{3}} de desconto.",
"example": {
"body_text": [
["31 de julho", "INVERNO30", "30%"]
]
}
}
]
}
Resposta 200:
{
"success": true
}
Excluir template por nome
DELETE /api/public/message_templates/{wabaId}?name={name}
Exemplo:
curl -X DELETE "https://{host}/api/public/message_templates/123455667710?name=lembrete_cupom_expirar" \
-H "Authorization: Basic {credentials}"
Resposta 200:
{
"success": true
}
Excluir template por ID
DELETE /api/public/message_templates/{wabaId}/{id}?name={name}
O parâmetro
nameé obrigatório na query string mesmo ao deletar por ID, pois a Meta pode ter múltiplos templates com o mesmo nome em idiomas distintos.
Exemplo:
curl -X DELETE "https://{host}/api/public/message_templates/123455667710/1387372356726668?name=lembrete_cupom_expirar" \
-H "Authorization: Basic {credentials}"
Resposta 200:
{
"success": true
}
7.9 Migração de Templates
Migra templates de uma WABA de origem para a WABA de destino informada na rota. Útil em cenários de consolidação de contas ou reestruturação de WABAs.
POST /api/public/migrate_message_templates/{wabaId}
Payload:
{
"source_waba_id": "102290129340398",
"page_number": 0,
"count": 2,
"template_ids": [
"1473688840035974",
"6162904357082268"
]
}
| Campo | Obrigatório | Descrição |
|---|---|---|
source_waba_id |
Sim | ID da WABA de origem dos templates. |
page_number |
Não | Página dos templates a migrar (paginação). |
count |
Não | Quantidade de templates a migrar por chamada. |
template_ids |
Não | Lista de IDs específicos a migrar. Se omitido, migra todos. |
Resposta 200:
{
"migrated_templates": [
"1473688840035974",
"6162904357082268"
],
"failed_templates": {
"572279198452421": "Incorrect category"
}
}
7.10 Usernames
Adicionar username
Solicita um username para o número de telefone comercial.
POST /api/public/usernames/{wabaId}/{phoneNumberId}
Payload:
{
"username": "minhaempresa.oficial"
}
Resposta 200:
{
"status": "approved"
}
Buscar sugestões de username
Retorna sugestões disponíveis com base no número informado.
POST /api/public/usernames/{wabaId}/{phoneNumberId}/suggestions
Este endpoint não requer body.
Resposta 200:
{
"data": [
{
"reserved_username": [
"minhaempresa.oficial",
"minhaempresa.br",
"minhaempresa.suporte"
]
}
]
}
Excluir username
DELETE /api/public/usernames/{wabaId}/{phoneNumberId}
Resposta 200:
true
8. Exemplos de Integração Completa
Fluxo 1: Enviar mensagem de texto simples
curl -X POST "https://{host}/api/public/messages/123455667710/105981245678901" \
-H "Authorization: Basic {credentials}" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "text",
"text": {
"body": "Olá! Esta é uma mensagem enviada pelo Hi Broker.",
"preview_url": false
}
}'
Fluxo 2: Upload de mídia e envio como imagem
Passo 1 — Upload do arquivo:
curl -X POST "https://{host}/api/public/media/123455667710/105981245678901" \
-H "Authorization: Basic {credentials}" \
-F "file=@./banner.jpg"
# Retorna: {"id": "4490709327384033"}
Passo 2 — Envio da mensagem com a mídia:
curl -X POST "https://{host}/api/public/messages/123455667710/105981245678901" \
-H "Authorization: Basic {credentials}" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "image",
"image": {
"id": "4490709327384033",
"caption": "Confira nossa promoção!"
}
}'
Fluxo 3: Criar template e usar em envio
Passo 1 — Criar template:
curl -X POST "https://{host}/api/public/message_templates/123455667710" \
-H "Authorization: Basic {credentials}" \
-H "Content-Type: application/json" \
-d '{
"name": "boas_vindas_cliente",
"parameter_format": "NAMED",
"language": "pt_BR",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "Olá, {{customer_name}}! Seja bem-vindo(a) à Minha Empresa. Seu código de cliente é {{customer_code}}.",
"example": {
"body_text_named_params": [
{ "param_name": "customer_name", "example": "Carlos" },
{ "param_name": "customer_code", "example": "CLI-001" }
]
}
}
]
}'
# Retorna: {"id": "9988776655443322", "status": "PENDING", "category": "UTILITY"}
Passo 2 — Aguardar aprovação (status APPROVED) e enviar:
curl -X POST "https://{host}/api/public/messages/123455667710/105981245678901" \
-H "Authorization: Basic {credentials}" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "template",
"template": {
"name": "boas_vindas_cliente",
"language": { "code": "pt_BR" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "parameter_name": "customer_name", "text": "Carlos" },
{ "type": "text", "parameter_name": "customer_code", "text": "CLI-001" }
]
}
]
}
}'
Fluxo 4: Upload resumível + atualização de foto de perfil
Passo 1 — Upload resumível:
curl -X POST "https://{host}/api/public/uploads/123455667710/105981245678901" \
-H "Authorization: Basic {credentials}" \
-F "file=@./logo-empresa.jpg"
# Retorna: {"h": "4::aW1hZ2UvanBlZw==::ARaExampleHandle"}
Passo 2 — Atualizar perfil:
curl -X POST "https://{host}/api/public/business_profiles/123455667710/105981245678901" \
-H "Authorization: Basic {credentials}" \
-H "Content-Type: application/json" \
-d '{
"about": "Atendimento de segunda a sábado, das 8h às 18h.",
"profile_picture_handle": "4::aW1hZ2UvanBlZw==::ARaExampleHandle"
}'
9. Referências Meta
| Recurso | Link |
|---|---|
| WhatsApp Cloud API — Messages | https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages/ |
| WhatsApp Cloud API — Media | https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media/ |
| Business Management API — Message Templates | https://developers.facebook.com/docs/whatsapp/business-management-api/message-templates/ |
| WhatsApp Business Profiles | https://developers.facebook.com/docs/whatsapp/cloud-api/reference/business-profiles/ |
10. Webhooks
Este recurso foi desenvolvido para receber, processar e encaminhar ao Webhook do cliente as mensagens recebidas da Meta (WhatsApp Business Platform), enviadas por usuários finais para o número de WhatsApp integrado.
Sempre que um cliente final envia uma mensagem pelo WhatsApp, a Meta repassa esse conteúdo para nosso sistema. Nós tratamos os dados recebidos e encaminhamos o evento para o Webhook configurado pelo cliente.
Formato enviado ao Webhook
Sempre que ocorrer um evento, seu endpoint de Webhook receberá um JSON com a seguinte estrutura:
{
"id":"7e5f5c77-3e65-4d53-9f8b-123456789abc",
"tenantId":"11111111-2222-3333-4444-555555555555",
"departmentId":"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"destinationDepartmentId":"bbbbbbbb-cccc-dddd-eeee-ffffffffffff",
"senderId":"5511999999999",
"consumerId":"5511888888888",
"consumerName":"João da Silva",
"accountId":"99999999-8888-7777-6666-555555555555",
"orderGaranteeFlag":true,
"payload":{
"/* Ver formatos possíveis em Formatos de Payload */"
},
"repliedMessageId":"abcd1234efgh5678",
"brokerTypeOrigin":"Meta",
"customerIdentificationProperties":[
{
"name":"cpf",
"value":"12345678900"
},
{
"name":"email",
"value":"joao.silva@exemplo.com"
}
],
"customProperties":[
{
"name":"canal",
"value":"whatsapp"
}
],
"adProperties":[
{
"name":"campaignId",
"value":"cmp_001"
}
]
}
Estrutura do Payload
| Campo | Tipo | Descrição |
|---|---|---|
id |
GUID | Identificador único da mensagem. |
tenantId |
GUID | Identificador do site/tenant. |
departmentId |
GUID | Departamento que recebeu a mensagem. |
destinationDepartmentId |
GUID | Departamento de destino, se houver roteamento. |
senderId |
string | Identificador do remetente no contexto do canal. |
consumerId |
string | Identificador do consumidor/usuário final. |
consumerName |
string | Nome do consumidor, quando disponível. |
accountId |
GUID | Conta associada ao atendimento. |
orderGaranteeFlag |
boolean | Indica se a resposta garantirá ordenação. |
payload |
Object | Conteúdo da mensagem. Um dos formatos listados na seção “Formatos de Payload". |
brokerTypeOrigin |
string/enum | Origem/broker do evento (ex.: Meta) |
customerIdentificationProperties |
Object List | Propriedades de identificação do usuário (chave/valor) |
customProperties |
Object List | Propriedades adicionais associadas ao cliente. |
adProperties |
Object List | Propriedades relacionadas a anúncios/campanhas de origem. |
Formatos de Payload
O campo payload no JSON enviado pelo Webhook pode variar conforme o tipo de conteúdo. Abaixo estão os formatos possíveis e suas regras:
Texto
| Campo | Tipo |
|---|---|
body |
string |
previewFirstUrl |
boolean |
identifier |
string |
data |
string |
Imagem
| Campo | Tipo |
|---|---|
imageType |
string |
url |
string |
caption |
string |
contentType |
string |
Áudio
| Campo | Tipo |
|---|---|
audioType |
string |
url |
string |
contentType |
string |
Vídeo
| Campo | Tipo |
|---|---|
videoType |
string |
url |
string |
caption |
string |
contentType |
string |
Documento
| Campo | Tipo |
|---|---|
documentType |
string |
url |
string |
caption |
string |
filename |
string |
contentType |
string |