POST /send-template

Envia uma mensagem WhatsApp usando um template previamente aprovado pelo Meta. Esta é a única forma de iniciar conversa fora da janela de 24h ou de mandar mensagem proativa.

Campo Valor
URL https://api.wevi.chat/functions/v1/send-template
Método POST
Auth Authorization: Bearer wevi_... (API key)
Content-Type application/json
Rate limit 60 req/min por API key
Plano necessário Pro ou Ultra

Pré-requisitos

Formato de erro. Desde 8 de setembro de 2026, os erros deste endpoint saem no envelope padrão: error é um código estável (missing_connection_id) e a frase que você já conhecia (missing_connection_id) vai em message. O corpo de sucesso não mudou. A chave de teste wevi_test_ passou a valer aqui também.

  1. WhatsApp conectado em Conta → WhatsApp Business. Anote o connection_id.
  2. Template aprovado pelo Meta: criado em WhatsApp Business → Templates, com status APPROVED.
  3. API key criada em Conta → Desenvolvedores → API Keys.

Body

Campo Tipo Obrigatório Descrição
connection_id string (uuid) sim ID da conexão WhatsApp da sua org.
template_name string sim Nome exato do template (case-sensitive).
to string sim Telefone destino. Aceita formato BR (com ou sem +55) ou internacional.
language_code string não Idioma do template. Padrão: pt_BR.
body_params array de strings não Variáveis do corpo na ordem {{1}}, {{2}}, {{3}}.
header_image_url string (URL pública) não Pra templates com header tipo imagem.
contact_id string (uuid) não Vincula o envio a um contato da Wevi. Permite usar variáveis dinâmicas (veja abaixo).
open_conversation "always" | "on_reply" não Se o disparo abre conversa no inbox. Padrão: always. Veja abaixo.
idempotency_key string não Chave única pra evitar duplicação em retries. Veja erros.

Conversa no inbox (open_conversation)

Controla o que acontece no inbox da Wevi quando o template sai.

Valor O que acontece
always (padrão) O disparo já abre a conversa no inbox, com a mensagem enviada no histórico.
on_reply Nada aparece no inbox na hora. Se o contato responder, a conversa é criada nesse momento e o disparo entra no histórico logo antes da resposta.

Use on_reply em disparo em volume (aviso, confirmação, lembrete), pra não encher o inbox de conversa que ninguém vai atender. O envio, a entrega e o status de leitura continuam registrados do mesmo jeito nos dois casos.

Quando o contato já tem uma conversa aberta, a mensagem entra nela normalmente, mesmo com on_reply. A opção decide apenas se uma conversa nova é aberta.

Disparo guardado há mais de 30 dias não volta mais: resposta muito depois abre a conversa só com a mensagem do contato.

Variáveis dinâmicas em body_params

Se você passar contact_id, os body_params podem conter substituições que a Wevi resolve antes de mandar pro Meta:

Variável Vira
{{contact_name}} contacts.display_name
{{contact_phone}} telefone normalizado
{{chave_custom}} valor de contact.custom_fields["chave_custom"]

Exemplo: template "Olá {{1}}, seu pedido {{2}} foi confirmado.", chamando com:

{
  "body_params": ["{{contact_name}}", "12345"],
  "contact_id": "uuid-do-cliente"
}

vira "Olá João Silva, seu pedido 12345 foi confirmado."

Exemplos

Template simples sem variáveis

curl -X POST https://api.wevi.chat/functions/v1/send-template \
  -H "Authorization: Bearer wevi_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "connection_id": "conn-uuid",
    "template_name": "boas_vindas",
    "to": "+5511999999999"
  }'

Com variáveis e contact_id

curl -X POST https://api.wevi.chat/functions/v1/send-template \
  -H "Authorization: Bearer wevi_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "connection_id": "conn-uuid",
    "template_name": "pedido_confirmado",
    "to": "+5511999999999",
    "body_params": ["{{contact_name}}", "12345", "R$ 297,00"],
    "contact_id": "contact-uuid",
    "idempotency_key": "pedido-12345-confirmacao"
  }'

Sem abrir conversa no inbox

curl -X POST https://api.wevi.chat/functions/v1/send-template \
  -H "Authorization: Bearer wevi_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "connection_id": "conn-uuid",
    "template_name": "lembrete_consulta",
    "to": "+5511999999999",
    "body_params": ["{{contact_name}}", "14h30"],
    "contact_id": "contact-uuid",
    "open_conversation": "on_reply"
  }'

Com header de imagem

curl -X POST https://api.wevi.chat/functions/v1/send-template \
  -H "Authorization: Bearer wevi_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "connection_id": "conn-uuid",
    "template_name": "promocao_imagem",
    "to": "+5511999999999",
    "header_image_url": "https://meusite.com/banner-promo.png",
    "body_params": ["50%"]
  }'

Resposta

Sucesso (200)

{
  "id": "envio-uuid",
  "wamid": "wamid.HBgN...",
  "status": "sent"
}
  • id: ID do envio na Wevi (use em logs/idempotency).
  • wamid: WhatsApp message ID retornado pelo Meta.
  • status: começa sent. Vira delivered, read ou failed conforme webhook do Meta atualiza.

Falha do Meta (200 mas status: "failed")

{
  "id": "envio-uuid",
  "status": "failed",
  "error": "Template not approved in this language"
}

Casos comuns: template ainda em pending, idioma inválido, número bloqueado.

Erros HTTP

Status error
400 missing_connection_id, template_name is required, missing_to, open_conversation must be "always" or "on_reply"
401 invalid_api_key
402 plan_limit_exceeded (sem WhatsApp no plano)
404 connection_not_found
429 rate_limit_exceeded

Diferença pro /send-message

/send-template /send-message
Pra quê Mensagem proativa, fora ou dentro da janela 24h Resposta textual dentro da janela 24h
Precisa template aprovado? Sim Não
Aceita mídia? Sim, via header_image_url Não (só texto)
Variáveis? Sim, no body_params Não

Veja `POST /send-message`.

Próximo

/send-message