whatsapp-bsp / api / v1 / docs
Voltar ao Dashboard

Documentação da API

Bem-vindo à API CoverCut. Nossa API permite integrar o WhatsApp Business Cloud diretamente no seu sistema.

Requisitos no Facebook

Antes de conectar à API oficial do WhatsApp (Meta), é necessário completar algumas configurações na sua conta do Facebook Business. Siga os passos abaixo na ordem indicada.

Passo 1 — Verificação da Empresa

Acesse a Central de Segurança do Business Manager e inicie o processo de verificação da sua empresa. Isso é fundamental para aumentar seus limites de envio de mensagens.

1
Inicie a Verificação na Central de Segurança

Clique no link abaixo para acessar a Central de Segurança da sua conta.

business.facebook.com/latest/settings/security_center

Passo 2 — Preencher Dados da Empresa

Acesse as configurações do Business Manager e preencha as informações da sua empresa. Isso é obrigatório para a Meta liberar o envio de mensagens em escala.

2
Acesse o link abaixo e preencha todos os campos solicitados

Razão social, CNPJ, endereço e telefone comercial.

business.facebook.com/latest/settings/business_info
Conta Pessoal (sem CNPJ)
Se você não possui empresa registrada, preencha o seu nome completo no campo "Razão social da empresa". Os demais campos podem ser preenchidos com seus dados pessoais normalmente.

Passo 3 — Cadastrar Cartão de Crédito

O envio de templates (mensagens ativas) é cobrado diretamente pela Meta. Para habilitar o envio, é necessário cadastrar um método de pagamento na sua conta Business.

3
Acesse o Hub de Faturamento

Clique no link abaixo para ir direto para a página de pagamentos.

business.facebook.com/latest/billing_hub/accounts
2
Selecione "Contas do WhatsApp Business"

Na tela de faturamento, localize e clique na opção Contas do WhatsApp Business para adicionar seu cartão de crédito vinculado especificamente ao número do WhatsApp que será utilizado na API.

Importante: Sem cartão cadastrado, o envio de templates de marketing e utilidade ficará bloqueado pela Meta. Mensagens dentro da janela de 24h (respostas) não são cobradas.

Custos de Envio de Templates

A Meta cobra por conversa iniciada via template, e não por mensagem individual. Os preços variam de acordo com a categoria do template:

Marketing
$0,06
por conversa iniciada
Templates promocionais, ofertas, campanhas
Utilidade
$0,006
por conversa iniciada
Confirmações, lembretes, notificações transacionais
Dica: Prefira templates de Utilidade para notificações automáticas (agendamentos, cobranças, confirmações). Além de custar 10x menos, eles têm taxas de entrega mais altas pois não são filtrados como spam.

Janelas de Conversa

A Meta trabalha com o conceito de janela de conversa: um período em que você pode trocar mensagens livremente sem custo adicional após o template inicial ter sido enviado.

24h
Conversa Padrão

Quando um cliente envia uma mensagem para o seu número, uma janela de 24 horas é aberta. Durante esse período, você pode responder livremente com qualquer tipo de mensagem, sem custo de template.

72h
Lead de Anúncios (Click-to-WhatsApp)

Quando o lead chega ao WhatsApp a partir de um anúncio Click-to-WhatsApp do Facebook/Instagram, a janela de conversa é ampliada para 72 horas, permitindo mais tempo para o atendimento sem custo adicional.

Fora da janela: Se a janela expirar e você precisar retomar o contato, será necessário enviar um template (marketing ou utilidade) para reabrir a conversa, e o custo correspondente será cobrado.

Nome de Exibição (Display Name)

Quando sua empresa utiliza a API Oficial do WhatsApp Business (Meta) para falar com clientes, o nome que aparece no perfil é o seu Nome de Exibição (ou Display Name). Ele funciona como a identidade e o cartão de visitas da sua empresa no aplicativo.

Ter um nome aprovado é essencial para transmitir confiança, ajudar no reconhecimento imediato da marca e, futuramente, para a obtenção do selo verde de Conta Comercial Oficial (OBA).

1. Diretrizes de Aprovação da Meta

A Meta possui regras estritas para a aprovação do Nome de Exibição. Ele deve refletir de forma consistente a sua marca externa e seguir as regras de formatação abaixo:

Regras de Formatação e Escrita

  • Tamanho Mínimo: O nome deve conter no mínimo 3 caracteres.
  • Gramática e Capitalização: Use maiúsculas e minúsculas corretamente (ex: Padaria Delícia). Não utilize todo o texto em caixa alta (ALL CAPS) (ex: PADARIA DELÍCIA), a menos que a sua marca seja registrada ou conhecida dessa forma (ex: IKEA, BMW).
  • Espaçamento: Não insira espaços extras entre as letras (ex: P a d a r i a será rejeitado).
  • Caracteres Especiais: Emojis, símbolos de marca registrada (como ®, ™), caracteres especiais desnecessários ou pontuação excessiva são estritamente proibidos (ex: Padaria Delícia! ✨).

Regras de Conteúdo e Associação

  • Sem Termos Genéricos: Nomes compostos apenas por palavras comuns como Moda, Roupas, Suporte ou apenas localizações como São Paulo, Brasil serão reprovados. O nome deve conter um identificador único da sua empresa (ex: Moda Estilo, Padaria Delícia São Paulo).
  • Consistência de Branding: O nome deve corresponder exatamente a como a empresa é conhecida no mercado (no site institucional, redes sociais, logotipo e documentos fiscais/CNPJ). A Meta confere essas informações durante a análise.
  • Associação com a Conta (WABA): Se o nome de exibição for de uma sub-marca ou departamento específico, a relação com a empresa principal deve ser clara (ex: Atendimento - Padaria Delícia).
  • Proibição de Nomes Individuais: Não use o nome completo de uma pessoa física sozinho (ex: João Silva será rejeitado, use João Silva Advocacia ou Consultório Dr. João Silva).
  • Termos Oficiais/Verificados: Não use palavras como "Oficial", "Verificado", "Official" ou "Verified" no nome, a menos que a conta já possua o selo de verificação oficial da Meta.
  • Sem Menção à Meta/WhatsApp: Não inclua os termos WhatsApp, Meta, Facebook ou Instagram no nome (ex: Suporte WhatsApp da Minha Empresa é proibido).
  • Evite URLs Completas: Não use formatos de sites com www. ou e-mails (ex: www.padariadelicia.com é rejeitado, mas PadariaDelicia.com é aceito se for o nome comercial da marca).
  • Proibido Promoções: O nome não pode conter mensagens promocionais, cupons ou frases de efeito (ex: Padaria Delícia - 20% OFF ou A Melhor Padaria da Cidade serão rejeitados).
Importante: O WhatsApp verifica ativamente a consistência do nome. Se a sua empresa se chama "Padaria Delícia", mas o site cadastrado ou as redes sociais utilizam outro nome sem qualquer ligação óbvia, o nome será rejeitado até que a associação seja comprovada ou o nome ajustado.

2. Exemplos de Nomes Aceitos vs. Rejeitados

O Que Pode (Aprovado) O Que Não Pode (Rejeitado) Motivo da Rejeição
Padaria Delícia PADARIA DELÍCIA Uso incorreto de caixa alta (ALL CAPS).
Loja Estilo São Paulo São Paulo Nome geográfico genérico.
Informática Silva Computadores Nome comercial genérico.
Atendimento - Padaria Delícia Suporte Termo de departamento sem o nome da marca.
PadariaDelicia.com www.padariadelicia.com Formato de URL completa (evitar phishing).
Padaria Delícia Padaria Delícia - Promoção Contém texto promocional no nome.
Minha Empresa Minha Empresa no WhatsApp Uso não autorizado de marcas registradas da Meta.
Clínica de Estética Bella Estética Bella Oficial Sugere verificação oficial sem possuir o selo.
Ana Souza Nutrição Ana Souza Nome de pessoa física sem identificador comercial.

3. O Que Fazer se Seu Nome For Rejeitado?

Se o seu Nome de Exibição for rejeitado, o processo de ajuste e reanálise é rápido e simples:

1
Revisar e Ajustar

Edite o nome no Painel do WhatsApp Manager na Meta de acordo com as diretrizes acima.

2
Comprovar Presença Digital (Branding)

Certifique-se de que o nome comercial desejado está claramente visível no site institucional e nas redes sociais da empresa vinculadas ao portfólio de negócios.

3
Enviar para Nova Análise

Submeta o novo nome. O WhatsApp costuma analisar novas solicitações dentro de um prazo que varia de **alguns minutos a até 24 horas**.

Boas Práticas & Prevenção de Banimento (2026)

Em 2026, a Meta intensificou significativamente as políticas de segurança e a inteligência dos seus algoritmos para proteger a experiência dos usuários no WhatsApp. Este guia apresenta os principais fatores que determinam a saúde do seu número e as diretrizes recomendadas para manter sua operação segura na API Oficial e no Modo de Coexistência.

1. O Cenário de Banimentos no WhatsApp

Os algoritmos de detecção da Meta evoluíram. Hoje, o foco de monitoramento está predominantemente no comportamento das contas comerciais e na qualidade das interações, e não puramente no volume bruto de mensagens enviadas.

Principais Fatores que Levam ao Banimento

  • Falta de Consentimento (Opt-in): Enviar mensagens ativas para contatos que não autorizaram a comunicação é o gatilho mais rápido para restrições. Listas frias ou bases compradas resultam em bloqueios quase instantâneos.
  • Comportamento Automatizado Não Oficial (Pirata): A utilização de ferramentas piratas, extensões de navegadores e APIs não oficiais que simulam interações humanas de forma fria é facilmente detectada pelos ritmos e padrões previsíveis dos envios.
  • Disparos em Massa Abruptos: Iniciar volumes elevados de mensagens repentinamente, sem aquecimento prévio ou respeitando os limites dos Messaging Tiers da Meta.
  • Alta Taxa de Denúncias (O Fator Mais Crítico): O botão "Denunciar Spam" ou "Bloquear" clicado pelos clientes finais é o fator com maior peso. Se o Quality Rating (Índice de Qualidade) do número cair para a cor vermelha (Low Quality), o número sofrerá sanções imediatas.
Mitos Comuns: O que NÃO causa banimento
A Meta não penaliza contas legítimas por:
  • Receber um alto volume de mensagens recebidas (Inbound).
  • Responder a milhares de clientes simultaneamente de forma legítima e contextual.
  • Apresentar crescimento orgânico de interações ou usar o WhatsApp Business App original manualmente.

2. O Uso Manual como "Trust Signal"

Ao contrário das ferramentas piratas, o uso manual e autêntico do WhatsApp é considerado o maior sinal de confiança (Trust Signal) para os algoritmos de segurança da Meta.

Por que o atendimento manual protege o seu número?
  • Humanização Natural: Padrões de digitação, pausas naturais, tempo de resposta variável e uso de vocabulários diversificados geram um comportamento 100% orgânico e seguro contra os robôs anti-spam.
  • Redução Drástica de Denúncias: O atendimento prestado por um agente humano tende a ser muito mais assertivo, resolvendo o problema do cliente de imediato, o que diminui a probabilidade dele clicar em "Denunciar Spam".
  • Frequência de Manutenção: A única exigência operacional do modo de coexistência é abrir o WhatsApp Business App no celular pelo menos uma vez a cada 13 dias para manter a chave da API ativa. O uso contínuo manual é benéfico e saudável para a conta.

3. Limites e Quantidades de Envio

Existe uma diferença conceitual e prática fundamental entre iniciar conversas através do WhatsApp Business App (celular) e através da Cloud API (automação):

Característica Pelo App de Celular (Manual) Pela Cloud API (Automação)
Necessidade de Templates Não (Mensagem livre) Sim (Obrigatoriamente aprovado pela Meta)
Recomendação de Limites 20 a 50 contatos frios/dia (sem histórico ou número salvo na agenda). Muito maior se os contatos forem clientes fidelizados. Controlado estritamente por Messaging Tiers.
Messaging Tiers (Volume) Não aplicável. Tier 0: 250 destinatários únicos/dia (Não verificado)
Tier 1: 1.000 destinatários únicos/dia (Verificado)
Tier 2: 10.000 destinatários únicos/dia
Tier 3: 100.000 destinatários únicos/dia
Janela de Conversa Livre Sempre livre. Livre por 24h após a última mensagem recebida do cliente.
Regra de Ouro dos Tiers: Para aumentar seu Tier na API (de 1.000 para 10.000, por exemplo), você deve enviar pelo menos a metade do seu limite diário atual em mensagens com alta qualidade em um período de 7 dias. O upgrade é automático pela Meta.

4. Boas Práticas Operacionais

No Modo de Coexistência (App + API)

  • Intervenção Humana Transparente: Utilize o aplicativo móvel para assumir conversas complexas em que o robô não está conseguindo guiar o cliente de forma assertiva.
  • Sincronização de Estado: Assegure-se de pausar a automação do robô quando a conversa estiver sob atendimento manual para evitar o envio de respostas simultâneas e incoerentes.
  • Manutenção de Conexão: Abra o aplicativo móvel pelo menos uma vez a cada 13 dias para evitar que a Meta desvincule a Cloud API por inatividade do app companheiro.
  • Conexões Suportadas: Lembre-se de que ao ativar a Coexistência, conexões antigas do WhatsApp Web ou aplicativos para desktop do Windows serão desconectados, pois o sistema aceita apenas dispositivos companheiros compatíveis com o espelhamento de eventos.
  • Desconexão do Número: Para desconectar um número em modo de coexistência da plataforma BSP e liberar a exclusão no Facebook Business Manager, o processo correto deve ser feito pelo app no celular — chamadas de API (deregister, subscribed_apps) não funcionam para esse tipo de conexão. Veja o passo a passo abaixo.
Como desconectar um número em Coexistência da plataforma BSP:
  1. Primeiro remova o número pela plataforma (botão Desconectar no dashboard)
  2. No celular, abra o WhatsApp Business
  3. Acesse Configurações → Conta → Plataforma Business
  4. Toque em Desconectar

Somente após esse passo a lixeira no Facebook Business Manager será liberada para excluir o número. Tentativas de desconectar via API (DELETE /subscribed_apps ou POST /deregister) retornam erro pois o vínculo de coexistência é gerenciado pelo app do celular, não pela Cloud API.

Na API Oficial Direta (Alta Performance)

  • Implemente o Double Opt-in: Sempre confirme se o usuário realmente deseja receber comunicações automáticas da sua marca antes de iniciar os fluxos transacionais ou promocionais.
  • Facilite o Opt-out (Cancelamento): Sempre dê a opção para o cliente parar de receber mensagens (ex: um botão de resposta escrito "Sair" ou "Cancelar"). É muito melhor o cliente sair da sua lista voluntariamente do que ele clicar no botão "Denunciar Spam" da Meta.
  • Aquecimento de Números Novos (Warm-up): Nunca inicie disparando 1.000 mensagens no primeiro dia de um número novo. Comece com 50 mensagens para clientes altamente engajados (que com certeza irão interagir), e dobre o volume a cada 2 dias se o Quality Rating se mantiver verde.
  • Preserve o Propósito do Template: Nunca mude a intenção de um template aprovado. Injetar links promocionais ou propagandas dentro de um template aprovado para "Atualizações Transacionais" causará a suspensão permanente do seu template e prejudicará o número.
  • Evite Loops Infinitos de Automação: Garanta que o fluxo do robô sempre possibilite o transbordo para atendimento humano ou a saída do menu para não frustrar o usuário.

Autenticação

Todas as requisições devem incluir seus tokens de acesso nos cabeçalhos HTTP. Você pode gerar esses tokens em seu dashboard.

Headers Requeridos
X-API-Key: sua_chave_de_api
X-API-Secret: seu_segredo_de_api

Início Rápido

Base URL

Endpoint Principal
https://api.covercut.com.br/api/v1

Webhooks

Nossos webhooks notificam seu sistema em tempo real sobre novas mensagens e mudanças de status.

Configuração

Acesse Configurações > Webhook no dashboard e informe a URL onde deseja receber os dados.

Configurar via API

Você também pode definir a URL de webhook por número diretamente pela API, sem acessar o painel — ideal para automatizar o provisionamento de números na sua aplicação ou em fluxos SaaS. A configuração é aplicada ao número identificado pelo phone_number_id no campo from.

Definir / atualizar o webhook

POST POST /api/v1/numbers/webhook
POST https://api.covercut.com.br/api/v1/numbers/webhook
Headers:
  X-API-Key: sua_chave
  X-API-Secret: seu_segredo
  Content-Type: application/json

