docs / api-connect
Voltar ao Dashboard

Documentação da API

Bem-vindo à API do WhatsApp Connect. Nossa API permite integrar o WhatsApp Business Cloud diretamente no seu sistema para enviar mensagens, receber atualizações e gerenciar conversas.

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 — 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.

1
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 2 — 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.

1
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.

Início Rápido

Base URL

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

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

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).

Enviar por número de telefone
{
  "to": "5547999999999",
  "type": "text",
  "text": {
    "body": "Olá! Como posso ajudar?"
  }
}
Enviar por BSUID (a partir de maio/2026)
{
  "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"  // presente quando disponível
}

POST Enviar Imagem

POST /api/v1/messages/send
{
  "to": "5547999999999",
  "type": "image",
  "image": {
    "link": "https://exemplo.com/imagem.jpg",
    "caption": "Legenda da imagem"
  }
}

POST Enviar Vídeo

POST /api/v1/messages/send
{
  "to": "5547999999999",
  "type": "video",
  "video": {
    "link": "https://exemplo.com/video.mp4",
    "caption": "Legenda opcional"
  }
}

POST Enviar Áudio

POST /api/v1/messages/send
{
  "to": "5547999999999",
  "type": "audio",
  "audio": {
    "link": "https://exemplo.com/audio.mp3"
  }
}

POST Enviar Documento

POST /api/v1/messages/send
{
  "to": "5547999999999",
  "type": "document",
  "document": {
    "link": "https://exemplo.com/arquivo.pdf",
    "filename": "documento.pdf"
  }
}

POST Enviar Localização

POST /api/v1/messages/send
{
  "to": "5547999999999",
  "type": "location",
  "location": {
    "latitude": -26.9195,
    "longitude": -49.0661,
    "name": "Covercut",
    "address": "Rua Exemplo, 123"
  }
}

POST Enviar Contato

POST /api/v1/messages/send
{
  "to": "5547999999999",
  "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
{
  "to": "5547999999999",
  "type": "reaction",
  "reaction": {
    "message_id": "wamid.xxx",
    "emoji": "👍"
  }
}

POST Enviar Mensagem Interativa

Crie uma experiência dinâmica com menus de lista ou botões de resposta rápida.

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
{
  "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" } }
      ]
    }
  }
}

1. Menu de Lista (List Message)

POST /api/v1/messages/send
{
  "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" }
          ]
        }
      ]
    }
  }
}

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

POST /api/v1/messages/send
{
  "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 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"
}
Marcar como lida sem indicador de digitação
Atualmente não existe um endpoint separado apenas para marcar como lida. Chame /typing sempre que quiser que o remetente veja os tiques azuis — o indicador de digitação some automaticamente após alguns segundos ou quando você enviar a próxima mensagem.

POST Enviar Template

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

POST /api/v1/messages/template
{
  "to": "5547999999999",
  "type": "template",
  "template": {
    "name": "nome_do_template",
    "language": { "code": "pt_BR" },
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "Nome Cliente" }
        ]
      }
    ]
  }
}

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

Para templates que possuem cabeçalho de mídia, use o componente header:

Exemplo: Template com Vídeo
{
  "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) ou Quick Reply.

Exemplo: Botões Variáveis
{
  "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" }
        ]
      }
    ]
  }
}

POST Enviar Template de Marketing

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

POST /api/v1/messages/marketing
{
  "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%" }
        ]
      }
    ]
  }
}

POST Enviar para Grupo (Oficial)

Funcionalidade oficial da Meta (novembro/2025) para comunicação em grupos. O campo recipient_type deve ser explicitamente definido como group.

POST /api/v1/messages/send — Mensagem de Texto em Grupo
{
  "messaging_product": "whatsapp",
  "recipient_type": "group",
  "to": "Y2FwaV9ncm91cDoxNzA1NTU1MDEzOToxMjAzNjM0MDQ2OTQyMzM4MjAZD", // ID do grupo oficial
  "type": "text",
  "text": {
    "preview_url": true,
    "body": "Olá grupo! Esta é uma mensagem de teste enviada via API Oficial."
  }
}

Exemplo: Envio de Mídia em Grupo (Imagem/Vídeo/Áudio/PDF)

