ProtectZapProtectZap
Para todos os produtos

Documentação da API e do MCP

Ligue a ProtectZap ao seu sistema pela API, receba avisos por webhook e opere a conta por MCP. Esta página explica o que vale para todos os produtos; os endereços, avisos e ferramentas de cada um ficam na página do produto.

Produtos

Começo rápido

1. No painel, abra Integrações › Chaves de acesso e clique em Nova chave. Escolha os produtos que a chave pode usar, a permissão (Leitura, ou Leitura e escrita) e a validade. A chave aparece uma vez só: guarde num lugar seguro.

2. Faça a primeira consulta. Por exemplo, os contatos do Disparos:

curl https://www.protectzap.com.br/api/v1/disparos/contatos \
  -H "Authorization: Bearer SUA_CHAVE"

3. Siga para a página do produto que você vai integrar, com os endereços, exemplos e avisos dele.

Chaves e autenticação

Toda chamada leva a chave no cabeçalho Authorization: Bearer pzg_live_....

  • Produtos: a chave vale só para os produtos escolhidos na criação, e só enquanto a conta tem o plano de cada um. Chamar a API de um produto que a chave não inclui é recusado com produto_ausente.
  • Permissão: Leitura só consulta; Leitura e escrita consulta e age. Use a de leitura onde só precisa consultar. Cada endereço diz a permissão que exige.
  • Validade: 30, 90 ou 365 dias. Chave que muda algo vale no máximo 365 dias; a de leitura também pode não vencer. Dá para limitar a chave a uma lista de IPs.
  • A chave completa aparece uma vez, na criação. A ProtectZap guarda só uma impressão dela. Até 10 chaves ativas por conta.
  • Criar e revogar chave avisa o dono no painel, e a chave que muda algo, usada de um IP novo, também.
  • Nunca ponha a chave na URL. Ela fica gravada em log, por isso é revogada na hora em que aparece numa URL.
  • A API é para servidor: chamada feita pelo navegador, de uma página de outro site, é recusada.

O Disparos tem também a Chave de Eventos, criada na própria automação: ela só coloca pessoas na fila daquela automação e não lê nada. Detalhes na página do Disparos.

Formato e ids

Pedidos e respostas em JSON. A resposta tem sempre o mesmo formato:

{ "success": true, "data": { ... } }

{ "success": false, "error": { "codigo": "nao_encontrado", "mensagem": "..." } }

Os ids levam um prefixo que diz o que são. Um id de um tipo no lugar de outro é recusado com id_de_outro_tipo.

PrefixoO que éProduto
num_número da contaTodos
whk_webhookTodos
whe_aviso de webhookTodos
ctt_contatoDisparos
dsp_campanhaDisparos
aut_automaçãoDisparos
evt_evento (uma pessoa na fila de uma automação)Disparos

Datas em ISO 8601 com fuso (2026-11-10T19:00:00-03:00). Horários de regra (janela de envio, recorrência) são de Brasília. Telefones com DDI e DDD, só dígitos.

Simular e repetir com segurança

O que chega às pessoas pode ser conferido antes. Nos Grupos, os endereços marcados com Aceita simular devolvem a prévia com "simular": true no corpo, sem gravar nada; no Disparos, a campanha tem o endereço próprio /simular.

Os endereços que criam algo que chega às pessoas pedem o cabeçalho Idempotency-Key (de 8 a 100 caracteres: letras, números e _ - : ., por exemplo um uuid); cada endereço diz se exige. A mesma chave devolve o mesmo resultado em vez de agir de novo: se a sua chamada cair no meio, repita com a mesma chave sem medo de mandar duas vezes. Os eventos das automações usam o identificador do próprio evento para isso.

Mudanças em algo que pode ter mudado no meio do caminho (o texto de um envio ou de uma campanha rodando) pedem a versao que você leu. Se alguém mexeu depois, a resposta é 409 e você lê de novo.

Limites

Os limites existem para uma chave vazada não virar estrago. Valem para todos os produtos:

  • 120 chamadas por minuto por chave e 300 por conta, somando as chaves. Passou, a resposta é 429 com Retry-After. No Disparos, um lote de contatos ou de eventos conta 1 chamada a cada 10 itens.
  • Corpo de até 1 MB na API e 256 KB no MCP, onde um lote conta uma chamada por mensagem (até 20).
  • 20 chaves inválidas de um mesmo IP em 10 min deixam o IP 15 min sem acesso.
  • A API não acelera nada: os envios seguem o mesmo ritmo e as mesmas regras da tela.

Cada produto tem ainda os seus: a cota de mensagens do mês no Disparos e a cota diária de envios e ações em massa nos Grupos.

Erros

O codigo é fixo e serve para o seu sistema decidir; a mensagem é para gente e pode mudar. Estes valem para todos os produtos; os próprios de cada produto estão na página dele.