Body:
{
  "from": "123456789012345",              // phone_number_id do número
  "webhook_url": "https://seu-sistema.com/webhook",
  "enabled": true,                         // opcional (default: true)
  "ignore_groups": false,                  // opcional
  "echo_enabled": false,                   // opcional (notificar msgs enviadas)
  "mirror_url": "https://backup.seu.com/hook", // opcional (webhook espelho)
  "mirror_enabled": false                  // opcional
}
Exemplo de Resposta — 200 OK
{
  "success": true,
  "message": "Webhook configurado com sucesso.",
  "webhook": {
    "phone_number_id": "123456789012345",
    "display_phone_number": "5547999999999",
    "webhook_url": "https://seu-sistema.com/webhook",
    "webhook_secret": "a1b2c3d4e5f6...",   // use para validar X-BSP-Signature
    "webhook_enabled": true,
    "ignore_groups": false,
    "echo_enabled": false,
    "mirror_url": null,
    "mirror_secret": null,
    "mirror_enabled": false,
    "using_fallback": false
  }
}

Consultar a configuração atual

GET GET /api/v1/numbers/webhook?from={phone_number_id}
GET https://api.covercut.com.br/api/v1/numbers/webhook?from=123456789012345
Headers:
  X-API-Key: sua_chave
  X-API-Secret: seu_segredo

Remover o webhook (voltar ao fallback geral)

Envie webhook_url vazio ou {"action":"delete"}. O número volta a usar a Configuração Geral da conta.

POST https://api.covercut.com.br/api/v1/numbers/webhook
{
  "from": "123456789012345",
  "action": "delete"
}

Campos

CampoTipoDescrição
fromstringObrigatório. O phone_number_id do número (veja em /api/v1/numbers/list).
webhook_urlstringURL de destino. Obrigatório, exceto ao remover.
enabledboolAtiva/desativa o envio. Default true.
ignore_groupsboolDescarta mensagens de grupos.
echo_enabledboolNotifica mensagens enviadas pela API (echo).
mirror_urlstringWebhook espelho — recebe o mesmo payload em paralelo.
mirror_enabledboolAtiva o webhook espelho.
actionstringUse "delete" para remover a configuração do número.
Nota: o webhook_secret é gerado automaticamente na primeira configuração e preservado nas atualizações seguintes — a resposta sempre traz o valor atual para você validar a assinatura X-BSP-Signature. Campos omitidos mantêm o valor atual do número.

Validar Assinatura (Segurança)

Cada envio contém o header X-BSP-Signature. Use-o para garantir que a mensagem veio de nós.

PHP — Validação de Assinatura
$signature = hash_hmac('sha256', $payload_bruto, $webhook_secret);
if (hash_equals($_SERVER['HTTP_X_BSP_SIGNATURE'], $signature)) {
    // Autêntico
}

Eventos de Mensagem

Exemplo de Payload — Nova Mensagem
{
  "event": "message",
  "direction": "inbound",
  "contact": {
    "wa_id": "5547999999999",
    "user_id": "BR.13491208655302741918",
    "name": "João Silva"
  },
  "message": {
    "id": "wamid...",
    "type": "text",
    "text": "Oi!"
  }
}
Exemplo Completo (Headers + Body)
{
  "headers": {
    "content-type": "application/json",
    "x-bsp-signature": "28a2a4200aaa6c457bfecca27d97f6a0b1dfef32f1bfa64b6aa8bfff2de4c429",
    "x-bsp-timestamp": "1778884885"
  },
  "body": {
    "event": "message",
    "from_number_id": "950147584848138",
    "contact": {
      "wa_id": "554799999999",
      "name": "Sandro"
    },
    "message": {
      "id": "wamid.HBgMNTU0N...",
      "type": "text",
      "text": "Ola"
    }
  }
}

Mensagens Enviadas (Echo) — Quem respondeu?

Toda mensagem enviada pelo seu número é repassada ao seu webhook como um evento de echo (event: "echo", direction: "outbound"). Isso permite acompanhar respostas independente de onde foram originadas.

Use o campo echo_source para saber a origem:

echo_sourceOrigem
apiEnviada pela Cloud API — inclui respostas digitadas por um atendente humano no Chatwoot e mensagens enviadas pela sua integração/IA via /api/v1/messages/send.
phoneEnviada diretamente do celular / app WhatsApp Business (modo Coexistência).

Para distinguir humano vs. IA dentro de echo_source: "api", use o campo opcional message.agent_name:

  • Respostas de um atendente no Chatwoot carregam o nome do atendente em agent_name.
  • Sua IA/integração define o próprio agent_name ao enviar (campo opcional no corpo de /messages/send) — ex.: "agent_name": "IA".
  • Convenção sugerida: trate nomes de pessoas como humano e o identificador da sua IA como automático.
Exemplo — Echo de resposta de um atendente
{
  "event": "echo",
  "direction": "outbound",
  "echo_source": "api",
  "from_number_id": "950147584848138",
  "contact": { "wa_id": "5547999999999", "name": "João Silva" },
  "message": {
    "id": "wamid...",
    "type": "text",
    "text": "Olá! Já vou te ajudar.",
    "agent_name": "Maria Atendente"
  }
}
Nota: agent_name é aditivo — só aparece quando há um nome associado ao envio. Mensagens antigas ou envios sem nome não trazem o campo.

Mensagens Não Suportadas (type: "unsupported")

A Meta envia type: "unsupported" quando o contato manda algo que a Cloud API não consegue entregar/renderizar (enquetes, mensagens de pagamento/pedido, recursos novos do app etc.). O conteúdo dessas mensagens não é recuperável via API — a mensagem real existe apenas no WhatsApp.

Quando disponível, o motivo vem no array message.errors (tipicamente código 131051):

Exemplo — Mensagem não suportada
{
  "event": "message",
  "direction": "inbound",
  "contact": { "wa_id": "5547999999999", "name": "João Silva" },
  "message": {
    "id": "wamid...",
    "type": "unsupported",
    "unsupported": { "type": "unknown" },
    "errors": [
      { "code": 131051, "title": "Message type is not currently supported" }
    ]
  }
}

Validar no n8n (Sem Código)

A forma mais simples de validar a segurança no n8n é:

  • Adicione um nó Crypto (Action: Hmac).
  • No campo Value, use: {{ JSON.stringify($json.body) }}.
  • No campo Secret, use seu Webhook Secret do Dashboard.
  • No campo Algorithm, use sha256.
  • Compare o resultado com o header x-bsp-signature.

Sincronização e Coexistência

Quando seu cliente conecta o número mantendo o aplicativo **WhatsApp Business** móvel ativo (Modo Coexistence), a Meta disponibiliza a sincronização do histórico das conversas e contatos salvos no celular. Nossa API recebe esses pacotes e os repassa de forma estruturada para o seu webhook.

Importante: Processamento Assíncrono

O volume de dados enviado no histórico de conversas dos últimos 6 meses pode ser extremamente grande (vários megabytes divididos em pacotes). É fundamental que o seu webhook processe esse evento de forma assíncrona (colocando em uma fila de background) e retorne imediatamente um status 200 OK para evitar que a API sofra timeout.

1. Webhook de Histórico de Conversas (history)

Este webhook é disparado automaticamente pela Meta logo após a conexão inicial do número no modo Coexistence, trazendo todo o histórico de conversas e mensagens dos últimos 6 meses segmentado por threads (conversas de cada contato).

Payload do Webhook — Evento history
{
  "event": "history",
  "from_number_id": "123456789012345",
  "history": {
    "metadata": {
      "phase": 1,
      "chunk_order": 1,
      "progress": 100
    },
    "threads": [
      {
        "id": "5547999999999",
        "context": {
          "wa_id": "5547999999999",
          "username": "sandro_dev",
          "user_id": "US.ENT.11815799212886844830"
        },
        "messages": [
          {
            "from": "5547999999999",
            "to": "5547888888888",
            "id": "wamid.HBgLNTUxMTk5OTk5...",
            "timestamp": "1715802120",
            "type": "text",
            "text": {
              "body": "Olá! Gostaria de saber mais sobre o plano SaaS."
            },
            "history_context": {
              "status": "read"
            }
          },
          {
            "from": "5547888888888",
            "to": "5547999999999",
            "id": "wamid.HBgLNTUxMTk5OTk5X2VjaG8...",
            "timestamp": "1715802180",
            "type": "text",
            "text": {
              "body": "Com certeza! Segue nosso catálogo de recursos."
            },
            "history_context": {
              "status": "sent"
            }
          }
        ]
      }
    ]
  }
}

Campos de Controle e Paginação do Histórico

CampoTipoDescrição
metadata.phaseinteger1: Mensagens mais recentes (entrega rápida);
2: Histórico profundo dos últimos 6 meses.
metadata.chunk_orderintegerOrdenação do pacote recebido (1, 2, 3...). Útil para rastrear a ordem de importação.
metadata.progressintegerPercentual de progresso da sincronização de 0 a 100%.
threads[].idstringIdentificador do contato dono do chat (Telefone ou BSUID).
threads[].contextobjectIdentificadores de privacidade adicionais da Meta (introduzidos em 2026).
messages[].history_context.statusstringO último status conhecido daquela mensagem histórica: sent, delivered, read, ou failed.

2. Webhook de Contatos do Celular (smb_app_state_sync)

Recebido após a sincronização inicial, repassando a agenda telefônica completa do aplicativo WhatsApp Business móvel do cliente.

Payload do Webhook — Evento smb_app_state_sync
{
  "event": "smb_app_state_sync",
  "from_number_id": "123456789012345",
  "smb_app_state_sync": {
    "contacts": [
      {
        "full_name": "Sandro Dev",
        "first_name": "Sandro",
        "phone_number": "5547999999999",
        "username": "sandro_dev",
        "user_id": "US.ENT.11815799212886844830"
      },
      {
        "full_name": "Maria Design",
        "first_name": "Maria",
        "phone_number": "5547988888888",
        "username": "maria_dsgn",
        "user_id": "US.ENT.99815799212886844112"
      }
    ]
  }
}

3. Eventos de Conexão e Offboarding (account_update)

Recebido quando um cliente do modelo Coexistence desinstala, limpa os dados ou re-registra o aplicativo do WhatsApp Business no celular. Esses eventos são cruciais para pausar campanhas de mensagens quando a Cloud API cai e retomá-las automaticamente quando ela volta.

Payload do Webhook — Eventos de account_update
{
  "event": "account_update",
  "timestamp": "2026-05-20T10:00:00-03:00",
  "from_number_id": "123456789012345",
  "account_update": {
    "phone_number": "5547999999999",
    "event": "ACCOUNT_OFFBOARDED" // Pode ser ACCOUNT_OFFBOARDED ou ACCOUNT_RECONNECTED
  }
}

Como Forçar a Sincronização via API

Se você desenvolve um SaaS e deseja forçar o envio imediato desses webhooks pela Meta (útil para acelerar a sincronização logo após a conexão do cliente no seu painel), faça uma requisição para o nosso endpoint dedicado:

POST POST /api/v1/numbers/sync_coexistence
POST https://api.covercut.com.br/api/v1/numbers/sync_coexistence
Headers:
  X-API-Key: sua_chave
  X-API-Secret: seu_segredo
  Content-Type: application/json

Body:
{
  "from": "123456789012345" // phone_number_id dono do número
}
Exemplo de Resposta — 200 OK
{
  "success": true,
  "message": "Sincronização iniciada com sucesso. Os dados serão transmitidos assincronamente em pacotes via Webhook.",
  "results": {
    "contacts": "Iniciado (contacts_sync_req_01)",
    "history": "Iniciado (history_sync_req_02)"
  }
}

4. Webhook de Status com Precificação (v24.0+)

Com as novas regras da Meta (Maio/2026), o webhook de status agora inclui detalhes sobre a cobrança de conversas individuais e de grupos (modelo PMP — Per-Message Pricing).

Payload do Webhook — Evento status
{
  "event": "status",
  "timestamp": "2026-05-19T14:15:00-03:00",
  "from_number_id": "123456789012345",
  "status": {
    "id": "wamid.HBgLNTUxM...",
    "status": "delivered",
    "recipient": "5547999999999",
    "pricing": {
      "billable": true,
      "pricing_model": "PMP",
      "type": "regular",
      "category": "group_marketing"
    }
  }
}

Os campos de precificação são mapeados da seguinte forma:

  • pricing.pricing_model: O modelo de cobrança. Para grupos, sempre retornará PMP (Per-Message Pricing).
  • pricing.type: Pode ser regular (cobrado) ou free_group_customer_service (grátis dentro da janela de serviço do grupo).
  • pricing.category: Categoria da mensagem. Exemplo: group_marketing, group_utility, ou group_service.

5. Webhooks da API de Grupos

Para gerenciar fluxos de grupos, você receberá notificações estruturadas de ciclo de vida, participantes e configurações.

Evento: group_lifecycle_update

Disparado ao criar ou deletar grupos. Contém o link de convite na criação.

{
  "event": "group_lifecycle_update",
  "timestamp": "2026-05-19T14:16:00-03:00",
  "from_number_id": "123456789012345",
  "from_number": "5547999999999",
  "data": {
    "event": "create",
    "group_id": "120363214587@g.us",
    "invite_link": "https://chat.whatsapp.com/L1M2N3O4P5Q6"
  }
}

Evento: group_participants_update

Disparado quando participantes entram ou saem do grupo.

{
  "event": "group_participants_update",
  "timestamp": "2026-05-19T14:17:00-03:00",
  "from_number_id": "123456789012345",
  "from_number": "5547999999999",
  "data": {
    "event": "join",
    "group_id": "120363214587@g.us",
    "participants": [
      {
        "user_id": "BR.874136928504",
        "wa_id": "5547888888888"
      }
    ]
  }
}

Business-Scoped User IDs (BSUID) — Junho 2026

ℹ️ Importante: A Meta adiciona o from_user_id (BSUID) aos webhooks — ela não descontinua o número de telefone. O número continua presente quando o usuário não adotou nome de usuário, ou pelas condições de retrospectiva de 30 dias / lista de contatos; é omitido apenas quando o usuário adota username e o número não pode ser incluído. Seu sistema está preparado para receber mensagens com BSUID, com ou sem número.

O que é BSUID?

BSUID (Business-Scoped User ID) é um identificador único gerado pela Meta para cada par usuário-negócio. Formato: CC. + até 128 alfanuméricos (ex: US.13491208655302741918); o BSUID principal usa o prefixo CC.ENT. (ex: US.ENT.11815799212886844830). O username do WhatsApp (ex: joao.silva) é exibido no app, mas o identificador usado na API é o BSUID.

Estrutura do Webhook com BSUID

Exemplo — Mensagem com BSUID (Julho 2026+)
{
  "event": "message",
  "direction": "inbound",
  "contact": {
    "user_id": "BR.13491208655302741918",
    "username": "joao.silva",
    "name": "João Silva"
  },
  "message": {
    "id": "wamid...",
    "type": "text",
    "text": "Oi, tudo bem?"
  }
}

Transição (Junho 2026) — Dual Mode

Durante a transição, webhooks incluem ambos número e BSUID. Seu sistema escolhe qual usar:

Exemplo — Mensagem com Número + BSUID
{
  "event": "message",
  "direction": "inbound",
  "contact": {
    "wa_id": "5547999999999",      ← número (omitido se username adotado e nº indisponível)
    "user_id": "US.13491208655302741918", ← BSUID (identificador estável)
    "username": "joao.silva",       ← username opcional
    "parent_user_id": "US.ENT.118...",    ← Parent BSUID (só multi-portfólio)
    "name": "João Silva"
  },
  "message": { ... }
}

Recomendações de Implementação

  • Use o BSUID como identificador estável: Se user_id estiver presente, use-o como chave. Mantenha o wa_id (número) quando vier — ele continua sendo enviado na maioria dos casos.
  • Armazene username: Novos contatos vêm com username — capture e exiba quando disponível.
  • Não remova o suporte a números: O número não é descontinuado; apenas pode faltar para usuários que adotaram nome de usuário.
  • Solicite o número quando precisar: Use o botão REQUEST_CONTACT_INFO (veja abaixo) para pedir o telefone de um usuário que o ocultou.

Campos aditivos por tipo de webhook

A partir de julho/2026 os webhooks podem trazer campos extras. Todos são aditivos — só aparecem quando a Meta os envia, sem quebrar o formato existente.

CampoOndeDescrição
contact.user_id / message.from_user_idmessage / echoBSUID do remetente.
contact.parent_user_idmessage / echoParent BSUID (só se multi-portfólio habilitado).
contact.usernamemessage / echoNome de usuário, quando o usuário adotou um.
status.recipient_user_idstatusBSUID do destinatário.
status.recipient_parent_user_idstatusParent BSUID do destinatário (multi-portfólio).
status.usernamestatus (delivered/read)Username do destinatário, quando disponível.

Solicitar contato — REQUEST_CONTACT_INFO (Julho 2026)

Quando o usuário toca no botão REQUEST_CONTACT_INFO (ou compartilha um contato), chega um webhook de mensagem com type: "contacts" contendo o número.