POST /api/v1/messages/send — Imagem
{
  "recipient_type": "group",
  "to": "GROUP_ID_HERE",
  "type": "image",
  "image": {
    "link": "https://exemplo.com/imagem.jpg",
    "caption": "Imagem para o grupo"
  }
}
POST /api/v1/messages/send — PDF / Documento
{
  "recipient_type": "group",
  "to": "GROUP_ID_HERE",
  "type": "document",
  "document": {
    "link": "https://exemplo.com/arquivo.pdf",
    "filename": "relatorio.pdf"
  }
}
POST /api/v1/messages/send — Vídeo
{
  "recipient_type": "group",
  "to": "GROUP_ID_HERE",
  "type": "video",
  "video": {
    "link": "https://exemplo.com/video.mp4",
    "caption": "Vídeo para o grupo"
  }
}
POST /api/v1/messages/send — Áudio
{
  "recipient_type": "group",
  "to": "GROUP_ID_HERE",
  "type": "audio",
  "audio": {
    "link": "https://exemplo.com/audio.mp3"
  }
}
Obtendo o GROUP_ID
O identificador do grupo deve ser capturado através dos webhooks de entrada (campo message.group_id) ou retornado por APIs de gestão de grupos da Meta.

Status de 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 Consultar Status

Retorna uma lista paginada de mensagens com seus status de entrega. Todos os parâmetros são opcionais — sem filtros, retorna as 50 mensagens mais recentes.

Endpoint
GET /api/v1/messages/status

Parâmetros de Query

ParâmetroTipoDescrição
wamidstringID único da mensagem (ex: wamid.XXX...). Retorna apenas este registro.
statusstringFiltra por status: sent, delivered, read ou failed.
fromstringFiltra pelo número de origem (display_phone_number ou phone_number_id).
recipientstringFiltra pelo número do destinatário.
sincestringData/hora de início. Aceita ISO 8601 ou YYYY-MM-DD.
untilstringData/hora de fim. Aceita ISO 8601 ou YYYY-MM-DD.
limitintegerQuantidade de registros por página. Padrão: 50. Máximo: 200.
offsetintegerDeslocamento para paginação. Padrão: 0.
Exemplo — buscar mensagens lidas hoje
curl -X GET "https://api.covercut.com.br/api/v1/messages/status?status=read&since=2025-01-01&limit=100" \
  -H "X-API-Key: sua_api_key" \
  -H "X-API-Secret: seu_api_secret"
Exemplo — buscar status de uma mensagem específica
curl -X GET "https://api.covercut.com.br/api/v1/messages/status?wamid=wamid.HBgLNTUxMTk5..." \
  -H "X-API-Key: sua_api_key" \
  -H "X-API-Secret: seu_api_secret"

Resposta

JSON — 200 OK
{
  "success": true,
  "total": 243,
  "count": 50,
  "limit": 50,
  "offset": 0,
  "messages": [
    {
      "wamid": "wamid.HBgLNTUxMTk5...",
      "status": "read",
      "direction": "outbound",
      "message_type": "text",
      "recipient": "5511999990000",
      "from_number": "+55 11 98888-0000",
      "from_number_id": "1234567890",
      "created_at": "2025-01-10 14:32:00"
    },
    {
      "wamid": "wamid.HBgLNTUxMTk4...",
      "status": "failed",
      "direction": "outbound",
      "message_type": "template",
      "recipient": "5511988880000",
      "from_number": "+55 11 98888-0000",
      "from_number_id": "1234567890",
      "template_name": "agendamento_confirmado",
      "created_at": "2025-01-10 13:10:00",
      "error": {
        "code": "131026",
        "message": "Message undeliverable"
      }
    }
  ]
}
Paginação
Use total e offset para navegar pelos resultados. Para buscar a próxima página, incremente o offset pelo valor de limit.
offset = offset + limit
Status vs. Webhook
Os status são atualizados em tempo real via webhook da Meta. Use este endpoint para reconciliar ou popular seu banco de dados. Para receber atualizações instantâneas, configure seu webhook de eventos.

Listar Templates da Meta

Consulte todos os templates de mensagem cadastrados na sua conta WABA (WhatsApp Business Account) diretamente da Meta. Útil para popular seletores de templates em interfaces de envio ou para sincronizar status de aprovação.

GET Listar Templates

Retorna os templates cadastrados na WABA associada ao número ativo do cliente. Os resultados são ordenados por status (APPROVED primeiro) e depois em ordem alfabética pelo nome.

