Referência da API

Endpoints, autenticação, schemas de request/response, e códigos de erro.

Autenticação

Todas as rotas /api/whatsapp/* requerem autenticação por chave de API:

curl https://api.vzdapplication.com/api/whatsapp/channels \
  -H "Authorization: Bearer vzd_SUA_CHAVE_AQUI"

A chave está em seu header Authorization como Bearer <chave>. Nunca a revele.

Base URL

https://api.vzdapplication.com

Conexão de Canais WhatsApp

POST /api/whatsapp/connect-sessions

Cria uma sessão de conexão para o cliente autentificar seu WhatsApp Business.

Autenticação

Requer: Chave de API (Authorization: Bearer) + Entitlement channel.connect

Request

CampoTipoDescrição
onboarding_mode *enumCOEXISTENCE ou CLOUD_API_ONLY. Padrão: COEXISTENCE
return_urlstringURL aonde redirecionar após conexão concluída (até 2048 caracteres)
client_referencestringID interno seu para rastreamento (até 128 caracteres)
labelstringRótulo para identificar este canal no painel (até 120 caracteres)

Response 201

{
  "connect_session_id": "550e8400-e29b-41d4-a716-446655440000",
  "connect_url": "https://app.vzdapplication.com/connect?session=...",
  "expires_at": "2024-01-15T14:00:00.000Z"
}

Erros

StatusCódigoDescrição
402payment_requiredSem crédito ou plano suspenso
429too_many_requestsLimite de criação de sessões excedido
GET /api/whatsapp/connect-sessions/:connectSessionId

Consulta o status de uma sessão de conexão.

Response 200

{
  "connect_session_id": "550e8400-e29b-41d4-a716-446655440000",
  "client_reference": "seu-id-interno",
  "status": "CONNECTED|FAILED|EXPIRED",
  "failure_reason": null,
  "channel": {
    "channel_id": "ch_xxx",
    "waba_id": "100234567890",
    "phone_number_id": "5511999887766",
    "phone_number": "+55 (11) 99988-7766",
    "display_name": "Beleza ABC",
    "status": "CONNECTED"
  }
}
DELETE /api/whatsapp/connect-sessions/:connectSessionId

Revoga uma sessão antes da conclusão. Útil para timeout.

Response

204 (sem conteúdo)

POST /api/whatsapp/connect-origins

Registra origem de retorno (webhook). Precisa fazer isso antes de conectar qualquer cliente.

Request

CampoTipo
origin *string URL (até 255 caracteres)
label *string (até 120 caracteres)

Response 201

{
  "id": "org_550e8400-e29b-41d4-a716-446655440000",
  "origin": "https://seu-dominio.com.br",
  "label": "Produção",
  "created_at": "2024-01-15T10:00:00.000Z"
}
GET /api/whatsapp/connect-origins

Lista origens registradas.

Response 200

{
  "origins": [
    {
      "id": "org_xxx",
      "origin": "https://seu-dominio.com.br",
      "label": "Produção",
      "created_at": "2024-01-15T10:00:00.000Z"
    }
  ]
}
DELETE /api/whatsapp/connect-origins/:originId

Revoga uma origem de retorno registrada. Deixa de receber webhooks nesse endpoint.

Response

204 (sem conteúdo)

Canais e Histórico

GET /api/whatsapp/channels

Lista canais WhatsApp conectados da sua conta.

Response 200

{
  "data": [
    {
      "id": "ch_xxx",
      "wabaId": "100234567890",
      "phoneNumberId": "5511999887766",
      "phoneNumber": "+55 (11) 99988-7766",
      "displayName": "Beleza ABC",
      "status": "CONNECTED|DEGRADED|REVOKED",
      "onboardingMode": "COEXISTENCE",
      "webhookSubscribedAt": "2024-01-15T10:00:00.000Z",
      "lastErrorMessage": null,
      "createdAt": "2024-01-15T09:55:00.000Z"
    }
  ]
}
GET /api/whatsapp/messages

Lista mensagens recebidas e echoes (respostas pelo celular). Até 30 por padrão, ordenadas por recência.

Query Parameters

ParâmetroTipoPadrãoDescrição
phone_number_idstring—Filtrar por número (opcional)
limitint30Quantos registros (máximo 100)

Response 200

{
  "data": [
    {
      "wamid": "wamid.HhBmRGVmAUH7...",
      "from": "5511987654321",
      "direction": "INBOUND|OUTBOUND",
      "origin": "CLOUD_API|BUSINESS_APP_ECHO",
      "type": "text|image|document|audio|video|location|interactive",
      "text": "Olá! Qual é o horário?",
      "mediaUrl": "https://...",
      "timestamp": "2024-01-15T10:00:00.000Z",
      "sentAt": "2024-01-15T10:00:00.000Z"
    }
  ]
}

Importante: BUSINESS_APP_ECHO = cliente respondeu pelo celular. Certifique-se de filtrar antes de entregar a uma IA, senão ela responderá a si mesma.

GET /api/whatsapp/statuses

Status de entrega das mensagens enviadas (enviada, entregue, lida, falha).

Response 200

{
  "data": [
    {
      "wamid": "wamid.HhBmRGVmAUH7...",
      "status": "SENT|DELIVERED|READ|FAILED",
      "timestamp": "2024-01-15T10:00:05.000Z",
      "occurredAt": "2024-01-15T10:00:05.000Z",
      "failureReason": null
    }
  ]
}

Envio de Mensagens

POST /api/whatsapp/messages/text

Envia mensagem de texto livre. Só funciona dentro da janela de 24 horas desde a última mensagem do cliente.

Request

CampoTipoDescrição
phone_number_id *stringSeu número (ex: "5511999887766")
to *stringNúmero do cliente (ex: "5511987654321")
body *stringTexto da mensagem (até 4096 caracteres)
preview_urlbooleanGerar preview de URLs? Padrão: false
reply_to_wamidstringResponder a qual mensagem? (opcional)
idempotency_keystringChave de idempotência (8-128 caracteres, opcional)
syncbooleanEsperar resposta (201)? Padrão: false (202 + job_id)

Response 202 (async padrão)

{
  "status": "queued",
  "job_id": "job_550e8400-e29b-41d4-a716-446655440000"
}

Response 201 (sync=true, primeira vez)

{
  "status": "sent",
  "wamid": "wamid.HhBmRGVmAUH7AglMkZGVzQ==",
  "message_id": "msg_2024_001",
  "recipient_wa_id": "5511987654321"
}

Erros

StatusCódigo
402payment_required — sem crédito
404channel_not_found — número não existe em sua conta
409channel_revoked — cliente revogou acesso
POST /api/whatsapp/messages/template

Envia mensagem template. Funciona em qualquer momento — templates são pré-aprovados.

Request

CampoTipo
phone_number_id *string
to *string
template_name *string (nome do template)
language_code *string (ex: "pt_BR")
componentsarray (parâmetros do template)
syncboolean (padrão: false)

Response

Idêntico a /messages/text

Gestão de Templates

POST /api/whatsapp/templates

Cria novo template na conta do cliente. Fica em revisão na Meta por minutos até horas.

Request

CampoTipo
phone_number_id *string
name *string (use versão: confirmacao_v2)
language *string (ex: "pt_BR")
category *enum: MARKETING, UTILITY, AUTHENTICATION
components *array
allow_category_changeboolean (padrão: false)

Response 201

{
  "name": "confirmacao_v2",
  "language": "pt_BR",
  "status": "PENDING_REVIEW",
  "id": "123456789",
  "category": "UTILITY"
}

Armadilha: Template apagado bloqueia o nome por 30 dias. Use nome versionado (v1, v2…) desde o início.

GET /api/whatsapp/templates

Lista templates da conta.

Query Parameters

ParâmetroTipo
phone_number_id *string
limitint (padrão: 20, máximo: 100)
statusAPPROVED, PENDING_REVIEW, REJECTED, PAUSED, DISABLED
namestring (buscar por nome)
afterstring (paginação)

Response 200

{
  "data": [
    {
      "name": "confirmacao_v2",
      "language": "pt_BR",
      "status": "APPROVED",
      "id": "123456789",
      "category": "UTILITY"
    }
  ],
  "paging": { "next_cursor": "xxx" }
}
DELETE /api/whatsapp/templates

Apaga template. Nome fica bloqueado por 30 dias.

Query Parameters

ParâmetroTipo
phone_number_id *string
name *string

Response 200

{
  "deleted": true,
  "name": "confirmacao_v2",
  "name_reuse_blocked_days": 30
}

Webhook de Retorno

PUT /api/whatsapp/webhook

Registra URL de webhook. Você recebe POST assinado com cada evento.

Request

CampoTipo
webhook_url *https://seu-dominio (obrigatório HTTPS)

Response 200

{
  "webhook_url": "https://seu-dominio.com.br/webhooks/whatsapp",
  "webhook_secret": "sk_whk_abc123..."
}

O segredo aparece uma única vez. Guarde com segurança — não há rota para ler de volta.

DELETE /api/whatsapp/webhook

Remove webhook. Você volta a depender de polling.

Response

204 (sem conteúdo)

Códigos de Erro

CódigoHTTPSignificado
invalid_request400Validação falhou (campo obrigatório faltando, formato inválido)
unauthorized401Chave de API inválida ou ausente
invalid_signature401Assinatura HMAC do webhook inválida — valide usando o segredo
payment_required402Sem crédito ou plano suspenso. Veja checkout_url na resposta
forbidden403Acesso negado (ex: webhook URL interna)
channel_not_found404Número não existe em sua conta
connect_session_not_found404Sessão de conexão não existe ou nunca foi criada
channel_authorization_rejected409Crítico: Token do canal foi recusado pela Meta. Reconecte o número.
channel_revoked409Cliente revogou permissão de acesso no Gerenciador de Negócios da Meta
connect_session_in_progress409Sessão de conexão já está em progresso — espere conclusão
email_already_registered409E-mail já registrado
connect_session_gone410Sessão de conexão expirou — crie uma nova
too_many_requests429Rate limit excedido. Espere (ver header Retry-After)
template_catalog_unavailable503Meta API indisponível, tente novamente em instantes
graph_api_error502Meta retornou erro. Veja campo context da resposta