Payload — Webhook de contacts (compartilhamento)
{
  "event": "message",
  "contact": { "user_id": "US.13491208655302741918" },
  "message": {
    "type": "contacts",
    "from_user_id": "US.13491208655302741918",
    "contacts": [
      {
        "origin": "contact_request",   // "other" = compartilhou um contato direto
        "vcard": "...",                // presente só quando origin = "other"
        "phones": [
          { "phone": "+5547999999999", "wa_id": "5547999999999", "type": "..." }
        ]
      }
    ]
  }
}

Novos eventos de webhook

Três novos eventos passam a ser encaminhados ao seu endpoint. Inscreva os campos correspondentes no Painel de Apps da Meta para recebê-los.

user_id_update — BSUID do usuário mudou

Disparado quando o BSUID de um usuário muda (ex.: troca de número). Atualize o mapeamento no seu CRM usando previouscurrent.

Payload — Evento user_id_update
{
  "event": "user_id_update",
  "from_number_id": "<phone_number_id>",
  "contacts": [ { "wa_id": "5547999999999" } ],
  "user_id_update": [
    {
      "wa_id": "5547999999999",
      "user_id": { "previous": "US.OLD...", "current": "US.NEW..." },
      "parent_user_id": { "previous": "US.ENT.OLD...", "current": "US.ENT.NEW..." },
      "timestamp": "1750030073"
    }
  ]
}

business_username_updates — status do nome de usuário comercial

Disparado quando o status do seu nome de usuário comercial muda (reserved, approved ou deleted).

Payload — Evento business_username_updates
{
  "event": "business_username_updates",
  "from_number_id": "<phone_number_id>",
  "from_number": "5547999999999",
  "username": "minhaempresa",
  "status": "approved"   // approved | reserved | deleted
}

user_preferences — preferências de marketing (opt-in/out)

Encaminha as preferências do usuário, agora com BSUID/username quando presentes.

Payload — Evento user_preferences
{
  "event": "user_preferences",
  "from_number_id": "<phone_number_id>",
  "contacts": [ { "wa_id": "5547999999999", "user_id": "US.134..." } ],
  "user_preferences": [
    { "category": "marketing_messages", "value": "stop", "timestamp": 1750030073 }
  ]
}

Calling API — Webhooks de Chamadas (v25.0+)

Quando usuários ligam para seu número WhatsApp, você recebe webhooks detalhados sobre o evento de chamada com informações completas do chamador, incluindo BSUID e username.

Tipos de Eventos de Chamada

StatusDescrição
incomingChamada entrante iniciada pelo usuário
missedChamada não atendida
rejectedVocê rejeitou a chamada
acceptedVocê aceitou a chamada
connectedConexão estabelecida (início da conversa)
endedChamada finalizada

Exemplo de Webhook — Chamada Recebida

Payload — Nova Chamada Entrante
{
  "event": "call",
  "timestamp": "2026-06-01T10:30:00-03:00",
  "from_number_id": "950147584848138",
  "from_number": "+55 47 9999-9999",
  "call": {
    "id": "call_HBgM...",
    "status": "incoming",
    "duration_seconds": 0,
    "from": "5547999999999",
    "from_user_id": "BR.13491208655302741918",
    "from_username": "joao.silva",
    "from_name": "João Silva",
    "to_user_id": "seu_bsuid_aqui",
    "contacts": [{
      "user_id": "BR.13491208655302741918",
      "username": "joao.silva",
      "profile": {
        "name": "João Silva"
      }
    }]
  }
}

Exemplo — Chamada Finalizada (com duração)

Payload — Chamada Encerrada
{
  "event": "call",
  "timestamp": "2026-06-01T10:35:45-03:00",
  "from_number": "+55 47 9999-9999",
  "call": {
    "id": "call_HBgM...",
    "status": "ended",
    "duration_seconds": 312,     ← 5 minutos 12 segundos
    "from_user_id": "BR.xxxxx",
    "from_username": "joao.silva",
    "from_name": "João Silva"
  }
}

Casos de Uso

  • Rastreamento de chamadas: Armazene call_id, from_user_id, duration_seconds para análise.
  • CRM integration: Sincronize automaticamente chamadas entrantes com seu CRM usando BSUID.
  • Alertas: Notifique agentes sobre chamadas perdidas ou rejeitadas.
  • Relatórios: Gere dashboards de volume de chamadas e duração média por período.

Rastreamento de Origem — Facebook Ads

Quando usuários iniciam conversa através de anúncios do Facebook, você recebe dados detalhados sobre a campanha que gerou o contato. Ideal para análise de ROI e origem de leads.

Campo referral no Webhook

Presente apenas quando o usuário chegou via Facebook Ads ou outro canal de origem Meta:

Exemplo — Mensagem com Referral (Facebook Ads)
{
  "event": "message",
  "direction": "inbound",
  "contact": {
    "wa_id": "5547999999999",
    "user_id": "BR.xxxxx",
    "name": "João Silva"
  },
  "message": {
    "id": "wamid...",
    "type": "text",
    "text": "Poderia me passar mais informações?",
    "referral": {
      "source_type": "ad",
      "source_id": "120249258250040188",
      "source_url": "https://fb.me/6Y5vfFmfx",
      "headline": "Converse conosco",
      "ctwa_clid": "AfgryxuX3no-rLzpWHK9py-sp-..."
    }
  }
}

Campos de Referral

CampoTipoDescrição
source_typestringTipo de origem: "ad", "conversation_referral", etc.
source_idstringID único da campanha/anúncio na Meta.
source_urlstringURL que o usuário clicou para iniciar a conversa.
headlinestringTexto do botão ou copy do anúncio.
ctwa_clidstringID de clique do WhatsApp para rastreamento granular.

Integração com Analytics

  • ROI por Campanha: Agrupe source_id e calcule custo/conversão.
  • Performance por Headline: Compare qual copy do anúncio gera mais engajamento.
  • Atribuição Multi-canal: Cruzar dados com Google Analytics usando ctwa_clid.
Nota: O campo referral só aparece quando o usuário inicia conversa através de um anúncio. Não está presente em mensagens iniciadas manualmente.

Webhook de Alertas

Configure um endpoint separado para receber alertas operacionais como quedas de qualidade ou suspensões.

Mensagens

POST Enviar Mensagem de Texto

Envia uma mensagem de texto simples. Use to para enviar ao número de telefone ou recipient para enviar ao BSUID do usuário (veja IDs de Usuário).

Múltiplos Números Conectados:

Se você possui mais de um número ativo, adicione o parâmetro "from": "ID_DO_SEU_NUMERO" no JSON para especificar por qual canal enviar a mensagem. Caso não seja informado, será utilizado o primeiro número conectado.

POST /api/v1/messages/send (Por Número)
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "text",
  "text": {
    "body": "Olá! Como posso ajudar?"
  }
}
POST /api/v1/messages/send (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "text",
  "text": {
    "body": "Olá! Como posso ajudar?"
  }
}

Resposta

JSON — 200 OK
{
  "success": true,
  "message": "Mensagem enviada com sucesso",
  "message_id": "wamid.HBgLNTU0Nzk5...",
  "from": "1234567890",
  "to": "5547999999999",
  "user_id": "BR.13491208655302741918"
}

POST Enviar Imagem

POST /api/v1/messages/send (Via Link)
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "image",
  "image": {
    "link": "https://exemplo.com/imagem.jpg",
    "caption": "Legenda da imagem"
  }
}
POST /api/v1/messages/send (Via Link - Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "image",
  "image": {
    "link": "https://exemplo.com/imagem.jpg",
    "caption": "Legenda da imagem"
  }
}
POST /api/v1/messages/send (Via Media ID)
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "image",
  "image": {
    "id": "8451871321564",
    "caption": "Legenda opcional"
  }
}
POST /api/v1/messages/send (Via Media ID - Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "image",
  "image": {
    "id": "8451871321564",
    "caption": "Legenda opcional"
  }
}

POST Enviar Vídeo

POST /api/v1/messages/send (Via Link)
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "video",
  "video": {
    "link": "https://exemplo.com/video.mp4",
    "caption": "Legenda opcional"
  }
}
POST /api/v1/messages/send (Via Link - Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "video",
  "video": {
    "link": "https://exemplo.com/video.mp4",
    "caption": "Legenda opcional"
  }
}
POST /api/v1/messages/send (Via Media ID)
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "video",
  "video": {
    "id": "8451871321564"
  }
}
POST /api/v1/messages/send (Via Media ID - Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "video",
  "video": {
    "id": "8451871321564"
  }
}

POST Enviar Áudio

Para enviar um arquivo de áudio simples. Se quiser que o áudio apareça como uma mensagem de voz (voice note gravado na hora), o arquivo deve estar no formato .ogg (codec opus) e você deve incluir o parâmetro "voice": true.

POST /api/v1/messages/send (Via Link)
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "audio",
  "audio": {
    "link": "https://exemplo.com/audio.mp3"
  }
}
POST /api/v1/messages/send (Via Link - Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "audio",
  "audio": {
    "link": "https://exemplo.com/audio.mp3"
  }
}
POST /api/v1/messages/send (Voice Note via Media ID)
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "audio",
  "audio": {
    "id": "8451871321564",
    "voice": true
  }
}
POST /api/v1/messages/send (Voice Note via Media ID - Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "audio",
  "audio": {
    "id": "8451871321564",
    "voice": true
  }
}

POST Enviar Documento

POST /api/v1/messages/send (Via Link)
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "document",
  "document": {
    "link": "https://exemplo.com/arquivo.pdf",
    "filename": "documento.pdf"
  }
}
POST /api/v1/messages/send (Via Link - Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "document",
  "document": {
    "link": "https://exemplo.com/arquivo.pdf",
    "filename": "documento.pdf"
  }
}
POST /api/v1/messages/send (Via Media ID)
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "document",
  "document": {
    "id": "8451871321564",
    "filename": "boleto.pdf"
  }
}
POST /api/v1/messages/send (Via Media ID - Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "document",
  "document": {
    "id": "8451871321564",
    "filename": "boleto.pdf"
  }
}

POST Enviar Sticker (Figurinha)

POST /api/v1/messages/send (Via Link)
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "sticker",
  "sticker": {
    "link": "https://exemplo.com/figurinha.webp"
  }
}
POST /api/v1/messages/send (Via Link - Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "sticker",
  "sticker": {
    "link": "https://exemplo.com/figurinha.webp"
  }
}
POST /api/v1/messages/send (Via Media ID)
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "sticker",
  "sticker": {
    "id": "8451871321564"
  }
}
POST /api/v1/messages/send (Via Media ID - Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "sticker",
  "sticker": {
    "id": "8451871321564"
  }
}

POST Enviar Localização

POST /api/v1/messages/send
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "location",
  "location": {
    "latitude": -26.9195,
    "longitude": -49.0661,
    "name": "Covercut",
    "address": "Rua Exemplo, 123"
  }
}
POST /api/v1/messages/send (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "location",
  "location": {
    "latitude": -26.9195,
    "longitude": -49.0661,
    "name": "Covercut",
    "address": "Rua Exemplo, 123"
  }
}

POST Enviar Contato

POST /api/v1/messages/send
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "contacts",
  "contacts": [
    {
      "name": { "formatted_name": "João Silva", "first_name": "João" },
      "phones": [{ "phone": "5547999999999", "type": "CELL" }]
    }
  ]
}
POST /api/v1/messages/send (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "contacts",
  "contacts": [
    {
      "name": { "formatted_name": "João Silva", "first_name": "João" },
      "phones": [{ "phone": "5547999999999", "type": "CELL" }]
    }
  ]
}

POST Enviar Reação

POST /api/v1/messages/send
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "reaction",
  "reaction": {
    "message_id": "wamid.xxx",
    "emoji": "👍"
  }
}
POST /api/v1/messages/send (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "reaction",
  "reaction": {
    "message_id": "wamid.xxx",
    "emoji": "👍"
  }
}

POST Responder / Citar Mensagem

Para responder uma mensagem específica (fazendo com que ela apareça como citação no balão), inclua o campo context com o message_id (wamid) da mensagem original. Funciona com qualquer tipo de mensagem: texto, imagem, vídeo, áudio, documento, interativo, etc.

O message_id da mensagem recebida chega pelo webhook no campo message.id.

POST /api/v1/messages/send — Responder com texto
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "text",
  "text": {
    "body": "Claro! Vou verificar isso agora mesmo."
  },
  "context": {
    "message_id": "wamid.HBgLNTU0Nzk5OTk5OTk5..."
  }
}
POST /api/v1/messages/send — Responder com texto (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "text",
  "text": {
    "body": "Claro! Vou verificar isso agora mesmo."
  },
  "context": {
    "message_id": "wamid.HBgLNTU0Nzk5OTk5OTk5..."
  }
}
POST /api/v1/messages/send — Responder com imagem
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "image",
  "image": {
    "link": "https://exemplo.com/imagem.jpg",
    "caption": "Aqui está o comprovante!"
  },
  "context": {
    "message_id": "wamid.HBgLNTU0Nzk5OTk5OTk5..."
  }
}
POST /api/v1/messages/send — Responder com imagem (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "image",
  "image": {
    "link": "https://exemplo.com/imagem.jpg",
    "caption": "Aqui está o comprovante!"
  },
  "context": {
    "message_id": "wamid.HBgLNTU0Nzk5OTk5OTk5..."
  }
}
Como obter o message_id para responder:

Ao receber uma mensagem pelo webhook, o campo message.id contém o wamid. Armazene-o e passe-o no campo context.message_id ao responder. Veja a seção Webhooks para o formato do payload.

POST Enviar Mensagem Interativa

Crie uma experiência dinâmica com menus de lista, botões de resposta rápida ou botões de link externo (CTA URL).

POST Enviar Botões de Resposta Rápida

Envia uma mensagem com até 3 botões de resposta rápida. Ideal para confirmações simples.

POST /api/v1/messages/send
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "interactive",
  "interactive": {
    "type": "button",
    "header": { "type": "text", "text": "Confirmação" },
    "body": { "text": "Você gostaria de agendar agora?" },
    "footer": { "text": "Selecione uma opção" },
    "action": {
      "buttons": [
        { "type": "reply", "reply": { "id": "btn_yes", "title": "Sim" } },
        { "type": "reply", "reply": { "id": "btn_no", "title": "Não" } }
      ]
    }
  }
}
POST /api/v1/messages/send (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "interactive",
  "interactive": {
    "type": "button",
    "header": { "type": "text", "text": "Confirmação" },
    "body": { "text": "Você gostaria de agendar agora?" },
    "footer": { "text": "Selecione uma opção" },
    "action": {
      "buttons": [
        { "type": "reply", "reply": { "id": "btn_yes", "title": "Sim" } },
        { "type": "reply", "reply": { "id": "btn_no", "title": "Não" } }
      ]
    }
  }
}

1. Menu de Lista (List Message)

POST /api/v1/messages/send
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "interactive",
  "interactive": {
    "type": "list",
    "header": { "type": "text", "text": "Título do Menu" },
    "body": { "text": "Escolha uma opção abaixo:" },
    "footer": { "text": "Rodapé opcional" },
    "action": {
      "button": "Ver Opções",
      "sections": [
        {
          "title": "Serviços",
          "rows": [
            { "id": "id1", "title": "Corte de Cabelo", "description": "30 minutos" },
            { "id": "id2", "title": "Barba Completa", "description": "20 minutos" }
          ]
        }
      ]
    }
  }
}
POST /api/v1/messages/send (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "interactive",
  "interactive": {
    "type": "list",
    "header": { "type": "text", "text": "Título do Menu" },
    "body": { "text": "Escolha uma opção abaixo:" },
    "footer": { "text": "Rodapé opcional" },
    "action": {
      "button": "Ver Opções",
      "sections": [
        {
          "title": "Serviços",
          "rows": [
            { "id": "id1", "title": "Corte de Cabelo", "description": "30 minutos" },
            { "id": "id2", "title": "Barba Completa", "description": "20 minutos" }
          ]
        }
      ]
    }
  }
}

2. Botões de Resposta Rápida (Reply Buttons)

POST /api/v1/messages/send
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "interactive",
  "interactive": {
    "type": "button",
    "body": { "text": "Você gostaria de agendar agora?" },
    "action": {
      "buttons": [
        { "type": "reply", "reply": { "id": "btn_yes", "title": "Sim" } },
        { "type": "reply", "reply": { "id": "btn_no", "title": "Não" } }
      ]
    }
  }
}
POST /api/v1/messages/send (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "interactive",
  "interactive": {
    "type": "button",
    "body": { "text": "Você gostaria de agendar agora?" },
    "action": {
      "buttons": [
        { "type": "reply", "reply": { "id": "btn_yes", "title": "Sim" } },
        { "type": "reply", "reply": { "id": "btn_no", "title": "Não" } }
      ]
    }
  }
}

3. Botão de URL (CTA URL)