Endpoint
GET /api/v1/templates/list

Parâmetros de Query (todos opcionais)

ParâmetroTipoDescrição
fromstringFiltra pelo phone_number_id de um número específico do cliente. Se omitido, usa o primeiro número ativo.
statusstringFiltra pelo status do template: APPROVED, PENDING, REJECTED, PAUSED, DISABLED.
categorystringFiltra pela categoria: MARKETING, UTILITY ou AUTHENTICATION.
namestringFiltra por substring do nome do template (case-insensitive). Ex: boas_vindas retorna todos os templates cujo nome contém esse trecho.
limitintegerQuantidade máxima de templates retornados. Padrão: 200. Máximo: 500.
Exemplo — listar todos os templates aprovados
curl -X GET "https://api.covercut.com.br/api/v1/templates/list?status=APPROVED" \
  -H "X-API-Key: sua_api_key" \
  -H "X-API-Secret: seu_api_secret"
Exemplo — buscar templates de utilidade que contenham "confirmacao"
curl -X GET "https://api.covercut.com.br/api/v1/templates/list?category=UTILITY&name=confirmacao" \
  -H "X-API-Key: sua_api_key" \
  -H "X-API-Secret: seu_api_secret"

Resposta

JSON — 200 OK
{
  "success": true,
  "message": "Templates listados com sucesso",
  "waba_id": "123456789012345",
  "phone_number_id": "987654321098765",
  "total": 3,
  "templates": [
    {
      "id": "111222333444555",
      "name": "agendamento_confirmado",
      "status": "APPROVED",
      "category": "UTILITY",
      "language": "pt_BR",
      "components": [
        {
          "type": "BODY",
          "text": "Olá {{1}}, seu agendamento para {{2}} foi confirmado!"
        },
        {
          "type": "FOOTER",
          "text": "Responda CANCELAR para desmarcar."
        }
      ],
      "quality_score": { "score": "HIGH" },
      "last_updated_time": "2026-01-15T10:30:00+0000"
    },
    {
      "id": "666777888999000",
      "name": "promocao_janeiro",
      "status": "APPROVED",
      "category": "MARKETING",
      "language": "pt_BR",
      "components": [
        { "type": "HEADER", "format": "IMAGE" },
        {
          "type": "BODY",
          "text": "Aproveite {{1}}% de desconto em todos os produtos!"
        }
      ],
      "quality_score": { "score": "MEDIUM" },
      "last_updated_time": "2026-01-10T08:00:00+0000"
    },
    {
      "id": "101112131415161",
      "name": "recuperacao_senha",
      "status": "PENDING",
      "category": "AUTHENTICATION",
      "language": "pt_BR",
      "components": [
        {
          "type": "BODY",
          "text": "Seu código de verificação é {{1}}. Válido por 10 minutos.",
          "add_security_recommendation": true
        },
        {
          "type": "FOOTER",
          "code_expiration_minutes": 10
        },
        {
          "type": "BUTTONS",
          "buttons": [{ "type": "OTP", "otp_type": "COPY_CODE", "text": "Copiar código" }]
        }
      ],
      "quality_score": null,
      "last_updated_time": "2026-04-01T14:00:00+0000"
    }
  ]
}
Campos retornados por template

Cada objeto no array templates contém: id, name, status, category, language, components, quality_score, rejected_reason (quando reprovado) e last_updated_time.

Sobre o filtro por nome

O filtro ?name= é aplicado localmente após receber a lista da Meta — a API da Meta não suporta busca por substring. Para grandes contas com muitos templates, isso pode reduzir a performance. Use os filtros de status e category para pre-filtrar no lado da Meta antes de aplicar o filtro de nome.

Gestão de Templates

Os endpoints abaixo são proxies diretos para a API oficial da Meta. Nenhum dado é armazenado no BSP — tudo é enviado e recebido em tempo real da sua conta WABA. Você precisa de um número ativo com Access Token válido.

Revisão da Meta

Templates criados ou editados passam por revisão automática da Meta antes de ficarem disponíveis para envio. O tempo médio é de alguns minutos a algumas horas. Use o endpoint Listar Templates para monitorar o status.

POST Criar Template

Envia um novo template de mensagem para a sua WABA. Após a criação, o template ficará com status PENDING até ser revisado pela Meta.

Endpoint
POST /api/v1/templates/create

Parâmetros do Body (JSON)

