Templates

Templates

Gerencie templates do WhatsApp Business: listar, criar, editar, remover e sincronizar da Meta.

Templates são mensagens pré-aprovadas pela Meta. Use-os para iniciar conversas ou reengajar contatos fora da janela de 24h.

GET /v1/templates

Lista templates do usuário.

GET /v1/templates 200401404429

Query: account_id (opcional; sem ele, retorna de todas as conexões do usuário).

Resposta 200: array de templates. statusPENDING | APPROVED | REJECTED | QUALITY_POOR. categoryAUTHENTICATION | MARKETING | UTILITY. Templates de conexões soft-deletadas são omitidos.

Resposta 200

[
{
  "id": "tpl_ckv...",
  "name": "boas_vindas",
  "language": "pt_BR",
  "category": "MARKETING",
  "status": "APPROVED",
  "components": { },
  "metaId": "987654321",
  "whatsAppAccountId": "ckv...",
  "userId": "usr_...",
  "syncedAt": "2026-06-20T10:00:00.000Z",
  "deletedAt": null,
  "createdAt": "2026-06-01T00:00:00.000Z",
  "updatedAt": "2026-06-20T10:00:00.000Z"
}
]

POST /v1/templates

Cria um template na Meta + banco.

POST /v1/templates 201400401404409422429

Body (JSON):

{
  "account_id": "ckv...",
  "name": "boas_vindas",
  "category": "MARKETING",
  "language": "pt_BR",
  "components": [
    { "type": "BODY", "text": "Olá {{1}}, bem-vindo!" }
  ],
  "allow_category_change": false
}
Campo Tipo Obrigatório Regras
name string Sim 1–512 chars, regex ^[a-z][a-z0-9_]*$ (minúsculas, dígitos, underscore)
category enum Sim AUTHENTICATION | MARKETING | UTILITY
language string Sim ≥ 2 chars (ex.: pt_BR)
components array Sim ≥ 1 componente (HEADER/BODY/FOOTER/BUTTONS/CAROUSEL)
account_id string Não opcional
allow_category_change boolean Não opcional

Botões (type: BUTTONS)

Cada botão do componente BUTTONS é um destes quatro subtipos:

SubtipoCampos
QUICK_REPLYtext (1–25 chars)
URLtext, url, example (opcional — obrigatório para URL com variável)
PHONE_NUMBERtext, phone_number
COPY_CODEtext (opcional), example (opcional)

Limites que o validador aplica no array buttons:

  • máx 10 botões no total;
  • máx 2 do subtipo URL, máx 1 PHONE_NUMBER, máx 1 COPY_CODE;
  • botões QUICK_REPLY precisam ficar contíguos (não pode intercalar com outro subtipo no meio do bloco);
  • URL com variável ({{n}} na url) só é aceita com a variável no final da string, e exige example preenchido.
{
  "name": "confirmacao_pedido",
  "category": "UTILITY",
  "language": "pt_BR",
  "components": [
    { "type": "BODY", "text": "Pedido {{1}} confirmado!" },
    {
      "type": "BUTTONS",
      "buttons": [
        { "type": "QUICK_REPLY", "text": "Rastrear pedido" },
        { "type": "URL", "text": "Ver no site", "url": "https://loja.com/pedido/{{1}}", "example": ["9F8D"] },
        { "type": "PHONE_NUMBER", "text": "Falar com suporte", "phone_number": "+551140028922" }
      ]
    }
  ]
}

Regras que o validador aplica:

  • só é aceito em category=MARKETINGUTILITY/AUTHENTICATION são rejeitados;
  • exige de 2 a 10 cards — 1 card ou 11+ é rejeitado;
  • cada card exige 1 ou 2 botões (componente BUTTONS dentro do card) — card sem nenhum botão é rejeitado pela Meta na criação (400);
  • todos os cards precisam usar o mesmo formato de mídia no HEADER (todos IMAGE ou todos VIDEO — não pode misturar);
  • os botões precisam ter a mesma assinatura em todos os cards (mesma sequência de subtipos — ex.: todo card com [QUICK_REPLY, URL], não pode um card ter [QUICK_REPLY] e outro [URL, PHONE_NUMBER]).
{
  "name": "promo_carousel",
  "category": "MARKETING",
  "language": "pt_BR",
  "components": [
    { "type": "BODY", "text": "Confira as novidades!" },
    {
      "type": "CAROUSEL",
      "cards": [
        {
          "components": [
            { "type": "HEADER", "format": "IMAGE", "example": { "header_handle": ["<handle da Resumable Upload API>"] } },
            { "type": "BODY", "text": "Produto A" },
            { "type": "BUTTONS", "buttons": [{ "type": "QUICK_REPLY", "text": "Quero esse" }] }
          ]
        },
        {
          "components": [
            { "type": "HEADER", "format": "IMAGE", "example": { "header_handle": ["<handle da Resumable Upload API>"] } },
            { "type": "BODY", "text": "Produto B" },
            { "type": "BUTTONS", "buttons": [{ "type": "QUICK_REPLY", "text": "Quero esse" }] }
          ]
        }
      ]
    }
  ]
}

Para enviar o template carrossel, ver /docs/messages (campo carousel).

Resposta 201: o template criado (mesmo shape do GET), com metaId e status retornados pela Meta.

curl -X POST https://api.wablastmessage.com/v1/templates \
-H "Authorization: Bearer wak_sua_chave" \
-H "Content-Type: application/json" \
-d '{
  "name": "boas_vindas",
  "category": "MARKETING",
  "language": "pt_BR",
  "components": [{ "type": "BODY", "text": "Olá {{1}}, bem-vindo!" }]
}'

PUT /v1/templates/{id}

Edita um template (não pode estar PENDING).

PUT /v1/templates/{id} 200400401404409422429

Path: id (obrig.).

Body (JSON): ao menos um de:

{ "category": "UTILITY", "components": [] }

Após editar, o status volta a PENDING (re-aprovação Meta).

Tentar editar template com status PENDING retorna 400 TEMPLATE_PENDING — aguarde a Meta aprovar/rejeitar antes.


DELETE /v1/templates/{id}

Remove um template (Meta + banco).

DELETE /v1/templates/{id} 200401404409422429

Resposta 200:

{ "success": true }

404 da Meta é tratado como idempotente (template já removido na Meta → trata como sucesso).


POST /v1/templates/sync

Puxa os templates aprovados da Meta para o banco (upsert/revive + prune dos que sumiram).

POST /v1/templates/sync 200400401404409422429

Body (JSON):

{ "account_id": "ckv..." }

account_id opcional (default = conexão padrão).

Resposta 200:

{ "synced": 3, "updated": 5, "pruned": 1 }
CampoSignificado
syncedcriados no banco
updatedjá existiam, atualizados
prunedsoft-deletados (sumiram da Meta)
Pular para o conteúdo