Envia uma mensagem interativa com um botão que abre um link externo. Este é o novo recurso oficial da Meta que substitui a necessidade de templates para links simples.

POST /api/v1/messages/send
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "interactive",
  "interactive": {
    "type": "cta_url",
    "header": { "type": "text", "text": "Confira nosso site" },
    "body": { "text": "Clique no botão abaixo para ver as ofertas exclusivas que preparamos para você hoje." },
    "footer": { "text": "Ofertas válidas por tempo limitado" },
    "action": {
      "name": "cta_url",
      "parameters": {
        "display_text": "Ver Ofertas",
        "url": "https://sua-loja.com.br/ofertas"
      }
    }
  }
}
POST /api/v1/messages/send (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "interactive",
  "interactive": {
    "type": "cta_url",
    "header": { "type": "text", "text": "Confira nosso site" },
    "body": { "text": "Clique no botão abaixo para ver as ofertas exclusivas que preparamos para você hoje." },
    "footer": { "text": "Ofertas válidas por tempo limitado" },
    "action": {
      "name": "cta_url",
      "parameters": {
        "display_text": "Ver Ofertas",
        "url": "https://sua-loja.com.br/ofertas"
      }
    }
  }
}
Notas Importantes:

• O display_text do botão aceita no máximo 20 caracteres.

• O cabeçalho (header) é opcional e aceita text, image, video ou document.

• Este tipo de mensagem não requer aprovação prévia da Meta (diferente de templates).

POST Indicador de Digitação + Marcar como Lida

Em uma única chamada, este endpoint faz duas coisas simultaneamente:

  • Marca a mensagem como lida — o remetente vê os dois tiques azuis (✓✓)
  • Exibe o "digitando..." — o indicador de digitação aparece para o contato

Use o message_id (wamid) recebido no evento de webhook da mensagem inbound.

POST /api/v1/messages/typing
{
  "message_id": "wamid.xxx"
}

Opcional — se tiver múltiplos números, especifique qual usar com o campo from:

Com múltiplos números
{
  "message_id": "wamid.xxx",
  "from": "phone_number_id"
}

POST Carrossel de Mídia Interativo

Envie uma mensagem interativa com 2 a 10 cartões em formato de carrossel horizontal. Cada cartão pode ter uma imagem ou vídeo no cabeçalho, texto no corpo e um botão de URL ou de resposta rápida.

Regras da Meta para Carrosséis:

• A mensagem deve ter entre 2 e 10 cartões.

• O campo body.text principal (acima dos cartões) é obrigatório.

• Cada cartão deve ter cabeçalho do tipo image ou video.

• O tipo e a quantidade de botões deve ser igual em todos os cartões.

Endpoint dedicado

POST /api/v1/messages/carousel
POST https://api.covercut.com.br/api/v1/messages/carousel

Parâmetros

Campo Tipo Obrigatório Descrição
from string Condicional Phone Number ID do remetente. Obrigatório se há múltiplos números conectados.
to string Sim* Telefone do destinatário. Use to ou recipient.
recipient string Sim* BSUID do destinatário. Use to ou recipient.
body.text string Sim Texto principal exibido acima dos cartões.
cards array Sim Array de 2 a 10 cartões do carrossel.
cards[].header.type string Sim image ou video.
cards[].header.image.link string Condicional URL pública da imagem. Use link ou id.
cards[].header.image.id string Condicional Media ID da imagem (upload prévio). Use link ou id.
cards[].body.text string Não Texto descritivo exibido no corpo do cartão.
cards[].action object Sim Botão do cartão — cta_url ou quick_reply (veja exemplos abaixo).

Exemplo 1 — Carrossel com Botão de URL (CTA URL)

POST /api/v1/messages/carousel
{
  "from": "123456789012345",
  "to": "5547999999999",
  "body": {
    "text": "Confira nossas promoções da semana! 🔥"
  },
  "cards": [
    {
      "header": {
        "type": "image",
        "image": {
          "link": "https://exemplo.com/promo1.jpg"
        }
      },
      "body": {
        "text": "Produto A — De R$99 por R$59,90"
      },
      "action": {
        "name": "cta_url",
        "parameters": {
          "display_text": "Ver Produto",
          "url": "https://sua-loja.com.br/produto-a"
        }
      }
    },
    {
      "header": {
        "type": "image",
        "image": {
          "link": "https://exemplo.com/promo2.jpg"
        }
      },
      "body": {
        "text": "Produto B — Frete Grátis acima de R$100"
      },
      "action": {
        "name": "cta_url",
        "parameters": {
          "display_text": "Ver Produto",
          "url": "https://sua-loja.com.br/produto-b"
        }
      }
    }
  ]
}
POST /api/v1/messages/carousel (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "body": {
    "text": "Confira nossas promoções da semana! 🔥"
  },
  "cards": [
    {
      "header": {
        "type": "image",
        "image": {
          "link": "https://exemplo.com/promo1.jpg"
        }
      },
      "body": {
        "text": "Produto A — De R$99 por R$59,90"
      },
      "action": {
        "name": "cta_url",
        "parameters": {
          "display_text": "Ver Produto",
          "url": "https://sua-loja.com.br/produto-a"
        }
      }
    },
    {
      "header": {
        "type": "image",
        "image": {
          "link": "https://exemplo.com/promo2.jpg"
        }
      },
      "body": {
        "text": "Produto B — Frete Grátis acima de R$100"
      },
      "action": {
        "name": "cta_url",
        "parameters": {
          "display_text": "Ver Produto",
          "url": "https://sua-loja.com.br/produto-b"
        }
      }
    }
  ]
}

Exemplo 2 — Carrossel com Botões de Resposta Rápida

POST /api/v1/messages/carousel
{
  "from": "123456789012345",
  "to": "5547999999999",
  "body": {
    "text": "Escolha o serviço que deseja agendar 📅"
  },
  "cards": [
    {
      "header": {
        "type": "image",
        "image": {
          "link": "https://exemplo.com/servico-corte.jpg"
        }
      },
      "body": {
        "text": "Corte de Cabelo — R$45,00 (30 min)"
      },
      "action": {
        "buttons": [
          {
            "type": "quick_reply",
            "quick_reply": {
              "id": "agendar_corte",
              "title": "Agendar"
            }
          }
        ]
      }
    },
    {
      "header": {
        "type": "image",
        "image": {
          "link": "https://exemplo.com/servico-barba.jpg"
        }
      },
      "body": {
        "text": "Barba Completa — R$35,00 (20 min)"
      },
      "action": {
        "buttons": [
          {
            "type": "quick_reply",
            "quick_reply": {
              "id": "agendar_barba",
              "title": "Agendar"
            }
          }
        ]
      }
    },
    {
      "header": {
        "type": "image",
        "image": {
          "link": "https://exemplo.com/servico-combo.jpg"
        }
      },
      "body": {
        "text": "Combo Completo — R$70,00 (50 min)"
      },
      "action": {
        "buttons": [
          {
            "type": "quick_reply",
            "quick_reply": {
              "id": "agendar_combo",
              "title": "Agendar"
            }
          }
        ]
      }
    }
  ]
}
POST /api/v1/messages/carousel (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "body": {
    "text": "Escolha o serviço que deseja agendar 📅"
  },
  "cards": [
    {
      "header": {
        "type": "image",
        "image": {
          "link": "https://exemplo.com/servico-corte.jpg"
        }
      },
      "body": {
        "text": "Corte de Cabelo — R$45,00 (30 min)"
      },
      "action": {
        "buttons": [
          {
            "type": "quick_reply",
            "quick_reply": {
              "id": "agendar_corte",
              "title": "Agendar"
            }
          }
        ]
      }
    },
    {
      "header": {
        "type": "image",
        "image": {
          "link": "https://exemplo.com/servico-barba.jpg"
        }
      },
      "body": {
        "text": "Barba Completa — R$35,00 (20 min)"
      },
      "action": {
        "buttons": [
          {
            "type": "quick_reply",
            "quick_reply": {
              "id": "agendar_barba",
              "title": "Agendar"
            }
          }
        ]
      }
    },
    {
      "header": {
        "type": "image",
        "image": {
          "link": "https://exemplo.com/servico-combo.jpg"
        }
      },
      "body": {
        "text": "Combo Completo — R$70,00 (50 min)"
      },
      "action": {
        "buttons": [
          {
            "type": "quick_reply",
            "quick_reply": {
              "id": "agendar_combo",
              "title": "Agendar"
            }
          }
        ]
      }
    }
  ]
}

Resposta

JSON — 200 OK
{
  "success": true,
  "message": "Carrossel enviado com sucesso",
  "message_id": "wamid.HBgLNTU0Nzk5...",
  "from": "123456789012345",
  "to": "5547999999999",
  "user_id": "BR.13491208655302741918"
}
Atenção — Consistência de Botões:

Todos os cartões do carrossel devem usar o mesmo tipo e a mesma quantidade de botões. Por exemplo, se o primeiro cartão tem 1 botão quick_reply, todos os demais cartões também devem ter exatamente 1 botão quick_reply. Misturar cta_url com quick_reply resultará em erro.

Mensagens de Catálogo e Produto

Envie produtos do seu catálogo do WhatsApp diretamente na conversa — sem precisar de template aprovado. Use o endpoint dedicado:

Endpoint
POST https://api.covercut.com.br/api/v1/messages/catalog
Pré-requisitos e Limitações:
  • Catálogo vinculado: Crie o catálogo no Commerce Manager e vincule ao WABA do número antes de usar.
  • catalog_id e SKUs: O catalog_id e os product_retailer_id (SKUs) são obtidos no Commerce Manager da Meta.
  • Janela de 24h: Esses tipos de mensagem só podem ser enviados dentro da janela de atendimento ativa (o cliente precisa ter iniciado uma conversa nas últimas 24h). Fora da janela, use um Template de Catálogo aprovado.

POST Produto Único (Single Product)

Exibe um card interativo com um único produto do catálogo. O cliente pode ver detalhes, adicionar ao carrinho e iniciar o checkout.

POST /api/v1/messages/catalog
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "product",
  "body": {
    "text": "Confira este produto em promoção!"
  },
  "footer": {
    "text": "Estoque limitado"
  },
  "action": {
    "catalog_id": "SEU_CATALOG_ID",
    "product_retailer_id": "SKU_DO_PRODUTO"
  }
}
POST /api/v1/messages/catalog (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "product",
  "body": {
    "text": "Confira este produto em promoção!"
  },
  "footer": {
    "text": "Estoque limitado"
  },
  "action": {
    "catalog_id": "SEU_CATALOG_ID",
    "product_retailer_id": "SKU_DO_PRODUTO"
  }
}
Campos opcionais:

body, footer e header são opcionais no produto único. O card do produto (imagem, título e preço) é exibido automaticamente a partir do catálogo.

POST Multi-Produtos (Product List)

Exibe uma lista com até 30 produtos organizados em até 10 seções. Ideal para vitrines e recomendações personalizadas.

POST /api/v1/messages/catalog
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "product_list",
  "header": {
    "type": "text",
    "text": "Produtos em Destaque"
  },
  "body": {
    "text": "Selecionamos estes itens especialmente para você 🛍️"
  },
  "footer": {
    "text": "Frete grátis acima de R$200"
  },
  "action": {
    "catalog_id": "SEU_CATALOG_ID",
    "sections": [
      {
        "title": "Mais Vendidos",
        "product_items": [
          { "product_retailer_id": "SKU_1" },
          { "product_retailer_id": "SKU_2" },
          { "product_retailer_id": "SKU_3" }
        ]
      },
      {
        "title": "Novidades",
        "product_items": [
          { "product_retailer_id": "SKU_4" },
          { "product_retailer_id": "SKU_5" }
        ]
      }
    ]
  }
}
POST /api/v1/messages/catalog (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "product_list",
  "header": {
    "type": "text",
    "text": "Produtos em Destaque"
  },
  "body": {
    "text": "Selecionamos estes itens especialmente para você 🛍️"
  },
  "footer": {
    "text": "Frete grátis acima de R$200"
  },
  "action": {
    "catalog_id": "SEU_CATALOG_ID",
    "sections": [
      {
        "title": "Mais Vendidos",
        "product_items": [
          { "product_retailer_id": "SKU_1" },
          { "product_retailer_id": "SKU_2" },
          { "product_retailer_id": "SKU_3" }
        ]
      },
      {
        "title": "Novidades",
        "product_items": [
          { "product_retailer_id": "SKU_4" },
          { "product_retailer_id": "SKU_5" }
        ]
      }
    ]
  }
}

POST Catálogo Completo (Catalog Message)

Envia um botão que abre o catálogo completo do negócio no WhatsApp. O parâmetro thumbnail_product_retailer_id é opcional e define qual produto aparece como capa.

POST /api/v1/messages/catalog
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "catalog_message",
  "body": {
    "text": "Confira todo o nosso catálogo com preços e disponibilidade em tempo real! 🛒"
  },
  "footer": {
    "text": "Entrega para todo o Brasil"
  },
  "action": {
    "name": "catalog_message",
    "parameters": {
      "thumbnail_product_retailer_id": "SKU_CAPA"
    }
  }
}
POST /api/v1/messages/catalog (Por BSUID)
{
  "from": "123456789012345",
  "recipient": "BR.13491208655302741918",
  "type": "catalog_message",
  "body": {
    "text": "Confira todo o nosso catálogo com preços e disponibilidade em tempo real! 🛒"
  },
  "footer": {
    "text": "Entrega para todo o Brasil"
  },
  "action": {
    "name": "catalog_message",
    "parameters": {
      "thumbnail_product_retailer_id": "SKU_CAPA"
    }
  }
}

Resposta (todos os tipos)

JSON — 200 OK
{
  "success": true,
  "message": "Mensagem de catálogo enviada com sucesso",
  "message_id": "wamid.HBgLNTU0Nzk5...",
  "from": "123456789012345",
  "to": "5547999999999"
}

GET Consultar Status da Mensagem

Consulte o status de entrega das mensagens enviadas pelo seu número. Use este endpoint para sincronizar os status sent, delivered, read e failed com o seu banco de dados.

GET /api/v1/messages/status
GET https://api.covercut.com.br/api/v1/messages/status

Parâmetros de Query

ParâmetroTipoDescrição
wamidstringID único da mensagem (WAID).
statusstringFiltra por: sent, delivered, read ou failed.
limitintegerQuantidade por página (Padrão 50, Máx 100).
Exemplo de Resposta — 200 OK
{
  "success": true,
  "messages": [
    {
      "wamid": "wamid.HBgLNTUxMTk5OTk5OTk5...",
      "status": "read",
      "recipient": "5511999990000",
      "created_at": "2025-01-10 14:32:00"
    }
  ]
}

GET Exportar Logs (CSV)

Gere e baixe um arquivo .csv completo contendo o histórico de mensagens, facilitando a importação em ferramentas de BI, ERPs ou CRMs para retenção própria.

GET /api/v1/messages/export
GET https://api.covercut.com.br/api/v1/messages/export

Parâmetros de Query Opcionais

ParâmetroTipoDescrição
statusstringFiltra por: sent, delivered, read ou failed.
fromstringFiltra pelo número de origem que enviou a mensagem.
recipientstringFiltra pelo telefone de destino.
sincestringData de início. Formato YYYY-MM-DD (Ex: 2026-05-01).
untilstringData final. Formato YYYY-MM-DD (Ex: 2026-05-31).
Exemplo de Requisição (cURL)
curl -X GET "https://api.covercut.com.br/api/v1/messages/export?since=2026-05-01&until=2026-05-31" \
     -H "X-API-Key: sua-chave-api" \
     -H "X-API-Secret: seu-secret-api" \
     --output logs_maio.csv

Gestão de Templates

Crie, gerencie e envie templates de mensagem aprovados pela Meta.

Enviar Template

Inicie conversas com mensagens pré-aprovadas. Use to (telefone) ou recipient (BSUID) como destino.

Quando usar o campo components?

O campo components serve para preencher variáveis dinâmicas do seu template (exemplo: {{1}}, {{2}}) ou para enviar arquivos de mídia no cabeçalho.

  • Se o seu template for apenas um texto fixo (sem variáveis e sem arquivos), você não precisa enviar o components no JSON. Basta enviar apenas o nome e o idioma.
  • Se o seu template tiver variáveis no texto, você deve enviar o type: body preenchendo cada variável.
  • Se o seu template não tiver variáveis no texto, mas exigir um arquivo de imagem/vídeo/documento, você deve enviar apenas o type: header com o link/id do arquivo.

Template sem variáveis (texto fixo)

Quando o template não possui nenhuma variável ({{1}}, {{2}}…) nem cabeçalho de mídia, basta enviar o name e o language. O campo components é completamente opcional nesse caso.

POST /api/v1/messages/template (sem variáveis)
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "template",
  "template": {
    "name": "boas_vindas",
    "language": { "code": "pt_BR" }
  }
}

Template com variáveis no texto