CampoTipoObrig.Descrição
namestringSimNome único do template. Apenas letras minúsculas, números e _. Ex: agendamento_confirmado
categorystringSimMARKETING, UTILITY ou AUTHENTICATION
languagestringSimCódigo de idioma. Ex: pt_BR, en_US, es
componentsarraySimArray de componentes do template (HEADER, BODY, FOOTER, BUTTONS)
allow_category_changebooleanNãoSe true, permite que a Meta reclassifique a categoria automaticamente para evitar rejeição
fromstringNãophone_number_id específico. Se omitido, usa o primeiro número ativo
Exemplo — template de utilidade com variável
curl -X POST "https://api.covercut.com.br/api/v1/templates/create" \
  -H "X-API-Key: sua_api_key" \
  -H "X-API-Secret: seu_api_secret" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "agendamento_confirmado",
    "category": "UTILITY",
    "language": "pt_BR",
    "allow_category_change": true,
    "components": [
      {
        "type": "BODY",
        "text": "Olá {{1}}, seu agendamento para {{2}} está confirmado! Qualquer dúvida, responda esta mensagem."
      },
      {
        "type": "FOOTER",
        "text": "Responda CANCELAR para desmarcar."
      }
    ]
  }'
Exemplo — template de marketing com imagem e botão
curl -X POST "https://api.covercut.com.br/api/v1/templates/create" \
  -H "X-API-Key: sua_api_key" \
  -H "X-API-Secret: seu_api_secret" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "oferta_especial_maio",
    "category": "MARKETING",
    "language": "pt_BR",
    "components": [
      {
        "type": "HEADER",
        "format": "IMAGE",
        "example": { "header_handle": ["https://exemplo.com/banner.jpg"] }
      },
      {
        "type": "BODY",
        "text": "Aproveite {{1}}% de desconto em toda a loja até {{2}}!",
        "example": { "body_text": [["20", "31/05"]] }
      },
      {
        "type": "BUTTONS",
        "buttons": [
          { "type": "URL", "text": "Ver ofertas", "url": "https://exemplo.com/ofertas" }
        ]
      }
    ]
  }'

Resposta

JSON — 200 OK
{
  "success": true,
  "message": "Template criado com sucesso. Aguarde a revisão da Meta.",
  "template_id": "111222333444555",
  "status": "PENDING",
  "name": "agendamento_confirmado",
  "category": "UTILITY",
  "language": "pt_BR",
  "waba_id": "123456789012345",
  "phone_number_id": "987654321098765"
}

POST Criar Template de Marketing Customizado

Endpoint dedicado para criação de modelos promocionais usando formatação com parâmetros nomeados (parameter_format: "named").

Endpoint
POST /api/v1/templates/marketing

Exemplo de Payload

JSON
{
  "name": "meu_modelo_marketing",
  "category": "MARKETING",
  "language": "pt_BR",
  "parameter_format": "named",
  "components": [
    {
      "type": "body",
      "text": "Seu código é *{{discount_code}}*, válido até {{expiration_date}}.",
      "example": {
        "body_text_named_params": [
          { "param_name": "discount_code", "example": "BEMVINDO" },
          { "param_name": "expiration_date", "example": "amanhã" }
        ]
      }
    }
  ]
}

POST Editar Template

Atualiza os components de um template existente. Após a edição, o template voltará para revisão da Meta com status PENDING.

Limitações da Meta

Apenas os componentes (texto, botões) podem ser editados. Nome, categoria e idioma são imutáveis — para alterá-los, exclua o template e recrie. Templates com status APPROVED e REJECTED podem ser editados; templates PENDING não.

Endpoint
POST /api/v1/templates/update

Parâmetros do Body (JSON)

CampoTipoObrig.Descrição
template_idstringSimID numérico do template (obtido via Listar Templates)
componentsarraySimLista completa dos novos componentes (substitui os existentes)
fromstringNãophone_number_id específico para autenticar a requisição
Exemplo — atualizar texto do corpo do template
curl -X POST "https://api.covercut.com.br/api/v1/templates/update" \
  -H "X-API-Key: sua_api_key" \
  -H "X-API-Secret: seu_api_secret" \
  -H "Content-Type: application/json" \
  -d '{
    "template_id": "111222333444555",
    "components": [
      {
        "type": "BODY",
        "text": "Olá {{1}}, seu agendamento para {{2}} foi confirmado e está com tudo certo!"
      },
      {
        "type": "FOOTER",
        "text": "Dúvidas? Responda esta mensagem."
      }
    ]
  }'