StatusCódigoQuando
401nao_autenticadoChave ausente, inválida, vencida ou revogada. A resposta é a mesma nos quatro casos.
401chave_na_urlA chave apareceu na URL. Ela é revogada na hora, porque a URL fica gravada em log: crie outra e mande só no cabeçalho.
403escopo_ausenteA chave é só de leitura e o endereço pede leitura e escrita, ou é uma Chave de Eventos usada fora da automação dela.
403produto_ausenteA chave não inclui o produto do endereço (uma chave só dos Grupos chamando a API de Disparos).
403sem_acessoA conta não tem o plano que dá acesso à API do produto.
403ip_nao_permitidoA chave tem lista de IPs e a chamada veio de outro.
403origem_recusadaA chamada veio de uma página de outro site (navegador). A API é para servidor.
400pedido_invalidoCorpo ou parâmetro inválido. A mensagem diz o que corrigir.
400id_invalidoO id não está no formato do prefixo.
400id_de_outro_tipoUm id de outro tipo no lugar errado (um ctt_ onde se espera dsp_).
400idempotency_key_ausenteO endereço exige o cabeçalho Idempotency-Key e ele não veio, ou veio fora do formato (8 a 100 caracteres: letras, números e _ - : .).
404nao_encontradoNão existe, ou é de outra conta. Em parte dos endereços o código diz o recurso (campanha_nao_encontrada, envio_nao_encontrado, webhook_nao_encontrado); todo 404 quer dizer o mesmo.
409conflitoA situação mudou no meio do caminho (outra edição entrou antes, o item já saiu ou está saindo). Leia de novo antes de repetir.
413pedido_grandeCorpo acima do tamanho máximo.
429limite_excedidoLimite de chamadas por minuto da chave (o cabeçalho Retry-After diz quanto esperar) ou de usos por hora de um recurso, como a IA dos Grupos.
429limite_da_contaLimite de chamadas por minuto da conta, somando as chaves.
429ip_bloqueadoMuitas chaves inválidas deste IP em pouco tempo. Espere o tempo do Retry-After.
502falha_externaO WhatsApp não respondeu como esperado ao pedido. Tente de novo em instantes.
500erro_internoFalha do nosso lado. Tente de novo em instantes; se continuar, fale com o suporte.
503indisponivelNão foi possível conferir a chave ou o limite agora. Tente de novo em instantes.

Webhooks

Um webhook manda um POST para o seu endereço (https público) quando algo acontece. O cadastro é da conta: até 5 por conta, cada um com os avisos que pedir, de qualquer produto que a conta usa. Crie pela tela (Integrações › Webhooks) ou pela API de um dos produtos. O corpo é sempre:

{ "id": "6f1b2c3d-...", "tipo": "disparos.evento.enviado", "criado_em": "2026-11-10T19:41:07.512Z", "dados": { ... } }

O id é o do aviso: na API, o mesmo aviso aparece como whe_ seguido desse id.

Cabeçalhos: X-ProtectZap-Evento (o id, igual ao do corpo), X-ProtectZap-Tipo, X-ProtectZap-Tentativa e X-ProtectZap-Assinatura. Os mesmos valores seguem também nos cabeçalhos X-ProtectGroups-*, para quem já recebia antes.

Confira a assinatura antes de confiar no aviso. Ela é t=<segundos>,v1=<hex>, onde v1 é o HMAC-SHA256 de t.corpo com o segredo do webhook. Use o corpo cru, exatamente como chegou, e recuse horário com mais de 5 minutos:

import crypto from "node:crypto"

function conferirAssinatura(segredo, cabecalho, corpoCru) {
  const p = Object.fromEntries(cabecalho.split(",").map((s) => s.trim().split("=")))
  const t = Number(p.t)
  if (!t || !p.v1 || Math.abs(Date.now() / 1000 - t) > 300) return false
  const esperado = crypto.createHmac("sha256", segredo).update(`${t}.${corpoCru}`).digest()
  const recebido = Buffer.from(p.v1, "hex")
  return recebido.length === esperado.length && crypto.timingSafeEqual(recebido, esperado)
}
  • Responda 2xx em até 10 segundos. Sem isso, tentamos de novo em 1 min, 5 min, 30 min, 2 h, 6 h, 12 h.
  • O mesmo aviso pode chegar mais de uma vez (nova tentativa ou reenvio pelo painel): use o id para descartar o repetido.
  • Um endereço que falha sem parar por 3 dias é desligado e o dono é avisado. Religar entrega o que ficou na fila.
  • Não seguimos redirecionamento e só entregamos para endereço público.
  • O catálogo de avisos de cada produto está na página dele. O botão Testar manda um webhook.teste.

MCP

O servidor MCP (Model Context Protocol) permite que qualquer aplicação compatível, como um aplicativo de IA, consulte e opere a conta com a mesma chave da API. É um servidor só, chamado protectzap: ele mostra as ferramentas dos produtos da chave. Endereço: https://www.protectzap.com.br/api/mcp. Transporte HTTP (Streamable HTTP), sem sessão, com a chave no cabeçalho Authorization: Bearer SUA_CHAVE.

Exemplo de configuração no formato mcpServers, aceito pela maioria das aplicações compatíveis:

{
  "mcpServers": {
    "protectzap": {
      "type": "http",
      "url": "https://www.protectzap.com.br/api/mcp",
      "headers": {
        "Authorization": "Bearer SUA_CHAVE"
      }
    }
  }
}

Nada chega às pessoas sem a sua confirmação. As ferramentas que planejam devolvem o plano e um código; só a ferramenta confirmar executa, com a mesma chave, em até 15 minutos e uma vez. Se o plano mudou entre planejar e confirmar (um número caiu, o público mudou), nada é executado e a aplicação recebe a diferença. Chave de leitura não vê nem chama confirmar.

Textos e nomes que vêm do WhatsApp ou do seu sistema chegam à aplicação marcados como dados: o servidor a instrui a nunca obedecer a algo escrito neles. As ferramentas de cada produto estão na página dele.