Quando o template contém variáveis ({{1}}, {{2}}…), envie o componente body com os valores que substituirão cada variável, na mesma ordem.

POST /api/v1/messages/template (com variáveis)
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "template",
  "template": {
    "name": "confirmacao_pedido",
    "language": { "code": "pt_BR" },
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "João Silva" },
          { "type": "text", "text": "#4521" }
        ]
      }
    ]
  }
}

Templates com Mídia (Imagem/Vídeo/Documento)

Para templates que possuem cabeçalho de mídia, use o componente header. Se ele não tiver variáveis de texto, remova o bloco body do exemplo abaixo:

Exemplo: Template com Vídeo
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "template",
  "template": {
    "name": "video_promo",
    "language": { "code": "pt_BR" },
    "components": [
      {
        "type": "header",
        "parameters": [
          {
            "type": "video",
            "video": { "link": "https://suisite.com/video.mp4" }
          }
        ]
      },
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "Sandro" }
        ]
      }
    ]
  }
}

Templates com Botões Dinâmicos

Templates podem ter botões de Call to Action (Link/Telefone), Quick Reply ou Copy Code (copiar código).

Exemplo: Botão URL Dinâmico
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "template",
  "template": {
    "name": "confirmacao_agendamento",
    "language": { "code": "pt_BR" },
    "components": [
      {
        "type": "body",
        "parameters": [{ "type": "text", "text": "15/05 às 14h" }]
      },
      {
        "type": "button",
        "sub_type": "url",
        "index": 0,
        "parameters": [
          { "type": "text", "text": "agendar/id_123" }
        ]
      }
    ]
  }
}

Combinando Cabeçalho + Corpo + Botões (payload completo)

O caso mais comum de template promocional junta os três blocos no mesmo envio. Envie os componentes nesta ordem: headerbodybutton.

Regra de ouro: só inclua o componente que carrega dado dinâmico
  • Header de mídia: sempre entra no payload (o arquivo — imagem/vídeo — é passado no momento do envio via link ou id).
  • Body: só entra se o texto tiver variáveis ({{1}}, {{2}}…). Se o texto for estático, não envie o bloco body.
  • Botões: só entram os botões dinâmicos (quick_reply com payload, URL com sufixo variável, copy_code, payment_request). Botão totalmente estático (URL fixa, texto fixo) não precisa de componente — ele aparece sozinho.
  • O index do botão é base 0 e conta a posição do botão entre todos os botões do template (0, 1, 2…).
Texto estático + imagem + botões

O corpo é fixo, então não há bloco body. Entram o header (imagem) e apenas os botões dinâmicos — aqui, dois botões de resposta rápida (quick_reply). O payload é o texto que volta no webhook quando o cliente toca no botão.

Texto estático + imagem + botões (quick reply)
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "template",
  "template": {
    "name": "promo_com_imagem",
    "language": { "code": "pt_BR" },
    "components": [
      {
        "type": "header",
        "parameters": [
          { "type": "image", "image": { "link": "https://seusite.com/banner.jpg" } }
        ]
      },
      {
        "type": "button",
        "sub_type": "quick_reply",
        "index": 0,
        "parameters": [
          { "type": "payload", "payload": "QUERO_SABER_MAIS" }
        ]
      },
      {
        "type": "button",
        "sub_type": "quick_reply",
        "index": 1,
        "parameters": [
          { "type": "payload", "payload": "FALAR_COM_VENDEDOR" }
        ]
      }
    ]
  }
}

Se os botões forem URL/telefone fixos (sem variável), o payload fica com apenas o bloco header — nenhum bloco button é necessário.

Texto variável + imagem ou vídeo + botões

Aqui entram os três blocos: header (mídia), body (preenchendo as variáveis) e button (URL com sufixo dinâmico). Para vídeo, troque o parâmetro do header de image para video (mostrado logo abaixo).

Texto variável + imagem + botão URL dinâmico
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "template",
  "template": {
    "name": "promo_personalizada",
    "language": { "code": "pt_BR" },
    "components": [
      {
        "type": "header",
        "parameters": [
          { "type": "image", "image": { "link": "https://seusite.com/banner.jpg" } }
        ]
      },
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "João" },
          { "type": "text", "text": "20%" }
        ]
      },
      {
        "type": "button",
        "sub_type": "url",
        "index": 0,
        "parameters": [
          { "type": "text", "text": "produto/id_123" }
        ]
      }
    ]
  }
}

Mesmo payload com vídeo no cabeçalho — apenas o parâmetro do header muda:

Variação: cabeçalho de vídeo
{
  "type": "header",
  "parameters": [
    { "type": "video", "video": { "link": "https://seusite.com/promo.mp4" } }
  ]
}

Em vez de link, você pode usar { "id": "MEDIA_ID" } com o id de um arquivo já enviado via upload de mídia — evita a Meta baixar a URL a cada disparo.

Botão Copiar Código (Copy Code)

Permite que o cliente toque num botão e o código seja copiado automaticamente para a área de transferência — ideal para chaves PIX, cupons ou códigos de acesso.

Restrições confirmadas pela Meta: exclusivo para categoria MARKETING. O texto do botão é fixo ("Copiar código da oferta") e não pode ser customizado. A interface do Meta Business Manager não exibe essa opção — o template deve ser criado via nossa plataforma ou pela API. Não funciona no WhatsApp Web.
1. Criar o template (via nossa plataforma)

No dashboard, crie um template de categoria Marketing e adicione um botão "Copiar Código (Cupom)". O payload enviado à Meta será:

Criar template com botão COPY_CODE
{
  "from": "123456789012345",
  "name": "cupom_desconto",
  "category": "MARKETING",
  "language": "pt_BR",
  "components": [
    {
      "type": "BODY",
      "text": "Olá, {{1}}! Use o código abaixo para obter {{2}} de desconto.",
      "example": {
        "body_text": [["João", "20%"]]
      }
    },
    {
      "type": "BUTTONS",
      "buttons": [
        {
          "type": "COPY_CODE",
          "example": ["DESCONTO20"]
        }
      ]
    }
  ]
}
2. Enviar a mensagem

Após aprovação, passe o código real no parâmetro coupon_code. O parâmetro usa "type": "coupon_code" (não "text").

Enviar mensagem com botão Copiar Código
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "template",
  "template": {
    "name": "cupom_desconto",
    "language": { "code": "pt_BR" },
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "João" },
          { "type": "text", "text": "20%" }
        ]
      },
      {
        "type": "button",
        "sub_type": "copy_code",
        "index": 0,
        "parameters": [
          { "type": "coupon_code", "coupon_code": "DESCONTO20" }
        ]
      }
    ]
  }
}
Limitações: código limitado a 15 caracteres. Apenas 1 botão COPY_CODE por template. Não funciona no WhatsApp Web. A Meta pode rejeitar templates cujo conteúdo seja transacional (ex: cobrança PIX) — o botão é destinado a cupons e ofertas promocionais.

Templates de Solicitação de Pagamento (Brasil)

Permite que comerciantes solicitem pagamentos via PIX dinâmico, Boleto ou Link de pagamento diretamente na conversa do WhatsApp, sem necessidade da integração de Detalhes do Pedido. Disponível para categorias Marketing e Utilidade.

Vantagens: até 3 botões de pagamento por template (um de cada tipo); integração simplificada — o código/link real é enviado dinamicamente ao disparar a mensagem; combina com outros tipos de botões e com modelos de oferta por tempo limitado.

1. Criar o template

No dashboard selecione o botão "Solicitação de Pagamento (BR)" e escolha o tipo. O texto do botão é fixado pela Meta conforme o tipo escolhido.

TipoTexto fixo do botãoCampo obrigatório no envio
pix_dynamic_codeCopy Pix codepix_dynamic_code.code
boletoCopy Boleto codeboleto.digitable_line
payment_linkOpen payment linkpayment_link.uri
Criar template com 3 botões de pagamento
{
  "from": "123456789012345",
  "name": "cobranca_pagamento",
  "category": "UTILITY",
  "language": "pt_BR",
  "components": [
    {
      "type": "BODY",
      "text": "Olá, {{1}}! Sua fatura de R$ {{2}} está disponível. Escolha a forma de pagamento:"
    },
    {
      "type": "BUTTONS",
      "buttons": [
        {
          "type": "PAYMENT_REQUEST",
          "text": "Copy Pix code",
          "payment_setting": {
            "type": "pix_dynamic_code",
            "pix_dynamic_code": { "code": "00020101021226700014br.gov.bcb.pix..." }
          }
        },
        {
          "type": "PAYMENT_REQUEST",
          "text": "Copy Boleto code",
          "payment_setting": {
            "type": "boleto",
            "boleto": { "digitable_line": "03399026944140000002628346101018898510000008848" }
          }
        },
        {
          "type": "PAYMENT_REQUEST",
          "text": "Open payment link",
          "payment_setting": {
            "type": "payment_link",
            "payment_link": { "uri": "https://exemplo.com/pagar/123" }
          }
        }
      ]
    }
  ]
}

2. Enviar a mensagem

O código/link real é passado nos parâmetros do botão com sub_type: "payment_request". O index corresponde à posição do botão (0, 1, 2).

Enviar mensagem com botões de pagamento
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "template",
  "template": {
    "name": "cobranca_pagamento",
    "language": { "code": "pt_BR" },
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "João" },
          { "type": "text", "text": "150,00" }
        ]
      },
      {
        "type": "button",
        "sub_type": "payment_request",
        "index": "0",
        "parameters": [{
          "type": "action",
          "action": {
            "payment_request": {
              "payment_setting": {
                "type": "pix_dynamic_code",
                "pix_dynamic_code": { "code": "00020101021226700014br.gov.bcb.pix..." }
              }
            }
          }
        }]
      },
      {
        "type": "button",
        "sub_type": "payment_request",
        "index": "1",
        "parameters": [{
          "type": "action",
          "action": {
            "payment_request": {
              "payment_setting": {
                "type": "boleto",
                "boleto": { "digitable_line": "03399026944140000002628346101018898510000008848" }
              }
            }
          }
        }]
      },
      {
        "type": "button",
        "sub_type": "payment_request",
        "index": "2",
        "parameters": [{
          "type": "action",
          "action": {
            "payment_request": {
              "payment_setting": {
                "type": "payment_link",
                "payment_link": { "uri": "https://exemplo.com/pagar/123" }
              }
            }
          }
        }]
      }
    ]
  }
}

Template Detalhes do Pedido (Brasil)

Template com formato especial ORDER_DETAILS que exibe itens do pedido, subtotal, impostos e opções de pagamento (PIX, Boleto, Link). Ideal para faturas e cobranças detalhadas. Disponível para categorias Marketing e Utilidade.

1. Criar o template

No dashboard selecione Formato: Detalhes do Pedido. O botão ORDER_DETAILS é adicionado automaticamente.

Criar template Order Details
{
  "from": "123456789012345",
  "name": "fatura_detalhada",
  "category": "UTILITY",
  "language": "pt_BR",
  "display_format": "ORDER_DETAILS",
  "components": [
    {
      "type": "HEADER",
      "format": "DOCUMENT",
      "text": "Sua Fatura"
    },
    {
      "type": "BODY",
      "text": "Olá, {{1}}! Segue sua fatura. Escolha a forma de pagamento."
    },
    {
      "type": "BUTTONS",
      "buttons": [
        { "type": "ORDER_DETAILS", "text": "Ver detalhes do pedido" }
      ]
    }
  ]
}

2. Enviar a mensagem

O payload de envio inclui os itens do pedido, valores e o código de pagamento no componente do botão com sub_type: "order_details". Os valores usam offset: 100 (centavos).

Enviar mensagem Order Details com PIX dinâmico
{
  "from": "123456789012345",
  "to": "5547999999999",
  "type": "template",
  "template": {
    "name": "fatura_detalhada",
    "language": { "code": "pt_BR" },
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "João" }
        ]
      },
      {
        "type": "button",
        "sub_type": "order_details",
        "index": 0,
        "parameters": [{
          "type": "action",
          "action": {
            "order_details": {
              "reference_id": "PEDIDO-001-2026",
              "type": "digital-goods",
              "payment_type": "br",
              "payment_settings": [{
                "type": "pix_dynamic_code",
                "pix_dynamic_code": {
                  "code": "00020101021226700014br.gov.bcb.pix...",
                  "merchant_name": "Empresa LTDA",
                  "key": "39580525000189",
                  "key_type": "CNPJ"
                }
              }],
              "currency": "BRL",
              "total_amount": { "value": 15000, "offset": 100 },
              "order": {
                "status": "pending",
                "items": [{
                  "retailer_id": "PROD-001",
                  "name": "Plano Mensal",
                  "amount": { "value": 15000, "offset": 100 },
                  "quantity": 1
                }],
                "subtotal": { "value": 15000, "offset": 100 },
                "tax": { "value": 0, "offset": 100, "description": "Sem impostos" }
              }
            }
          }
        }]
      }
    ]
  }
}
Offset: todos os valores monetários usam offset: 100 — ou seja, "value": 15000 = R$ 150,00. O campo reference_id deve ser único por pedido para rastreamento. Tipos de chave PIX aceitos: CNPJ, CPF, EMAIL, PHONE, RANDOM.

Enviar Template de Marketing

Endpoint dedicado (alias) para disparo de Custom Marketing Templates, com suporte a parâmetros nomeados.

POST /api/v1/messages/marketing
{
  "from": "123456789012345",
  "to": "5547999999999",
  "template": {
    "name": "oferta_especial_maio",
    "language": { "code": "pt_BR" },
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "parameter_name": "discount_code", "text": "BEMVINDO20" },
          { "type": "text", "parameter_name": "discount_amount", "text": "20%" }
        ]
      }
    ]
  }
}

Listar Templates da Meta

Consulte todos os templates de mensagem cadastrados na sua conta WABA diretamente da Meta. Este endpoint retorna o status de aprovação, categoria e componentes de cada template.

GET Listar Templates

Requer Autenticação

Este endpoint exige o envio do seu Token de API no cabeçalho da requisição (Authorization: Bearer SEU_TOKEN).

GET /api/v1/templates/list
GET https://api.covercut.com.br/api/v1/templates/list

Upload de Exemplo (Mídia)

A Meta exige que templates com cabeçalho de mídia (imagem, vídeo ou documento) possuam um arquivo de exemplo. Use este endpoint para obter o header_handle necessário para a criação do template.

POST Obter Handle

POST /api/v1/media/upload_handle
POST https://api.covercut.com.br/api/v1/media/upload_handle

Request Body (Multipart)

CampoTipoDescrição
filefileO arquivo de imagem/vídeo (Máx 5MB).
fromstringO phone_number_id que será dono do template.
Exemplo de Resposta — 200 OK
{
  "success": true,
  "header_handle": "h/4_C_A0B1C2D3E4F5G6H7I8J9K0L1M2N3O4P5Q6"
}

Criar Template

Envia um novo template de mensagem para análise da Meta. Você deve especificar a categoria (MARKETING ou UTILITY) e os componentes (HEADER, BODY, FOOTER, BUTTONS).

POST Criar Template

O endpoint de criação aceita variáveis tanto Posicionais (ex: {{1}}, {{2}}) quanto Nomeadas (ex: {{nome}}, {{pedido_id}}).

Limites e Regras da Meta
  • Tamanhos máximos: Cabeçalho (60 caracteres), Corpo (1024 caracteres), Rodapé (60 caracteres).
  • Formato de Variáveis Nomeadas: Apenas letras minúsculas, números e sublinhados (ex: {{customer_name}}). Letras maiúsculas ou espaços resultarão em erro.
  • Exemplos: Todo componente com variável precisa do campo example. O formato do exemplo muda caso use variáveis nomeadas.
POST /api/v1/templates/create
POST https://api.covercut.com.br/api/v1/templates/create

Exemplo Payload (Variáveis Posicionais - Padrão)

{
  "name": "boas_vindas",
  "category": "MARKETING",
  "language": "pt_BR",
  "components": [
    {
      "type": "BODY",
      "text": "Olá {{1}}, bem-vindo!",
      "example": {
        "body_text": [ ["João"] ]
      }
    }
  ]
}

Exemplo Payload (Variáveis Nomeadas)

Quando utilizar nomes nas variáveis, é obrigatório enviar "parameter_format": "NAMED" e o bloco example muda para um array de objetos.

{
  "name": "boas_vindas_nomeado",
  "category": "MARKETING",
  "language": "pt_BR",
  "parameter_format": "NAMED",
  "components": [
    {
      "type": "BODY",
      "text": "Olá {{nome_cliente}}, bem-vindo!",
      "example": {
        "body_text_named_params": [
          { "param_name": "nome_cliente", "example": "João" }
        ]
      }
    }
  ]
}

Criar Template de Marketing (Simplificado)

Versão simplificada para criação rápida de templates promocionais com suporte nativo a botões de CTA.

POST Criar Marketing