Resposta

JSON — 200 OK
{
  "success": true,
  "message": "Template atualizado com sucesso. As alterações serão revisadas pela Meta.",
  "template_id": "111222333444555",
  "updated": true
}

DELETE Excluir Template

Remove um template da sua WABA. Aceita também requisições POST para clientes que não suportam HTTP DELETE com body.

Atenção: ação irreversível

Após a exclusão, o nome do template fica bloqueado por 30 dias na Meta — você não poderá criar outro template com o mesmo nome nesse período. Se omitir o template_id, todas as variantes de idioma do template serão excluídas.

Endpoint
DELETE /api/v1/templates/delete
POST   /api/v1/templates/delete  ← alternativa para clientes sem suporte a DELETE

Parâmetros do Body (JSON)

CampoTipoObrig.Descrição
namestringSimNome do template a excluir
template_idstringNãoSe informado, exclui apenas a variante de idioma específica. Se omitido, exclui todas as línguas
fromstringNãophone_number_id específico para autenticar a requisição
Exemplo — excluir template em todos os idiomas
curl -X DELETE "https://api.covercut.com.br/api/v1/templates/delete" \
  -H "X-API-Key: sua_api_key" \
  -H "X-API-Secret: seu_api_secret" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "agendamento_confirmado"
  }'
Exemplo — excluir apenas a variante pt_BR (via template_id)
curl -X DELETE "https://api.covercut.com.br/api/v1/templates/delete" \
  -H "X-API-Key: sua_api_key" \
  -H "X-API-Secret: seu_api_secret" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "agendamento_confirmado",
    "template_id": "111222333444555"
  }'

Resposta

JSON — 200 OK (todas as línguas)
{
  "success": true,
  "message": "Template excluído em todos os idiomas com sucesso. O nome ficará bloqueado por 30 dias na Meta.",
  "deleted": true,
  "name": "agendamento_confirmado",
  "template_id": null,
  "scope": "all_languages",
  "waba_id": "123456789012345"
}
JSON — 200 OK (variante específica)
{
  "success": true,
  "message": "Variante de idioma do template excluída com sucesso.",
  "deleted": true,
  "name": "agendamento_confirmado",
  "template_id": "111222333444555",
  "scope": "language_variant",
  "waba_id": "123456789012345"
}

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.

GET Listar Grupos

Retorna uma lista de todos os grupos em que o número de telefone do BSP é membro. Útil para descobrir o group_id oficial.

Endpoint
GET /api/v1/groups/list
Exemplo de Resposta (200 OK)
{
  "success": true,
  "data": [
    { "id": "Y2FwaV9...", "name": "Grupo de Vendas" },
    { "id": "Y2FwaV9...", "name": "Suporte N2" }
  ]
}

POST Criar Grupo

Cria um novo grupo e adiciona participantes iniciais. Note que há limites de participantes para contas Business (geralmente até 10).

POST /api/v1/groups/create
{
  "name": "Nome do Novo Grupo",
  "description": "Descrição opcional",
  "participants": [
    "5547999999999",
    "BR.13491208655302741918"
  ]
}

GET Ver Informações do Grupo

Obtém detalhes de um grupo específico, incluindo nome, descrição e participantes.

Endpoint
GET /api/v1/groups/info?group_id=GROUP_ID_HERE

GET / POST Gerenciar Link de Convite

Obtenha ou resete o link de convite do grupo. Use POST (com corpo contendo group_id) para invalidar o link anterior e gerar um novo.

Obter Link — GET
GET /api/v1/groups/invite_link?group_id=GROUP_ID_HERE
Resetar Link — POST
POST /api/v1/groups/invite_link
{ "group_id": "GROUP_ID_HERE" }

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.

Gestão Individual por Número

No dashboard de Webhooks, você encontrará uma tabela de Status de Número. Ela permite gerenciar cada conexão de forma independente:

  • Configuração Geral: Define uma URL padrão que funciona como "reserva" (fallback).
  • Controle por Número: Cada número pode ser ativado ou desativado individualmente, permitindo que você pause as notificações de um celular específico sem afetar os outros.
  • URLs Exclusivas: Se você precisar enviar os dados de um número para um sistema diferente, basta clicar em "Configurar" ao lado do número desejado.
