Como enviar mensagens WhatsApp via API
Nível: Intermediário
Tempo de leitura: 8 min
Plano necessário: Pro ou Ultra
Procurando a referência técnica? Veja POST /send-template, POST /send-message e POST /send-conversation-message na documentação de API, com schema completo, idempotência, variáveis dinâmicas e códigos de erro.
O que é esta funcionalidade
A Wevi oferece dois endpoints HTTP que permitem enviar mensagens WhatsApp diretamente de qualquer sistema externo com suporte a requisições HTTP, como n8n, Make, Zapier, sistemas próprios ou scripts.
Com isso, você consegue, por exemplo:
- Enviar um template de boas-vindas quando um novo cliente se cadastra no seu CRM
- Disparar um lembrete de consulta a partir do seu sistema de agendamento
- Notificar clientes sobre status de pedido via webhook do seu e-commerce
- Criar automações de reengajamento a partir de qualquer ferramenta externa
Endpoints disponíveis
| Endpoint | Quando usar |
|---|---|
POST /functions/v1/send-template |
Enviar template aprovado pela Meta. Funciona a qualquer momento, mesmo sem histórico de conversa. |
POST /functions/v1/send-message |
Enviar texto livre. Só funciona se o contato interagiu com você nas últimas 24 horas. Não fica registrado na conversa nem no histórico do agente de IA, só na aba Enviadas de Campanhas. |
POST /functions/v1/send-conversation-message |
Enviar texto e/ou imagem dentro de uma conversa já existente, continuando o atendimento. A mensagem aparece na conversa e entra no contexto do agente de IA. Ideal pra entregar o resultado de um processo assíncrono (ex: geração de imagem via n8n) na mesma conversa que o originou. |
Pré-requisitos
- Plano Pro ou Ultra
- Conexão WhatsApp ativa na Wevi (obtenha o
connection_idem Conectores) - Para
send-template: pelo menos um template aprovado pela Meta - Uma API Key gerada em Conta → Desenvolvedores
Passo 1: Gerar uma API Key
- No painel, vá em Conta → aba Desenvolvedores
- Role até a seção API Keys
- Digite um nome para identificar a chave (ex: "n8n produção") e clique em Criar chave
- Copie o token exibido. Ele começa com
wevi_e não será exibido novamente
Passo 2: Obter o connection_id
O connection_id identifica qual número WhatsApp vai enviar a mensagem.
- Vá em Conectores no painel
- Clique no conector WhatsApp desejado
- Copie o ID que aparece na URL ou nas configurações do conector
Passo 3: Fazer a primeira chamada
Enviando um template
curl -X POST https://api.wevi.chat/functions/v1/send-template \
-H "Authorization: Bearer wevi_SUACHAVEAQUI" \
-H "Content-Type: application/json" \
-d '{
"connection_id": "uuid-da-conexao",
"template_name": "boas_vindas_v1",
"language_code": "pt_BR",
"body_params": ["Maria"],
"to": "5548999001122"
}'
Resposta de sucesso:
{
"id": "uuid-do-envio",
"wamid": "wamid.ABC123...",
"status": "sent"
}
Enviando texto livre (dentro da janela de 24h)
curl -X POST https://api.wevi.chat/functions/v1/send-message \
-H "Authorization: Bearer wevi_SUACHAVEAQUI" \
-H "Content-Type: application/json" \
-d '{
"connection_id": "uuid-da-conexao",
"to": "5548999001122",
"text": "Olá! Seu pedido foi enviado e chega em até 2 dias úteis."
}'
Entregando o resultado de um processo assíncrono numa conversa existente
Use quando um sistema externo (ex: um workflow no n8n que demora minutos pra terminar) precisa devolver o resultado dentro da mesma conversa que originou o pedido:
curl -X POST https://api.wevi.chat/functions/v1/send-conversation-message \
-H "Authorization: Bearer wevi_SUACHAVEAQUI" \
-H "Content-Type: application/json" \
-d '{
"conversation_id": "uuid-da-conversa",
"text": "Prontinho! Aqui está o resultado.",
"media": {
"url": "https://exemplo.com/resultado.png",
"type": "image",
"mime_type": "image/png"
}
}'
O conversation_id é o mesmo valor que a Wevi já manda automaticamente (dentro de _wevi.conversation_id) quando um agente dispara uma ação customizada pro seu webhook.
Se o seu sistema já tem os bytes do arquivo em mãos (ex: uma imagem gerada que ainda não foi hospedada em lugar nenhum), pode mandar em media.base64 em vez de media.url. Não precisa subir o arquivo pra nenhum storage antes, o Wevichat cuida disso. Veja o passo a passo completo em POST /send-conversation-message.
Parâmetros completos
send-template
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
connection_id |
string (uuid) | Sim | ID da conexão WhatsApp |
template_name |
string | Sim | Nome exato do template aprovado |
to |
string | Sim | Número no formato internacional (ex: 5511999001122) |
language_code |
string | Não | Padrão: pt_BR |
body_params |
array de strings | Não | Valores das variáveis {{1}}, {{2}}... na ordem |
header_image_url |
string (URL) | Não | URL pública de imagem se o template tiver header de imagem |
contact_id |
string (uuid) | Não | ID do contato na Wevi para usar {{contact_name}} automaticamente |
idempotency_key |
string | Não | Chave única para evitar reenvios em caso de retry |
send-message
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
connection_id |
string (uuid) | Sim | ID da conexão WhatsApp |
to |
string | Sim | Número no formato internacional |
text |
string | Sim | Texto da mensagem (máx. 4096 caracteres) |
contact_id |
string (uuid) | Não | ID do contato na Wevi |
idempotency_key |
string | Não | Chave única para evitar reenvios |
send-conversation-message
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
conversation_id |
string (uuid) | Condicional | ID da conversa (ou use connection_id + to) |
connection_id |
string (uuid) | Condicional | ID da conexão WhatsApp, alternativa a conversation_id |
to |
string | Condicional | Telefone, usado junto com connection_id |
text |
string | Condicional | Texto ou legenda da mídia |
media |
objeto | Condicional | { url, type, mime_type, name? } — precisa de text e/ou media |
idempotency_key |
string | Não | Chave única para evitar reenvios |
Variáveis dinâmicas em templates
Se o template usa {{1}}, {{2}} etc., passe os valores em body_params na ordem:
{
"body_params": ["Maria", "15/06/2026", "14h30"]
}
Além disso, dentro do valor de qualquer variável você pode usar os marcadores especiais:
| Marcador | Substituído por |
|---|---|
{{contact_name}} |
Nome do contato na Wevi (requer contact_id) |
{{contact_phone}} |
Telefone do contato |
{{chave_do_campo}} |
Qualquer campo personalizado do contato (requer contact_id) |
Os campos personalizados são os campos extras que você criou para os contatos da sua organização (ex: plano, empresa, codigo_cliente). Você os cria e gerencia em Configurações → Campos personalizados no painel. Use a chave do campo como marcador.
Exemplo: se você tem um campo personalizado com chave plano, pode usar {{plano}} em qualquer body_params:
{
"contact_id": "uuid-do-contato",
"body_params": ["{{contact_name}}", "{{plano}}", "{{codigo_cliente}}"]
}
Se o contato não tiver o campo preenchido, o marcador é substituído por uma string vazia.
Limites de velocidade
Cada API Key tem um limite de 60 chamadas por minuto (1 por segundo em média). Ao ultrapassar, a API retorna 429 Too Many Requests com o header Retry-After indicando quantos segundos aguardar.
{ "error": "Too many requests", "retry_after": 12 }
No n8n, configure um nó Wait com o valor de retry_after antes de retentar. Em scripts próprios, leia o header Retry-After e durma esse número de segundos.
Para automações de alto volume (ex: disparar templates para uma lista grande), use campanhas em vez da API. Campanhas não têm limite de velocidade e processam em fila automaticamente.
Idempotência: evitando reenvios no n8n
O n8n pode reexecutar workflows em caso de erro de rede. Para evitar que a mesma mensagem seja enviada duas vezes, use idempotency_key:
{
"idempotency_key": "pedido-1234-confirmacao"
}
Se a chamada for repetida com a mesma chave, a Wevi retorna o resultado do envio original sem reenviar. A chave deve ser única por organização.
Exemplo: configurando no n8n
- Adicione um nó HTTP Request
- Configure:
- Method: POST
- URL:
https://api.wevi.chat/functions/v1/send-template - Authentication: Generic Credential Type → Header Auth
- Name:
Authorization - Value:
Bearer wevi_SUACHAVEAQUI
- Name:
- Em Body, selecione JSON e monte o payload
- Para usar dados do workflow, use expressões n8n como
{{ $json.email }}nos campos
O mesmo padrão funciona em qualquer ferramenta que suporte HTTP: Make, Zapier, scripts Python, Ruby, Node, ou qualquer sistema interno.
Erros comuns
Invalid API key
A chave foi revogada ou está incorreta. Gere uma nova em Conta → Desenvolvedores.
Connection not found
O connection_id não pertence à sua organização ou foi removido.
Template não aprovado ou inexistente A Meta retorna um erro de template. Verifique o status em WhatsApp > Templates.
Janela de 24h expirada (send-message)
Mensagem de texto livre só funciona dentro da janela de atendimento ativo. Use send-template para mensagens proativas.
402 — Plano não permite
API de envio requer plano Pro ou Ultra. Faça upgrade em Conta → Planos.
O que acontece quando o contato responde
Quando o destinatário responde a um template ou texto enviado via send-template/send-message, a conversa cai na caixa de entrada do agente normalmente. Mas a mensagem que você enviou não fica registrada no histórico dessa conversa, ela só aparece na aba Enviadas de Campanhas. O agente de IA não vai saber o que foi dito antes, e vai responder sem esse contexto.
Se você precisa que o agente de IA continue a conversa sabendo o que foi enviado, use `/send-conversation-message` em vez de send-message, ele grava a mensagem na própria conversa.
Acompanhando os envios
Todos os envios feitos via API aparecem na aba Enviadas dentro de Campanhas, junto com os disparos de campanha. Você pode filtrar por:
- Status (enviada, entregue, lida, falha)
- Origem (campanha ou API)
- Tipo (template ou texto)
- Período
O status é atualizado em tempo real conforme a Meta confirma a entrega e leitura.