POST /api/v1/templates/marketing/create
{
  "name": "oferta_especial_maio",
  "language": "pt_BR",
  "components": [
    {
      "type": "BODY",
      "text": "Temos uma oferta especial para você!"
    }
  ]
}

Editar Template

Atualiza o conteúdo de um template existente. Note que templates em uso podem exigir nova análise da Meta após a edição.

POST Editar Template

POST /api/v1/templates/update
{
  "template_id": "111222333444555",
  "components": [
    {
      "type": "BODY",
      "text": "Novo texto do corpo do template"
    }
  ]
}

Excluir Template

Remove permanentemente um template da sua conta WABA.

DELETE Excluir

DELETE /api/v1/templates/delete
{
  "name": "nome_do_template_a_excluir"
}

Baixar Mídia

Use este endpoint para baixar arquivos recebidos via Webhook. A API resolve a autenticação com a Meta automaticamente.

GET Obter Mídia

Endpoint
GET /api/v1/media/get?id={media_id}&from={phone_number_id}
Autenticação Obrigatória: Mesmo sendo uma requisição GET, você deve enviar os headers X-API-Key e X-API-Secret.

Parâmetro from (Recomendado): Identificador do número que recebeu a mídia. Obrigatório se você gerencia múltiplos números para garantir o uso do token correto. Pode ser o phone_number_id ou o número completo.

Adicione &mode=stream para receber o arquivo binário direto (download).

POST Fazer Upload de Mídia

Use este endpoint para enviar um arquivo para os servidores da Meta. O upload permite que você use o media_id para enviar mensagens, o que é mais rápido e confiável que o uso de links externos.

Opção 1: Formulário (multipart/form-data)

POST /api/v1/media/upload
Content-Type: multipart/form-data

file: [arquivo físico]
from: [phone_number_id - obrigatório se tiver mais de um número]

Opção 2: JSON com Base64 (Ideal para IA)

Se você possui o conteúdo do arquivo em Base64 (comum em IAs de áudio), pode enviar diretamente via JSON:

POST /api/v1/media/upload
Content-Type: application/json

{
  "file_base64": "T2dnUwACAAAAAAAA...",
  "filename": "audio.ogg",
  "filetype": "audio/ogg",
  "from": "phone_number_id" // Obrigatório se tiver mais de um número
}
Resposta
{
  "success": true,
  "message": "Upload concluído com sucesso",
  "media_id": "8451871321564"
}

Integração com n8n

Como Fazer Upload de Arquivos (POST)

Se você utiliza o n8n e precisa fazer o upload de um arquivo gerado em nós anteriores (como áudios do ElevenLabs), configure o seu nó HTTP Request da seguinte maneira:

  • Method: POST
  • Send Body: Habilitado
  • Body Content Type: Form-Data (muito importante!)
  • Specify Body: Using Fields Below
Atenção para Múltiplos Números:

Se você tiver mais de um número conectado e estiver fazendo o envio de arquivos (imagem, áudio, vídeo ou PDF) pelo n8n, é obrigatório incluir o campo from no body. Isso é necessário para que o sistema saiba de qual número está sendo feito o upload para a Meta.

Em Body Parameters, adicione os seguintes campos:

Nome: file
Tipo (Type): n8n Binary Data / Binary File
Input Data Field Name: data (ou o nome da propriedade onde está o arquivo)

Nome: from (Obrigatório se tiver mais de um número)
Tipo (Type): Text
Value: Seu ID do Número

Como Baixar Arquivos (GET)

Configure o nó HTTP Request com o Method GET, inclua seus Headers de autenticação (X-API-Key) e marque a opção Response Format como File para o n8n extrair a mídia perfeitamente.

Gestão de Grupos

Gerencie grupos onde o seu número de negócio é administrador ou membro. Você pode listar grupos, criar novos e gerenciar links de convite.

Elegibilidade e Requisitos de Grupos:

A API de Grupos da Meta está disponível exclusivamente para contas comerciais oficiais (Official Business Account - OBA) na Cloud API tradicional. Ela NÃO está disponível para números que utilizam o aplicativo móvel WhatsApp Business ou que estão no modelo de Coexistência (Multi-solution Conversations).

Limites e Restrições Oficiais (Meta):
  • Capacidade: Máximo de 8 participantes por grupo.
  • Quantidade: Máximo de 10.000 grupos por número comercial.
  • Negócios: Apenas 1 número comercial Cloud API (WABA) por grupo.
  • Mensagens Não Suportadas: Chamadas (Calling), mensagens temporárias, visualização única (view-once), mensagens de autenticação, mensagens de comércio e mensagens interativas.
  • Ações Não Suportadas: Esconder lista de participantes por administradores, editar mensagens e deletar mensagens.
Fluxo de Convite (Invite-only):

Por políticas de privacidade da Meta, sistemas não podem adicionar usuários diretamente em grupos. Você deve seguir este fluxo:

  1. Crie o grupo usando o endpoint /api/v1/groups/create. A resposta do webhook conterá o evento group_lifecycle_update com o link de convite (invite_link).
  2. Crie um modelo de mensagem (Template) do tipo especial "Group invite upon request" no Gerenciador de Negócios e aguarde a aprovação da Meta.
  3. Envie esse template de convite para o usuário final via API informando os parâmetros do grupo (JID, nome e ícone).
  4. Quando o usuário aceitar o convite e entrar no grupo, o seu sistema receberá a confirmação através do webhook group_participants_update.

POST Criar Grupo

Cria um novo grupo no WhatsApp e define as configurações iniciais.

POST /api/v1/groups/create
{
  "from": "PHONE_NUMBER_ID", // Opcional
  "subject": "Nome do Grupo",
  "description": "Descrição do grupo (opcional)",
  "join_approval_mode": "auto_approve" // "auto_approve" ou "approval_required"
}

GET / POST Link de Convite

Obtenha ou resete o link de convite do grupo.

Obter Link — GET

GET /api/v1/groups/invite_link
GET /api/v1/groups/invite_link?group_id=GROUP_ID&from=PHONE_NUMBER_ID

Resetar Link — POST

POST /api/v1/groups/invite_link
{
  "from": "PHONE_NUMBER_ID", // Opcional
  "group_id": "ID_DO_GRUPO"
}

POST Enviar para Grupo

Funcionalidade oficial da Meta para comunicação em grupos. Envie mensagens de texto livre, arquivos ou templates aprovados. Lembre-se de definir recipient_type: group.

POST /api/v1/messages/send — Grupo (Texto)
{
  "from": "123456789012345",
  "recipient_type": "group",
  "to": "120363214587@g.us",
  "type": "text",
  "text": { "body": "Olá grupo!" }
}
POST /api/v1/messages/send — Grupo (Template de Convite)
{
  "from": "123456789012345",
  "recipient_type": "individual",
  "to": "5547999999999",
  "type": "template",
  "template": {
    "name": "seu_template_convite",
    "language": { "code": "pt_BR" },
    "components": [
      {
        "type": "body",
        "parameters": [
          {
            "type": "group_invite_link",
            "group_invite_link": {
              "group_jid": "120363214587@g.us",
              "group_name": "Grupo Oficial Covercut",
              "group_icon": "8451871321564"
            }
          }
        ]
      }
    ]
  }
}
Modelo de Faturamento de Grupos (PMP):

O envio de mensagens para grupos segue a precificação baseada em entrega individual (Per-Message Pricing):

  • Você é cobrado por cada mensagem que for efetivamente entregue a um participante do grupo (e não por um custo fixo único).
  • O valor unitário por participante segue a tabela correspondente do país e operadora do participante (código DDI).
  • Sem descontos de volume: Mensagens de utilidade para grupos (Group utility messages) não qualificam para faixas de desconto por volume comercial na Meta.
Janelas de Serviço em Grupos:

Diferente de conversas 1:1 onde cada usuário tem sua própria janela de 24h:

  • Se qualquer participante enviar uma mensagem no grupo, uma janela de serviço de 24h é aberta para todo o grupo.
  • Dentro dessa janela de 24h, você pode enviar mensagens de texto livre (freeform) e templates de utilidade para o grupo totalmente grátis.
  • Mensagens de Marketing e Autenticação são sempre pagas, mesmo que enviadas dentro da janela ativa.
Métricas de Performance de Templates:

A Meta não disponibiliza métricas de performance (como taxa de leitura ou entrega) para modelos de mensagens (Templates) que forem disparados em grupos. Se você precisar rastrear esses dados, crie templates separados e exclusivos para envios de grupos.

GET Listar Grupos

Retorna uma lista de todos os grupos em que o número de telefone do BSP é membro.

GET /api/v1/groups/list
GET /api/v1/groups/list

GET Informações do Grupo

Retorna os detalhes de um grupo (assunto, descrição, participantes, modo de aprovação, etc).

GET /api/v1/groups/info
GET /api/v1/groups/info?group_id=GROUP_ID&from=PHONE_NUMBER_ID

DELETE Excluir Grupo

Exclui o grupo permanentemente da sua conta do WhatsApp Business.

DELETE /api/v1/groups/delete
{
  "from": "PHONE_NUMBER_ID", // Opcional
  "group_id": "ID_DO_GRUPO"
}

Códigos de Erro de Grupos

Abaixo estão listados os códigos de erro específicos retornados pela Meta em operações da Groups API. Utilize esta referência para tratamento de exceções no seu sistema.

Código Erro / Status HTTP Descrição / Solução
131020 Bad Group (400) Não é possível enviar mensagens para grupos que possuem apenas 1 participante (ex: apenas o seu próprio número de negócio). Adicione mais membros antes de enviar mensagens.
131041 Group Unknown (400) O grupo especificado não foi encontrado. Certifique-se de que o group_id (JID) está correto ou se o seu número comercial ainda é membro desse grupo.
131059 Invalid Cursor (400) O cursor de paginação fornecido expirou ou é inválido. Reinicie a paginação da lista de grupos desde o início.
131201 Partial Success (206) A requisição de participantes obteve sucesso parcial. Verifique a lista detalhada de resposta para identificar quais operações ou números de telefone falharam.
131202 Duplicate Participant (400) Foram informados participantes duplicados no array de entrada. Remova as duplicatas da sua requisição.
131204 Participant Overlimit (400) O número de participantes excede o limite oficial permitido pela Meta (máximo de 8 participantes por grupo).
131207 Group Suspended (403) O grupo foi suspenso automaticamente pela Meta por violação das políticas de uso comercial do WhatsApp.
131208 Rate Limit Hit (429) O limite de operações de grupo por minuto do seu número foi atingido. Implemente um fluxo de backoff e reduza a frequência das requisições.
131209 Invalid Aspect Ratio (400) A proporção da imagem do ícone do grupo é inválida. A imagem deve ser estritamente quadrada (proporção 1:1).
131210 Image Too Small (400) A imagem enviada para o ícone do grupo é muito pequena. A largura e altura mínimas devem ser de 192px.
131211 Limit Reached (400) O limite de criação de grupos do seu número de telefone foi atingido (máximo de 10.000 grupos ativos).
131212 Not a Participant (400) O participante especificado não faz parte do grupo informado.
131213 Invalid Request (400) A solicitação de participação (join request) informada não existe ou já foi processada.
131214 Creation Disabled (400) A criação de grupos está temporariamente desativada para este número devido a alto volume de mensagens de marketing enviadas na janela de suporte nos últimos 7 dias.
131215 Not Eligible (400) O número de telefone não é elegível para utilizar a API de Grupos (ex: número em modo sandbox/teste, WhatsApp Business App móvel ou onboarded em modelo de coexistência). O número precisa ser uma Official Business Account (OBA).

Integração ChatWoot (Auto-Config)

Nossa integração oficial permite conectar seu número ao Chatwoot em segundos, sem a necessidade de ferramentas externas como n8n.

Estilo Evolution API: O sistema detecta suas configurações e cria automaticamente a Caixa de Entrada (Inbox) e os Webhooks necessários dentro do seu Chatwoot.

1. O que você precisa:

  • URL da Instância: Ex: https://chat.suaempresa.com
  • ID da Conta: O número que aparece após /accounts/ na URL do Chatwoot.
  • Token de Acesso: Encontrado em Configurações de Perfil > Access Token no seu Chatwoot.

2. Ativando a Integração:

  1. Acesse seu Dashboard no BSP → Meus Números.
  2. Clique em Configurar ChatWoot no número desejado.
  3. Preencha os dados e clique em [ Conectar e Configurar ].
URL que o sistema usará para o Webhook do Chatwoot
https://api.covercut.com.br/api/adapters/chatwoot.php

O BSP configurará essa URL automaticamente no seu Chatwoot. Sempre que um atendente responder por lá, nós receberemos a notificação e enviaremos para o WhatsApp do cliente.

Como Funciona o Fluxo

Sentido Ação do Sistema
WhatsApp → Chatwoot Quando o cliente manda um "Oi", o BSP cria o contato e a conversa no Chatwoot e empurra a mensagem via API.
Chatwoot → WhatsApp Quando o atendente responde no Chatwoot, ele dispara o Webhook para nosso adapter, que envia para a Meta.

Sincronizar Envios via API

Por padrão, mensagens enviadas via API (como notificações automáticas ou bots externos) não aparecem no Chatwoot, pois o Chatwoot só recebe eventos de mensagens que "passam" por ele ou chegam pelo Webhook.

Endpoint Sincronizado: Use este endpoint especial para garantir que mensagens enviadas pelo seu sistema também apareçam no histórico do Chatwoot.
POST /api/v1/messages/send_sync

Este endpoint aceita os mesmos parâmetros do /messages/send, mas realiza uma ação adicional:

  • Envia a mensagem ao cliente via WhatsApp.
  • Cria/Localiza a conversa no Chatwoot.
  • Insere a mensagem como "Saída" (Agent Message) no painel do Chatwoot.
Exemplo de Requisição Sincronizada
{
  "to": "5547999999999",
  "type": "text",
  "text": {
    "body": "Seu pedido #123 foi enviado! 🚚"
  }
}

Com isso, seus atendentes terão o histórico completo da conversa, incluindo as automações disparadas pelo seu sistema.

Contas SaaS (White-label)

Visão Geral

Estes endpoints permitem que você, como revendedor, crie e gerencie Contas SaaS (sub-contas) de forma automatizada — exatamente o que a tela Contas SaaS do seu dashboard faz, porém via API. É ideal para embutir a conexão de WhatsApp diretamente dentro do seu próprio produto.

Como funciona o fluxo
1. Seu sistema chama POST /api/v1/saas/create informando o nome do cliente e o limite de conexões.
2. A API devolve um direct_link (link de conexão white-label) e um integration_snippet (código pronto do botão).
3. Você coloca esse botão no seu SaaS. Ao clicar, o cliente final conecta o WhatsApp dele de forma isolada, dentro daquela sub-conta.

Autenticação e Escopo

Todos os endpoints de SaaS usam as suas credenciais de API (as mesmas dos endpoints de mensagens). A sub-conta criada fica automaticamente vinculada à sua conta, e você só consegue listar, alterar ou excluir sub-contas que pertençam a você.

Headers Requeridos
X-API-Key: sua_chave_de_api
X-API-Secret: seu_segredo_de_api
Content-Type: application/json
Segurança:

As credenciais são obrigatórias no cabeçalho HTTP (não é aceita sessão de navegador). Também se aplicam a whitelist de IP e o rate limit do seu plano, iguais aos demais endpoints da API.

POST Criar Conta SaaS

Cria uma nova sub-conta (cliente SaaS) e retorna os links de conexão prontos para uso. O único campo obrigatório é o company_name.

Parâmetros (JSON Body)
ParâmetroObrigatórioDescrição
company_nameSimNome do cliente/empresa SaaS. Máximo de 100 caracteres.
number_limitNãoMáximo de números que essa conta poderá conectar. Padrão 1. Não pode ultrapassar o limite disponível no seu plano.
logoNãoURL http(s) do logo exibido na página de conexão (white-label).
primaryNãoCor primária em hexadecimal (ex.: #25D366).
redirectNãoURL http(s) para onde o cliente é enviado após conectar com sucesso.
autostartNãotrue (padrão) abre o pop-up da Meta automaticamente ao carregar o link.
layoutNãopopup (padrão) ou full. Use popup ao embutir como botão.
Exemplo — cURL
curl -X POST https://api.covercut.com.br/api/v1/saas/create \
  -H "X-API-Key: sua_chave_de_api" \
  -H "X-API-Secret: seu_segredo_de_api" \
  -H "Content-Type: application/json" \
  -d '{
    "company_name": "Cliente Final do SaaS",
    "number_limit": 1,
    "logo": "https://seu-saas.com/logo.png",
    "primary": "#0A66C2",
    "redirect": "https://seu-saas.com/painel",
    "autostart": true,
    "layout": "popup"
  }'

Resposta