Dica de Roteamento: O sistema prioriza a URL individual do número. Se ela não estiver configurada, o sistema envia automaticamente para a URL definida no Webhook Geral.

Opções de Controle

  • Ativar/Desativar: Você pode pausar o recebimento de webhooks sem precisar remover a URL configurada.
  • Ignorar Grupos: Se esta opção estiver ativa, o sistema filtrará automaticamente todas as mensagens vindas de grupos, entregando apenas mensagens de conversas individuais no seu webhook.

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
}

Validar no n8n (Sem código)

A forma mais simples de validar no n8n é usando o nó Crypto:

  1. Adicione um nó Crypto após o Webhook.
  2. Action: Hmac
  3. Value: {{ JSON.stringify($json.body) }}
  4. Secret: Seu Webhook Secret
  5. Algorithm: sha256
  6. Aí é só comparar o resultado com o header x-bsp-signature.
Modelo n8n Pronto:

Preparamos um fluxo base para o n8n que já inclui tratamento de dados e exemplos de envio de mensagens.

Baixar conexao_base.json

Eventos de Mensagem

Nova Mensagem

O campo contact.user_id (BSUID) está sempre presente. O campo contact.wa_id contém o telefone e pode ser omitido se o usuário tiver username ativo e não houver contato recente. O campo contact.username aparece apenas quando o usuário adotou um username no WhatsApp.

Event: message
{
  "event": "message",
  "timestamp": "2026-03-31T10:30:00-03:00",
  "from_number_id": "123456789",
  "from_number": "+55 47 99999-9999",
  "direction": "inbound",
  "contact": {
    "wa_id": "5547999999999",      // telefone — pode ser omitido (veja nota acima)
    "user_id": "BR.13491208655302741918",  // BSUID — sempre presente
    "name": "João Silva",
    "username": "@joaosilva"       // presente apenas se o usuário tiver username
  },
  "message": {
    "id": "wamid...",
    "type": "text",
    "timestamp": 1743413400,
    "text": "Oi!",
    "group_id": "Y2FwaV9..."       // Identificador único do grupo (se aplicável)
  }
}
Identifique contatos pelo user_id (BSUID)
A partir de 2026, usuários com username podem não ter wa_id no webhook. Use contact.user_id como identificador principal e mantenha wa_id como complemento quando disponível.

Status

O campo status.recipient contém o telefone do destinatário ou o BSUID — use-o como identificador universal. Quando a mensagem foi enviada por BSUID e o telefone não está disponível, apenas o BSUID é retornado.

Event: status
{
  "event": "status",
  "timestamp": "2026-03-31T10:30:05-03:00",
  "from_number_id": "123456789",
  "status": {
    "id": "wamid...",
    "status": "delivered",
    "recipient": "5547999999999"   // telefone OU BSUID OU GROUP_ID dependendo de como a mensagem foi enviada
  }
}

Webhook de Alertas

Além do webhook de mensagens, você pode configurar um endpoint separado para receber alertas operacionais gerados pelo BSP — como quedas de qualidade, suspensões e vencimento de assinatura. Isso permite rotear avisos para ferramentas de monitoramento (Slack, PagerDuty, etc.) sem misturar com o fluxo de mensagens.

Configuração

Acesse Configurações > Webhook no dashboard e localize a seção Webhook de Alertas. Informe a URL de destino e ative o envio. Um secret será gerado automaticamente na primeira vez que você salvar.

Nível de conta: O Webhook de Alertas é configurado uma única vez por conta, não por número. O campo alert.number_id no payload identifica qual número originou o alerta (quando aplicável).

Headers Enviados

Headers — Webhook de Alertas
Content-Type: application/json
X-BSP-Signature: <sha256_hmac(payload, alert_webhook_secret)>
X-BSP-Timestamp: <unix_timestamp>

A assinatura é calculada da mesma forma que o webhook de mensagens: hash_hmac('sha256', $payload_bruto, $alert_webhook_secret). Use o Alert Webhook Secret exibido no dashboard (diferente do secret do webhook de mensagens).

Payload do Evento alert

Event: alert
{
  "event": "alert",
  "timestamp": "2026-03-19T10:30:00-03:00",
  "alert": {
    "type": "quality_warning",
    "title": "Qualidade do número em queda",
    "message": "O número +55 47 99999-9999 está com qualidade YELLOW. Reduza o volume de mensagens não solicitadas.",
    "number_id": 42
  }
}