JSON — 200 OK
{
  "success": true,
  "message": "Cliente SaaS criado com sucesso!",
  "sub_customer_id": 118,
  "company_name": "Cliente Final do SaaS",
  "number_limit": 1,
  "token": "7a9af1b339abcf6395a28b92ef4fc25f...",
  "magic_link": "https://api.covercut.com.br/conectar.php?token=7a9af1b3...",
  "direct_link": "https://api.covercut.com.br/conectar.php?token=7a9af1b3...&autostart=1&logo=...&primary=%230A66C2&redirect=...&layout=popup",
  "integration_snippet": "function connectWhatsApp() { ... }"
}
Campos da Resposta
CampoTipoDescrição
sub_customer_idintID da sub-conta. Guarde-o: é usado para listar, ativar/inativar e excluir.
tokenstringToken de onboarding único do link de conexão.
magic_linkstringLink de conexão simples (sem personalização).
direct_linkstringLink de conexão white-label (com logo, cor, redirect e layout). É este que vira o botão no seu SaaS.
integration_snippetstringFunção JavaScript pronta que abre a conexão em pop-up e escuta o retorno de sucesso.

Embutindo o botão no seu SaaS

Cole a função recebida em integration_snippet na sua página e chame-a no clique de um botão. Ela abre o direct_link em pop-up e escuta o evento WA_CONNECT_SUCCESS quando o cliente termina a conexão.

HTML + JS — Botão de conexão
<button onclick="connectWhatsApp()">Conectar WhatsApp</button>

<script>
function connectWhatsApp() {
  const url = "COLE_AQUI_O_direct_link";
  const w = 550, h = 700;
  const left = (screen.width / 2) - (w / 2), top = (screen.height / 2) - (h / 2);
  window.open(url, "ConnectWhatsApp", "width=" + w + ",height=" + h + ",top=" + top + ",left=" + left);

  window.addEventListener("message", (event) => {
    if (event.data.type === "WA_CONNECT_SUCCESS") {
      console.log("Conectado!", event.data.customer_id);
      location.reload();
    }
  }, false);
}
</script>
Limite do plano:

Se a soma dos limites já alocados às suas contas SaaS ultrapassar o limite do seu plano, a criação retorna erro. Planos com excedente habilitado (overage) permitem ultrapassar, e o excedente é cobrado no fechamento do ciclo.

GET Listar Contas SaaS

Retorna todas as suas sub-contas, com o limite, o status e os números conectados de cada uma. Aceita GET ou POST.

Exemplo — cURL
curl https://api.covercut.com.br/api/v1/saas/list \
  -H "X-API-Key: sua_chave_de_api" \
  -H "X-API-Secret: seu_segredo_de_api"

Resposta

JSON — 200 OK
{
  "success": true,
  "clients": [
    {
      "id": 118,
      "name": "Cliente Final do SaaS",
      "number_limit": 1,
      "status": "active",
      "created_at": "2026-07-07 12:00:00",
      "pending_token": "7a9af1b3...",
      "numbers": [
        {
          "display_phone_number": "+55 47 99999-0001",
          "phone_number_id": "123456789012345",
          "status": "active"
        }
      ]
    }
  ]
}
Dica:

O campo id de cada item é o sub_customer_id usado nos endpoints de ativar/inativar e excluir. O pending_token aparece quando existe um link de conexão ainda não utilizado.

POST Ativar / Inativar Conta SaaS

Altera o status de uma sub-conta. Envie status explicitamente para definir o valor, ou omita-o para alternar entre ativo e inativo.

Parâmetros (JSON Body)
ParâmetroObrigatórioDescrição
sub_customer_idSimID da sub-conta (retornado em create / list).
statusNãoactive ou suspended. Se omitido, o status atual é invertido.
Exemplo — Inativar
curl -X POST https://api.covercut.com.br/api/v1/saas/status \
  -H "X-API-Key: sua_chave_de_api" \
  -H "X-API-Secret: seu_segredo_de_api" \
  -H "Content-Type: application/json" \
  -d '{ "sub_customer_id": 118, "status": "suspended" }'

Resposta

JSON — 200 OK
{
  "success": true,
  "message": "Cliente SaaS inativado com sucesso!",
  "sub_customer_id": 118,
  "status": "suspended"
}
Efeito:

Uma conta inativa (suspended) fica bloqueada, mas continua na sua lista e mantém o limite alocado. Para reativar, envie "status": "active".

POST Excluir Conta SaaS

Exclui uma sub-conta. É uma exclusão segura (soft-delete): os números vinculados são desconectados, o limite é liberado de volta ao seu plano e a conta some da sua lista.

Parâmetros (JSON Body)
ParâmetroObrigatórioDescrição
sub_customer_idSimID da sub-conta a ser excluída.
Exemplo — cURL
curl -X POST https://api.covercut.com.br/api/v1/saas/delete \
  -H "X-API-Key: sua_chave_de_api" \
  -H "X-API-Secret: seu_segredo_de_api" \
  -H "Content-Type: application/json" \
  -d '{ "sub_customer_id": 118 }'

Resposta

JSON — 200 OK
{
  "success": true,
  "message": "Cliente SaaS excluído com sucesso!",
  "sub_customer_id": 118
}
Atenção:

A exclusão desconecta imediatamente todos os números da sub-conta. A ação não pode ser desfeita — para conectar novamente, crie uma nova conta SaaS.

Códigos de Erro

HTTPSituação
400Parâmetro obrigatório ausente ou inválido (ex.: company_name vazio, URL de logo inválida, limite do plano excedido).
401Headers X-API-Key / X-API-Secret ausentes ou credenciais inválidas.
404Sub-conta não encontrada ou não pertence a você.
405Método HTTP não permitido para o endpoint.
429Limite de requisições do plano excedido. Aguarde 1 minuto.

Business-Scoped User IDs (BSUID) — Junho 2026

O WhatsApp introduz BSUID (Business-Scoped User ID): um identificador único por usuário-negócio que permite suporte a usernames (nomes de usuário), similar ao Instagram. O BSUID é adicionado aos webhooks — a Meta NÃO descontinua o número de telefone. O número continua presente quando o usuário não adotou um nome de usuário, ou quando se aplicam as condições de retrospectiva de 30 dias / lista de contatos. Ele é omitido apenas quando o usuário adota um nome de usuário e o número não pode ser incluído por essas condições.

Timeline

DataEventoImpacto
Abril 2026BSUIDs começam a aparecerWebhooks incluem from_user_id
29 Junho 2026Nome de usuário comercialEmpresas podem reservar/adotar username
Julho 2026API aceita BSUID em envio + botão REQUEST_CONTACT_INFOPode enviar para BSUID e/ou número
Número de telefone continua disponível. Ao enviar, você pode usar to (número) e/ou recipient (BSUID); se ambos forem enviados, o número tem precedência.

O que é um BSUID?

Exemplos de BSUID
US.13491208655302741918      ← Formato: CC. + até 128 alfanuméricos
US.ENT.11815799212886844830  ← BSUID principal (parent), prefixo CC.ENT.
joao.silva                   ← Username (exibido no app, após adoção)

Propriedades do BSUID

  • Único por negócio: Cada contato tem um BSUID diferente por empresa.
  • Persistente: Não muda mesmo se o usuário mudar de número ou desabilitar username.
  • Prefixado: Começa com código do país (ex: BR, US, ES).
  • Privado: A Meta garante privacidade — números não são expostos em BSUIDs.

Campos Novos nos Webhooks (Maio 2026+)

CampoLocalizaçãoTipoDescrição
from_user_idmessagesstringBSUID do remetente em mensagens inbound
recipient_user_idstatusesstringBSUID do destinatário em webhooks de status
to_user_idcallsstringBSUID do destinatário em eventos de chamada
to_parent_user_idcallsstringParent BSUID (para contexto de relacionamento)
user_idcontactsstringBSUID do contato
usernamecontactsstringNome de usuário WhatsApp do contato

Exemplo — Transição Junho 2026

Durante a transição, webhooks incluem ambos número e BSUID:

Webhook de Mensagem com Número + BSUID
{
  "from_number": "5547999999999",        ← número (omitido se username adotado e nº indisponível)
  "contact": {
    "wa_id": "5547999999999",            ← número (omitido se username adotado e nº indisponível)
    "user_id": "US.13491208655302741918", ← BSUID (novo!)
    "username": "joao.silva",            ← username (novo!)
    "name": "João Silva"
  }
}

Implementação Recomendada

Aceite BSUID como identificador, mantendo o número quando presente. O número não é descontinuado — apenas pode faltar para usuários com nome de usuário.
  1. Capture BSUID em webhooks:
    • Use user_id / from_user_id como identificador estável do contato
    • Mantenha o wa_id (número) quando vier — ele continua sendo enviado na maioria dos casos
  2. Armazene username: Novos contatos incluem username — capture para exibição amigável
  3. Envio de mensagens: Use to (número) e/ou recipient (BSUID). Com ambos, o número tem precedência.
  4. Solicite o número quando precisar: Se o usuário ocultou o número, peça-o com o botão REQUEST_CONTACT_INFO (abaixo).

Solicitar o número do usuário — REQUEST_CONTACT_INFO (Julho 2026)

Quando um usuário adota nome de usuário, o número pode não vir nos webhooks. Para pedi-lo, use o botão REQUEST_CONTACT_INFO. Ao tocar, o usuário compartilha o número e dispara um webhook de contacts com o telefone (e o vcard, se ele compartilhar um contato diretamente).

O texto do botão é opcional, o rótulo não é personalizável e o botão não leva parâmetros ao disparar o template.

Como mensagem interativa

POST /api/v1/messages/send
{
  "to": "5547999999999",            // ou "recipient": "<BSUID>"
  "type": "interactive",
  "interactive": {
    "type": "request_contact_info",
    "body": { "text": "Para concluir, compartilhe seu número:" },
    "action": { "name": "request_contact_info" }
  }
}

Como botão de template (utility/marketing)

Inclua o botão na criação do template (POST /api/v1/templates). No envio do template, não passe parâmetros para esse botão.

Componente de botão no template
{
  "type": "buttons",
  "buttons": [
    { "type": "REQUEST_CONTACT_INFO", "text": "Compartilhar contato" }
  ]
}

Webhook recebido ao compartilhar o contato

Evento de contacts
{
  "event": "message",
  "message": {
    "type": "contacts",
    "from_user_id": "US.13491208655302741918",
    "contacts": [
      {
        "origin": "contact_request",   // ou "other" (compartilhou um contato direto)
        "vcard": "...",                // presente só quando origin = "other"
        "phones": [
          { "phone": "+5547999999999", "wa_id": "5547999999999", "type": "..." }
        ]
      }
    ]
  }
}

Nome de usuário comercial — API (Julho 2026)

Reserve, consulte e remova o nome de usuário comercial (@) de um número. O nome de usuário não oculta o número da empresa no app. Endpoints autenticados com X-API-Key / X-API-Secret; parâmetro opcional from = phone_number_id (padrão: primeiro número ativo).

Método / EndpointDescrição
GET /api/v1/usernameRetorna { username, status } (status: approved ou reserved).
POST /api/v1/usernameAdota/altera. Corpo: { "username": "...", "transfer_action": "none|force_transfer" }. Use force_transfer para mover um nome já usado em outro número do seu portfólio (erro 147005 sem ele).
DELETE /api/v1/usernameRemove o nome de usuário do número.
GET /api/v1/username_suggestionsLista os nomes reservados para você (maior chance de aprovação).
POST /api/v1/username
{
  "from": "<phone_number_id>",     // opcional
  "username": "minhaempresa",
  "transfer_action": "none"           // ou "force_transfer"
}

// Resposta: { "success": true, "username": "minhaempresa", "status": "reserved" }

Regras do nome: 3–35 caracteres, apenas letras (a-z), dígitos, ponto e sublinhado; pelo menos uma letra; sem acentos; não começa/termina com ponto nem tem dois pontos seguidos; não começa com www. O status muda de reserved para approved quando o recurso é liberado (acompanhe pelo webhook business_username_updates).

Listar Números Conectados

Retorna todos os números WhatsApp conectados à sua conta. Use este endpoint para descobrir o phone_number_id de cada número — esse é o valor que você passa no campo from ao enviar mensagens.

GET /api/v1/numbers/list
Quando usar?

Ideal para automatizações que precisam descobrir o phone_number_id correto sem acessar o painel. Basta fazer essa chamada uma vez e armazenar os IDs na sua aplicação.

Exemplo de Uso (cURL)
curl --request GET \
  --url 'https://api.covercut.com.br/api/v1/numbers/list' \
  --header 'X-API-Key: sua_api_key' \
  --header 'X-API-Secret: seu_api_secret'
Exemplo de Resposta
{
  "success": true,
  "data": {
    "count": 2,
    "numbers": [
      {
        "phone_number_id": "123456789012345",
        "display_phone_number": "+55 47 99999-0001",
        "status": "active",
        "quality_rating": "GREEN",
        "phone_tier": "TIER_1K",
        "connected_at": "2026-01-10 09:00:00"
      },
      {
        "phone_number_id": "987654321098765",
        "display_phone_number": "+55 81 91234-5678",
        "status": "active",
        "quality_rating": "YELLOW",
        "phone_tier": "TIER_250",
        "connected_at": "2026-03-22 14:30:00"
      }
    ]
  },
  "message": "Números listados com sucesso."
}
Campos da Resposta
CampoTipoDescrição
phone_number_idstringID da Meta. Use como valor de from nos endpoints de envio.
display_phone_numberstringNúmero formatado para exibição (ex: +55 47 99999-0001).
statusstringactive, suspended ou disconnected.
quality_ratingstringAvaliação de qualidade: GREEN, YELLOW ou RED.
phone_tierstringLimite de templates diários: TIER_50, TIER_250, TIER_1K, TIER_10K, TIER_100K.
connected_atstringData e hora em que o número foi conectado.

Consultar Status do Número

Utilize este endpoint para consultar, em tempo real, a avaliação de qualidade de saúde do seu número e o status da conexão diretamente nos servidores da Meta.

GET /api/v1/numbers/status
Parâmetros de Consulta (Query String / JSON Body)
Parâmetro Obrigatório Descrição
from Sim O ID do número de telefone (Phone Number ID) que deseja consultar. Pode ser passado via query string (GET) ou no corpo JSON (POST).
Exemplo de Uso (cURL)
curl --request GET \
  --url 'https://api.covercut.com.br/api/v1/numbers/status?from=SEU_PHONE_NUMBER_ID' \
  --header 'X-API-Key: sua_api_key' \
  --header 'X-API-Secret: seu_api_secret'
Exemplo de Uso (POST com JSON)
curl --request POST \
  --url 'https://api.covercut.com.br/api/v1/numbers/status' \
  --header 'Content-Type: application/json' \
  --header 'X-API-Key: sua_api_key' \
  --header 'X-API-Secret: seu_api_secret' \
  --data '{
    "from": "SEU_PHONE_NUMBER_ID"
}'
Exemplo de Resposta
{
  "success": true,
  "data": {
    "phone_number_id": "123456789012345",
    "display_phone_number": "5547999999999",
    "status": "CONNECTED",
    "quality_rating": "GREEN",
    "name_status": "APPROVED",
    "connected_at": "2026-05-15 10:00:00"
  },
  "message": "Status recuperado com sucesso."
}

Nome de Usuário Comercial (API)

Gerencie o nome de usuário (@) comercial dos seus números diretamente pela API — ideal para quem usa sistema próprio. Os mesmos recursos estão na tela Nome de Usuário do painel. Disponível a partir de julho/2026 (reserva/adoção desde 29/jun/2026).

Importante

O nome de usuário comercial não oculta o número de telefone da empresa no app. O parâmetro from (phone_number_id) é opcional em todos os endpoints — se omitido, usamos o primeiro número ativo da conta.

Reservar / Adotar

POST /api/v1/username
Parâmetros (corpo JSON)
ParâmetroObrigatórioDescrição
usernameSim3–35 caracteres; apenas letras (a-z), dígitos, ponto e sublinhado; ao menos uma letra; sem acentos; não começa/termina com ponto; não começa com www.
transfer_actionNãonone (padrão) ou force_transfer para transferir um nome já usado em outro número do seu portfólio (sem isso, retorna erro 147005).
fromNãophone_number_id do número alvo.
Exemplo de Uso (cURL)
curl --request POST \
  --url 'https://api.covercut.com.br/api/v1/username' \
  --header 'Content-Type: application/json' \
  --header 'X-API-Key: sua_api_key' \
  --header 'X-API-Secret: seu_api_secret' \
  --data '{
    "username": "minhaempresa",
    "transfer_action": "none"
}'
Exemplo de Resposta
{
  "success": true,
  "message": "Nome de usuário definido",
  "from": "123456789012345",
  "username": "minhaempresa",
  "status": "reserved"
}

status: reserved (reservado e aprovado, ainda não visível) ou approved (visível aos usuários do WhatsApp). Acompanhe a mudança pelo webhook business_username_updates.