Tipos de Alerta

Tipo (alert.type) Descrição number_id
quality_warning Qualidade do número caiu para YELLOW — risco de suspensão se continuar. Sim
quality_critical Qualidade do número caiu para RED. O número foi suspenso automaticamente. Sim
tier_change O tier de mensagens do número foi alterado pela Meta. Sim
suspension Assinatura expirada — acesso à API suspenso. Não
subscription_expiring A assinatura expira em breve. Renovação recomendada. Não
info Evento informativo (ex: número conectado ou desconectado). Sim ou Não
test Evento gerado ao clicar em "Testar Agora" no dashboard. Não

Validar Assinatura do Alerta

PHP — Validação de Assinatura do Alerta
$payload   = file_get_contents('php://input');
$signature = hash_hmac('sha256', $payload, $alert_webhook_secret);

if (hash_equals($_SERVER['HTTP_X_BSP_SIGNATURE'], $signature)) {
    $data = json_decode($payload, true);
    // $data['event'] === 'alert'
    // $data['alert']['type'], $data['alert']['number_id'], etc.
}
Dica: Se o alert_webhook_enabled estiver desativado, os alertas continuam sendo registrados no painel do dashboard — apenas o envio HTTP é suprimido.

Baixar Mídia

Quando uma mensagem de áudio, imagem, vídeo ou documento chega pelo Webhook, o campo message contém um Media ID. Use este endpoint para baixar o arquivo — a API resolve o token da Meta automaticamente usando as credenciais do seu número conectado.

Como funciona internamente:
media_id do webhook → API busca o token do número no banco → chama graph.facebook.com/v25.0/{id} → obtém a URL temporária + mime_type → faz o download autenticado → retorna o arquivo para você.

Não é necessário usar o token da Meta diretamente. A API cuida de toda a autenticação.

GET Modo Base64 (padrão)

Retorna o conteúdo do arquivo codificado em Base64 dentro de um JSON. Ideal para processar o arquivo no mesmo fluxo ou enviá-lo para uma API de transcrição via body JSON.

GET /api/v1/media/get?id={'{'}media_id{'}'}
// Resposta de sucesso
{
  "success": true,
  "message": "Mídia processada com sucesso",
  "media_id": "1234567890",
  "mime_type": "audio/ogg; codecs=opus",
  "filesize": 14532,
  "base64": "T2dnUwACAAAAAAAA..."
}

GET Modo Stream (binário direto)

Adicionando mode=stream, o endpoint retorna o arquivo binário diretamente com os headers Content-Type e Content-Disposition corretos — equivalente ao Response Format: File do n8n.

GET /api/v1/media/get?id={'{'}media_id{'}'}&mode=stream
// Headers da resposta (arquivo binário)
Content-Type: audio/ogg; codecs=opus
Content-Disposition: attachment; filename="1234567890.ogg"
Content-Length: 14532
Cache-Control: no-store

// Corpo: bytes do arquivo

Use este modo quando precisar do arquivo como binário — por exemplo, para enviar ao Whisper (OpenAI) ou qualquer outra API que aceite upload de arquivo.

Importante: O Media ID da Meta expira em aproximadamente 5 minutos após o recebimento do webhook. Faça o download logo após receber o evento.

Tipos de Mídia e Campos no Webhook

Cada tipo de mídia recebida expõe o id em um campo diferente dentro do objeto message:

Tipo Campo no message Exemplo de mime_type
Áudiomessage.audio.idaudio/ogg; codecs=opus
Imagemmessage.image.idimage/jpeg
Vídeomessage.video.idvideo/mp4
Documentomessage.document.idapplication/pdf
Stickermessage.sticker.idimage/webp

Exemplo de payload do Webhook com áudio

Payload recebido no seu servidor
{
  "event": "message",
  "timestamp": "2026-03-22T10:00:00-03:00",
  "from_number_id": "123456789",
  "contact": {
    "wa_id": "5547888889999",
    "name": "João Silva"
  },
  "message": {
    "id": "wamid.xxx",
    "type": "audio",
    "audio": {
      "id": "1234567890",
      "mime_type": "audio/ogg; codecs=opus"
    }
  }
}

// Para baixar: GET /api/v1/media/get?id=1234567890