Consultar nome atual

GET /api/v1/username
curl --request GET \
  --url 'https://api.covercut.com.br/api/v1/username?from=SEU_PHONE_NUMBER_ID' \
  --header 'X-API-Key: sua_api_key' \
  --header 'X-API-Secret: seu_api_secret'
{ "success": true, "from": "123456789012345", "username": "minhaempresa", "status": "approved" }

Sugestões reservadas

Lista os nomes que o WhatsApp reservou para o seu portfólio — têm maior chance de aprovação.

GET /api/v1/username_suggestions
{ "success": true, "from": "123456789012345", "suggestions": ["minhaempresa", "minhaempresa.oficial"] }

Remover

DELETE /api/v1/username
curl --request DELETE \
  --url 'https://api.covercut.com.br/api/v1/username?from=SEU_PHONE_NUMBER_ID' \
  --header 'X-API-Key: sua_api_key' \
  --header 'X-API-Secret: seu_api_secret'
{ "success": true, "from": "123456789012345", "deleted": true }
Erros específicos
Código MetaSignificado
147001Nome indisponível (já reivindicado ou reprovado). Tente outro.
147002Conta não qualificada — precisa de um limite de mensagens maior.
147003 / 147004É preciso vincular o número à Página do Facebook / conta do Instagram que já usa o nome.
147005Nome em uso em outro número do portfólio — reenvie com transfer_action: "force_transfer".
133010Número ainda não registrado para uso com a API.

Códigos de Erro

CódigoDescrição
400Requisição inválida ou parâmetros faltando.
401Credenciais inválidas ou expiradas.
429Rate limit excedido.
500Erro interno no servidor.

Rate Limiting

  • Plano Básico: 60 requisições/min.
  • Plano Pro: 180 requisições/min.

Suporte

Email: suporte@covercut.com.br
WhatsApp: (47) 99618-1954

Changelog

Histórico completo de atualizações, melhorias e correções da API.

Novo v1.6.0 30 Jun 2026
  • Correção
    Esclarecimento: o número de telefone NÃO é descontinuado — A documentação anterior dizia que a partir de 01/07/2026 a Meta enviaria "apenas BSUID". Isso está incorreto: o BSUID é adicionado aos webhooks e o número continua presente quando o usuário não adotou nome de usuário (ou pelas condições de 30 dias / lista de contatos). Ao enviar, você pode usar to (número) e/ou recipient (BSUID) — o número tem precedência.
  • Novo
    Botão REQUEST_CONTACT_INFO — Novo tipo interativo request_contact_info (e botão de mesmo nome em templates) para solicitar o número de telefone de um usuário que adotou nome de usuário. Ao compartilhar, chega um webhook type: "contacts" com o telefone (e vcard quando o usuário compartilha um contato direto). O texto é opcional, o rótulo não é personalizável e o botão não leva parâmetros no envio.
  • Novo
    Nome de usuário comercial (Business Username) — Novos endpoints GET/POST/DELETE /api/v1/username (com transfer_action) e GET /api/v1/username_suggestions para reservar, consultar e remover o @ do seu número. Também disponível na tela Nome de Usuário do painel.
  • Novo
    Novos eventos de webhookuser_id_update (BSUID do usuário mudou — atualize seu CRM via previouscurrent), business_username_updates (status do seu nome de usuário: reserved/approved/deleted) e user_preferences (opt-in/out de marketing). Inscreva os campos no Painel de Apps da Meta para recebê-los.
  • Melhoria
    Campos aditivos nos webhookscontact.parent_user_id / status.recipient_parent_user_id (Parent BSUID, multi-portfólio) e status.username em entregue/lido. Todos aditivos — só aparecem quando presentes, sem alterar o formato existente.
  • Melhoria
    Integração Chatwoot compatível com usuários só-username — O envio pelo Chatwoot agora reconhece destinatários BSUID (sem número) e usa o campo correto na API da Meta. O comportamento para números de telefone permanece idêntico.
  • Melhoria
    Novos códigos de erro traduzidos131062 (BSUID não suportado em templates de autenticação) e 147001–147005/133010 (nome de usuário comercial).
Novo v1.5.1 19 Jun 2026
  • Novo
    Identificação da origem das respostas (echo) — Mensagens de saída agora trazem echo_source (api = Cloud API/Chatwoot/integração; phone = celular em coexistência) e message.agent_name. Respostas de atendentes pelo Chatwoot passam a incluir o nome do atendente em agent_name, permitindo distinguir resposta humana de resposta da IA/integração.
  • Melhoria
    Mensagens não suportadas (type: "unsupported") — O webhook agora repassa o bloco unsupported junto com o array message.errors (ex.: código 131051) quando a Meta o envia, deixando claro o motivo de a mensagem não ter sido entregue. Na integração com Chatwoot, esses casos (e também location, contacts, interactive e button) passaram a exibir rótulos legíveis em português em vez do tipo cru em inglês.
Novo v1.5.0 28 Mai 2026 — CRÍTICO
  • Novo
    Business-Scoped User IDs (BSUID) — Suporte Completo — A Meta passou a adicionar from_user_id e to_user_id (BSUID — identificadores únicos por usuário-negócio) aos webhooks; o número de telefone não é descontinuado e continua presente na maioria dos casos. Seu sistema funciona com ou sem número: quando não há from, usa-se o BSUID como identificador. Usernames WhatsApp (como Instagram) também são suportados. Envio direcionado a BSUID e botão REQUEST_CONTACT_INFO disponíveis a partir de julho/2026.
  • Novo
    WhatsApp Calling API — Webhooks de Chamadas de Voz — Implementado suporte nativo aos eventos de chamadas (voice calls). Quando usuários ligam para seu número, você recebe webhook com event: "call" contendo call_id, status (incoming, connected, ended, missed, rejected), duration_seconds, além de BSUID e username do chamador. Webhook inclui estrutura completa com nome, username e dados de contato.
  • Novo
    Rastreamento de Origem — Facebook Ads & Referral — Adicionados 5 novos campos para capturar origem de mensagens via Facebook Ads: referral_source_type (ex: "ad"), referral_source_id (ID da campanha), referral_source_url, referral_headline (copy do anúncio) e referral_ctwa_clid. Permite rastreamento de ROI por campanha. Webhook do cliente inclui campo referral completo quando aplicável.
  • Novo
    Documentação Atualizada — Junho 2026 — Adicionada seção completa sobre BSUID e transição para identificação por username. Documentação de webhooks expandida com exemplos de Calling API e referral. Nova página de status com changelog detalhado de implementação e checklist de testes.
  • Melhoria
    Echo Detection Aprimorado — Corrigida lógica de detecção de echo (mensagens de saída recebidas como webhook) para funcionar corretamente quando há apenas BSUID sem número de telefone. Sistema agora suporta transição dual (número + BSUID simultâneos) até julho de 2026.
Novo v1.4.8 21 Mai 2026
  • Novo
    Exportação Programática de Logs CSV via API — Disponibilizado novo endpoint nativo GET /api/v1/messages/export que permite aos clientes e contas SaaS exportarem relatórios completos de histórico bruto em arquivo CSV. Este recurso permite filtrar via query params e facilita a automação de backup (via webhook/cron, n8n ou Make) transferindo o controle do armazenamento a longo prazo diretamente para o cliente.
Novo v1.4.7 20 Mai 2026
  • Novo
    Sistema Multi-Usuário (Equipes) com Controle de Acesso (RBAC) — Implementada aba "Gerenciar Equipe" permitindo adicionar e gerenciar colaboradores com perfis dedicados: admin (acesso total), developer (chaves de API, webhooks e Chatwoot, ocultando áreas financeiras/segurança) e viewer (perfil de apenas leitura com bloqueio de requisições POST).
  • Novo
    Fila e Logs de Entrega de Webhooks — Criada fila de reprocessamento e auditoria persistente de webhooks (bsp_webhook_queue) com rotina de limpeza automatizada (24h de retenção para envios normais e 48h para falhas de rede) e controle de reenvio síncrono.
  • Novo
    Rate Limit Centralizado — Implementado motor global de controle de limites de requisições por rota baseada na tabela bsp_rate_limits, garantindo estabilidade e impedindo abusos nas APIs de mensageria.
  • Melhoria
    Otimizações de Concorrência e Rate Limit na Coexistência — Resolução do erro (#4) Application request limit reached da Meta nos endpoints de sincronização de coexistência. O sistema agora executa um atraso seguro entre as chamadas e gerencia localmente uma trava de 10 minutos (HTTP 429), evitando desperdício de cota da API da Meta.
  • Correção
    Autenticação Híbrida e Resiliência de Migração DDL — Resolvido erro de banco de dados causado por chaves de API migradas em tabelas herdadas (antigas) de chaves de API. O motor de migração em app/db.php agora valida a existência de cada coluna de forma granular no MySQL. Adicionado suporte a autenticação por sessão em validateApiRequest, permitindo que chamadas do próprio painel (como carregamento de templates e mídia) funcionem de maneira transparente e segura usando o cookie de sessão do usuário ativo, corrigindo a "Falha de comunicação".
Novo v1.4.6 20 Mai 2026
  • Novo
    Reconexão de Coexistência (account_update) — Suporte nativo aos novos eventos de reconexão e offboarding (ACCOUNT_OFFBOARDED e ACCOUNT_RECONNECTED) da Meta para clientes em modo Coexistence. Isso permite que softwares parceiros pausem disparos e previnam falhas durante trocas de dispositivo.
Novo v1.4.5 19 Mai 2026
  • Novo
    Suporte à API de Grupos da Meta (Maio 2026) — Habilitados novos eventos de webhooks para controle de grupos (group_lifecycle_update, group_participants_update, etc.). Adicionado o repasse de metadados de precificação PMP (Per-Message Pricing) nos webhooks de status. Documentação de grupos atualizada com as novas diretrizes da Meta.
Novo v1.4.4 19 Mai 2026
  • Novo
    Endpoint de Monitoramento de Número — Adicionado o endpoint GET /api/v1/numbers/status que permite aos clientes SaaS consultarem em tempo real a avaliação de qualidade (quality rating) e o status de conexão dos seus números direto da Graph API da Meta, com sincronização automática do banco de dados local.
Novo v1.4.3 18 Mai 2026
  • Novo
    Filtros Avançados de Busca para Administração — Adicionado um novo sistema unificado de pesquisa rápida nas telas administrativas de Clientes (Index), Números Conectados e Financeiro. Permite localizar clientes de forma instantânea por Nome, E-mail ou Nome da Empresa (e também por IDs de WABA/Telefone ou Número de Telefone na aba de Números), mantendo o estado da busca e do filtro de status persistentes durante a paginação de registros.
  • Novo
    Relatórios e Exportação Premium de Logs — Novo painel de relatório interativo no dashboard de logs, permitindo visualizar volumetria, taxas de conversão (entregues/lidos) e distribuição de erros consolidados. Inclusa exportação em planilha CSV (com BOM UTF-8) e relatórios executivos em formato PDF otimizados para impressão vetorial nativa com suporte a logomarca da empresa do cliente.
  • Novo
    Personalização de Perfil e Logotipo — Nova aba Perfil & Segurança adicionada ao menu lateral, permitindo que cada cliente configure o nome da empresa e insira a URL da logomarca oficial da sua marca, que é consumida e exibida de forma automática e personalizada (white-label) no cabeçalho de todos os relatórios PDF gerados.
  • Novo
    Página de Status do Sistema & Integração Meta — Nova página de status de alta performance (status.php) alimentada de forma automática pela API do UptimeRobot com sistema inteligente de cache de 60s para evitar rate-limits. Conta com linha do tempo de 30 dias de disponibilidade recente por serviço, painel de onboarding interativo para desenvolvedores e integração nativa com a central de monitoramento da Meta (metastatus.com) para acompanhamento da WhatsApp Cloud API.
  • Fix
    Relatório de Logs e Métricas de Sucesso — Corrigida a lógica de cálculo da taxa de sucesso que antes ignorava mensagens em status sent (Enviado), gerando dados imprecisos. Adicionada a capacidade da modal de exportação herdar e processar dinamicamente todos os filtros de pesquisa ativos da tela (Status, Direção, Tipo e Telefone) nas exportações de PDF e planilhas CSV.
  • Fix
    Mapeamento Completo de Erros da API da Meta — Expandida e refinada a tradução de erros oficiais da Meta no ecossistema BSP. Além de corrigir a tradução do erro 131042 (Cobrança/Pagamento), o tradutor agora possui mapeamento humanizado em português para erros de contato bloqueado (130403), formato de mídia incompatível (131053), templates não encontrados/pausados/suspensos (132001, 132015, 132016), limite de volume por segundo da Cloud API (130429), número de remetente inativo (131009), PIN incorreto de 2 etapas (133005), além de experimentos da Meta (130472) e limites de envio.
  • Novo
    Documentação Completa do Carrossel de Mídia — Adicionados exemplos completos de JSON para o endpoint POST /api/v1/messages/carousel, cobrindo carrosseis com botão de URL (CTA URL) e botões de resposta rápida (quick_reply). Tabela de parâmetros expandida com todos os campos do cartão (header, body, action) e exemplo de resposta de sucesso.
Novo v1.4.2 16 Mai 2026
  • Novo
    Documentação de Prévia de Links — Adicionada seção detalhada sobre o funcionamento e requisitos técnicos (Open Graph) para a exibição de prévias de links em mensagens de texto.
Novo v1.4.1 13 Mai 2026
  • Novo
    Suporte Explícito a Múltiplos Números — Documentação atualizada para incluir o parâmetro from em todos os exemplos de envio da API. Isso permite que clientes com mais de um número conectado escolham o canal de saída da mensagem usando o ID do telefone desejado.
Novo v1.4.0 13 Mai 2026
  • Novo
    Envio de Stickers (Figurinhas) — Adicionado suporte ao tipo de mensagem sticker no endpoint POST /api/v1/messages/send, permitindo o envio de figurinhas dinâmicas por link ou ID.
Novo v1.3.0 12 Mai 2026
  • Novo
    Suporte a Respostas Citadas (Reply) via Chatwoot — Ao usar o botão Responder em uma conversa no Chatwoot, a mensagem agora chega no WhatsApp do cliente citando corretamente a mensagem original, igual ao app nativo do WhatsApp.
  • Novo
    Campo context no endpoint de envio — Os endpoints POST /api/v1/messages/send e /send_sync aceitam agora o campo opcional context.message_id para citar uma mensagem ao enviar via API.
    {
      "to": "5511999998888",
      "type": "text",
      "text": { "body": "Olá!" },
      "context": { "message_id": "wamid.HBgM..." }
    }
  • Fix
    Verificação de duplicidade no adapter Chatwoot — Corrigida a lógica que bloqueava indevidamente mensagens enviadas pelo botão Responder do Chatwoot, fazendo com que não chegassem ao WhatsApp.
Fix v1.2.1 11 Mai 2026
  • Fix
    Upload de mídia para Templates com cabeçalho de imagem — Corrigido o fluxo de duas etapas para upload de mídia na criação de templates, resolvendo o erro de "invalid media handle" ao usar token do sistema.
  • Fix
    Persistência de configurações Chatwoot — Resolvido problema onde as configurações da integração com Chatwoot eram perdidas após salvar.
Novo v1.2.0 08 Mai 2026
  • Novo
    Botão de URL (CTA URL) — Suporte ao tipo de mensagem interativa cta_url para enviar botões com link externo.
  • Novo
    Gestão de Templates via Dashboard — Interface completa para criar, editar, visualizar e excluir templates diretamente pelo painel, com suporte a mídia, botões e rodapé.
  • Novo
    Paginação no Painel Admin — Listas de clientes, números e financeiro passaram a usar paginação para melhorar a performance com grande volume de dados.
Novo v1.1.0 04 Mai 2026
  • Novo
    Integração nativa com Chatwoot — Sincronização bidirecional completa: mensagens recebidas do WhatsApp aparecem automaticamente no inbox do atendente, e mensagens enviadas pelo Chatwoot são entregues pelo WhatsApp sem configuração extra.
  • Novo
    Webhook de Alertas — Endpoint dedicado para receber notificações de eventos críticos (falha de entrega, número suspenso, etc.) separado do webhook principal de mensagens.
  • Fix
    Configuração de Webhook — Corrigido erro 500 ao salvar ou atualizar configurações de webhook no dashboard.
Launch v1.0.0 Abril 2026
  • Lançamento inicial da plataforma WhatsApp API Connect
  • Envio de texto, imagem, vídeo, áudio, documento, localização, contato, reação
  • Mensagens interativas (lista e botões) e templates aprovados pela Meta
  • Recebimento via webhook com rastreamento de status de entrega
  • Rate limiting, dashboard de gerenciamento e suporte a grupos (Oficial)
  • BSUID para identificação de usuários sem número de telefone