Integração com n8n

Substitua os 3 nodes do fluxo original (GET URL na Meta → Download com Bearer → Processar) por 1 único node HTTP Request:

Campo n8nValor
MethodGET
URLhttps://api.covercut.com.br/api/v1/media/get?id={{ $json.message.audio.id }}&mode=stream
Header X-API-Keysua chave de API
Header X-API-Secretseu secret de API
Response FormatFile

O arquivo chegará como binário, pronto para ser enviado ao próximo node (ex.: OpenAI → Transcribe Recording).

Troque o campo conforme o tipo de mídia: $json.message.audio.id para áudio, $json.message.image.id para imagem, $json.message.video.id para vídeo, $json.message.document.id para documento.

IDs de Usuário no Escopo da Empresa (BSUID)

A partir de 2026, o WhatsApp introduz nomes de usuário opcionais. Para suportá-los, a Meta criou um novo identificador chamado BSUID (Business-Scoped User ID): um código único por usuário, vinculado ao seu portfólio empresarial.

O que muda

QuandoO que acontece
31/03/2026BSUIDs começam a aparecer nos webhooks. O campo contact.user_id passa a estar presente em todas as mensagens recebidas.
Maio/2026A API passa a aceitar BSUIDs como destinatário de mensagens via campo recipient.

Formato do BSUID

O BSUID é prefixado com o código do país ISO 3166 alpha-2, seguido de um ponto e até 128 caracteres alfanuméricos:

Exemplos de BSUID
BR.13491208655302741918
US.13491208655302741918
US.ENT.11815799212886844830  // BSUID principal (portfólios vinculados)

Enviar mensagem por BSUID

Use o campo recipient no lugar de to. Não é necessário formatar como telefone.

POST /api/v1/messages/send — via BSUID
{
  "recipient": "BR.13491208655302741918",
  "type": "text",
  "text": { "body": "Olá!" }
}

Receber BSUID nos webhooks

O campo contact.user_id estará presente em todos os webhooks de mensagem recebida. O campo contact.wa_id (telefone) pode ser omitido quando o usuário adotou username e não houve interação nos últimos 30 dias.

Webhook — contact com BSUID
"contact": {
  "wa_id": "5547999999999",          // pode ser omitido
  "user_id": "BR.13491208655302741918",  // sempre presente
  "name": "João Silva",
  "username": "@joaosilva"           // presente se o usuário tiver username
}
Boas práticas
  • Armazene o user_id (BSUID) junto ao número de telefone nos seus registros de contato.
  • Use user_id como chave principal de identificação — ele está sempre presente.
  • Não tente enviar mensagens de autenticação (one-tap, zero-tap, copy-code) usando BSUID — esses tipos exigem telefone.
  • BSUIDs são específicos ao seu portfólio: o mesmo usuário terá um BSUID diferente em cada empresa.
Erro 131062 — BSUID não suportado
Se tentar enviar um template de autenticação usando BSUID, a Meta retornará o código 131062: Business-scoped User ID (BSUID) recipients are not supported for this message. Use o número de telefone nesses casos.

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.

3. Recursos Avançados

O BSP oferece controles granulares para melhorar sua operação:

  • Ignorar Grupos: Filtra mensagens de grupos para não "poluir" seu Chatwoot.
  • Assinar Mensagens: Adiciona o nome do atendente ao final de cada resposta (ex: - Atendente João).
  • Reabrir Conversas: Reativa tickets "Resolvidos" no Chatwoot ao receber nova mensagem do cliente.

Como Funciona o Fluxo

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

Códigos de Erro

Código Descrição
400Requisição inválida ou parâmetros faltando.
401Credenciais inválidas ou expiradas.
404Recurso ou endpoint não encontrado.
429Muitas requisições. Rate limit excedido.
500Erro interno em nossos servidores.
131062Meta: BSUID não suportado para este tipo de mensagem. Templates de autenticação exigem número de telefone.

Rate Limiting

Nossa API possui limites de segurança para garantir a estabilidade do serviço:

  • Plano Básico: 60 requisições por minuto.
  • Plano Pro: 180 requisições por minuto.
Importante: Estes limites visam proteger a qualidade do seu número e evitar suspensões pela Meta por comportamento suspeito de spam.

Suporte

Precisa de ajuda? Nossa equipe técnica está disponível para auxiliar na sua integração.

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