Skip to main content
Toda entrega é um POST com corpo JSON no mesmo envelope. Os campos do topo não mudam; só o data varia por tipo de evento.

Envelope

string
Tipo do evento. Um dos valores em Tipos de evento.
string
ID do evento. Use como chave de idempotência — a entrega é at-least-once.
  • É o mesmo valor do header webhook-id e não muda entre reentregas do mesmo evento.
  • Se vários webhooks da instância assinam o evento, todos recebem o mesmo id.
  • Eventos diferentes têm ids diferentes — inclusive o DELIVERED e o READ da mesma mensagem.
  • É um valor opaco: não extraia informação dele. Para se referir à mensagem, use data.messageId.
string
ID da instância na Zapfy (o número conectado) que gerou o evento.
string
Quando o evento aconteceu, em ISO 8601 UTC, com resolução de segundo. Em mensagens e status, é a hora registrada pelo WhatsApp; em eventos de conexão e de QR Code, a hora em que a Zapfy registrou o evento. Não muda entre reentregas.
object
Payload específico do evento, descrito abaixo.

Tipos de evento

São também os nomes que você usa em events ao cadastrar um webhook.

Convenções

  • Campo sem valor é omitido. Ele nunca vem como null nem como string vazia: confira se está presente (if (data.quotedMessageId)). Cada campo abaixo diz quando está presente.
  • Objetos específicos de um tipo (media, location, reaction…) só aparecem no tipo de mensagem ao qual pertencem.
  • Valores de enum (DIRECT, READ, BANNED…) são em maiúsculo e fazem parte do contrato.
  • Telefones vêm só com dígitos, com o código do país e sem + (5511999998888). São o número exatamente como está registrado no WhatsApp, que nem sempre é do jeito que você digitou — veja o aviso abaixo.

Objetos comuns

chat

A conversa: onde o evento aconteceu e onde você responde.
  • Numa conversa direta, o chat é o contato: no MESSAGE.RECEIVED, o contato que escreveu; no MESSAGE.SENT, o contato para quem você enviou.
  • Num grupo, o chat é o grupo.
string
DIRECT (uma pessoa) · GROUP · STATUS (status/stories) · BROADCAST (lista de transmissão) · NEWSLETTER (canal).
string
O identificador da conversa no WhatsApp. Passe-o em to para responder — a API aceita como está. Sempre no mesmo formato: 5511988887777@s.whatsapp.net (uma pessoa), 81896604192873@lid (uma pessoa cujo número o WhatsApp esconde), 120363012345678901@g.us (um grupo — o mesmo id devolvido por GET /v1/groups), status@broadcast (status), …@newsletter (um canal). Use-o como chave da conversa no seu sistema.
string
O telefone da pessoa, só com dígitos. Presente só em conversas DIRECT, e só quando o WhatsApp expõe o número. Use-o para filtrar ou comparar por número.

sender

Quem escreveu a mensagem, quando outra pessoa escreveu: numa conversa direta, é o próprio contato; num grupo, o participante que escreveu. O sender não vem quando fromMe é true — em conversas diretas e em grupos. Uma mensagem que você escreveu é sempre do seu próprio número, então o fromMe basta.
string
O identificador no WhatsApp de quem escreveu, no mesmo formato do chat.id (…@s.whatsapp.net, ou …@lid quando o WhatsApp esconde o número). Aceito em to.
string
O telefone da pessoa. Presente só quando o WhatsApp expõe o número.
string
O nome de perfil que o contato configurou no próprio WhatsApp — não o nome salvo nos seus contatos. Presente só quando o contato tem nome de perfil.
O WhatsApp esconde o telefone de alguns contatos. Quando isso acontece, phone não vem e o id é um identificador …@lid, que continua funcionando em to. Para filtrar por número, use phone, nunca id.
Celulares brasileiros e o 9º dígito. Linhas de celular brasileiras mais antigas estão registradas no WhatsApp sem o 9º dígito. Você pode enviar para 5544997075632 e receber o MESSAGE.SENT com chat.phone 554497075632 (e chat.id 554497075632@s.whatsapp.net) — é a mesma pessoa.
  • Para responder, use sempre o chat.id exatamente como chegou.
  • Para comparar com os números do seu sistema, leve isso em conta: num celular brasileiro, trate 55 + DDD + 8 dígitos e 55 + DDD + 9 + 8 dígitos como o mesmo número.

MESSAGE.RECEIVED / MESSAGE.SENT

Texto numa conversa direta:
Imagem num grupo, respondendo a outra mensagem:
string
ID da mensagem no WhatsApp — o mesmo valor que os endpoints de envio devolvem. Use para reagir, editar, apagar, citar e para casar com MESSAGE.STATUS_UPDATED.
boolean
true em MESSAGE.SENT (o seu número escreveu), false em MESSAGE.RECEIVED.
object
A conversa. Veja chat.
object
Quem escreveu. Presente só quando fromMe é false. Veja sender.
string
Tipo do conteúdo. Veja a tabela abaixo.
string
O texto da mensagem, ou a legenda da mídia. Presente só quando há texto ou legenda.
string
ID da mensagem que esta responde. Presente só quando a mensagem é uma resposta.
O MESSAGE.SENT dispara quando o WhatsApp aceita uma mensagem do seu número. Ele traz o mesmo messageId que o endpoint de envio devolveu; mensagens digitadas no celular ou em outro aparelho conectado também chegam aqui. Editar ou apagar uma mensagem não gera evento.

Tipos de mensagem

object
Presente em IMAGE, VIDEO, AUDIO, DOCUMENT e STICKER. Descreve o arquivo; o arquivo em si não vem no webhook. Cada subcampo só aparece quando é conhecido.
object
Presente em LOCATION.
object
Presente em CONTACT.
object
Presente em REACTION.
object
Presente em POLL.
object
Presente em BUTTON_REPLY.
Mensagem com botões, como o MESSAGE.SENT de um envio feito pela API:
Quando o contato toca numa opção, chega um MESSAGE.RECEIVED com messageType BUTTON_REPLY, e o buttonReply.id é o ID que você definiu para aquela opção.

MESSAGE.STATUS_UPDATED

O que aconteceu com uma mensagem que você enviou: entregue, lida ou não enviada. O passo “enviada” é o próprio evento MESSAGE.SENT.
string[]
As mensagens a que este status se refere. É uma lista porque um único recibo pode cobrir várias mensagens — o contato abre a conversa e lê todas de uma vez, e um único READ pode trazer muitos IDs.
string
DELIVERED (✓✓, chegou no aparelho) · READ (✓✓ azul) · FAILED (não foi enviada). A ordem é DELIVERED < READ: ignore um status anterior ao que você já tem. FAILED é final: aquela mensagem não chegou ao WhatsApp e não vai chegar.
string
Por que não foi enviada, como código estável — use para decidir e para agrupar. Presente só quando status é FAILED.
  • NOT_ON_WHATSAPP — o número não tem WhatsApp. Não adianta reenviar.
  • MEDIA_DOWNLOAD_FAILED — não deu para baixar a mídia da URL (fora do ar, 404). Corrija a URL e reenvie.
  • MEDIA_INVALID — o arquivo não serve para esse tipo de mensagem. Envie outro arquivo.
  • MEDIA_UPLOAD_FAILED — o WhatsApp recusou o upload da mídia. Reenvie.
  • INVALID_MESSAGE — o WhatsApp não aceita esse conteúdo ali (ex.: documento em canal, mais de 3 botões de resposta). Ajuste a mensagem.
  • INSTANCE_LOGGED_OUT — a instância foi deslogada com a mensagem na fila. Conecte de novo e reenvie.
  • INSTANCE_DELETED — a instância foi apagada com a mensagem na fila.
  • WHATSAPP_ERROR — o WhatsApp recusou o envio, mesmo depois das novas tentativas. Veja message.
string
O que aconteceu, numa frase com o erro original (em inglês) — para mostrar ou registrar. Presente só quando status é FAILED.
  • Falha de envio: o envio respondeu 202 com o messageId, mas a mensagem não saiu. O FAILED traz esse mesmo messageId, e não há MESSAGE.SENT para ela. Uma mensagem enviada nunca recebe FAILED. Se a instância só desconectou, as mensagens na fila esperam e saem quando ela reconectar — não viram FAILED.
  • O status traz só os IDs das mensagens. A conversa e o destinatário são os do MESSAGE.SENT da mesma mensagem: ligue os dois pelo messageIds.
  • Grupos: o status significa que a mensagem chegou a ele para pelo menos um participante. O DELIVERED e o READ chegam uma vez cada por mensagem, não uma vez por participante.
  • Confirmação de leitura: o READ só chega se a confirmação de leitura estiver ligada nos dois números — o seu e o do contato.
  • Só os recibos do contato. Quando o seu próprio número lê uma mensagem que recebeu (abrindo a conversa no celular), nenhum webhook de status é enviado.

CONNECTION.UPDATED

string
Presente em CONNECTED: o telefone do número conectado.
string
Em CONNECTED: o nome de perfil do número conectado. Ausente logo depois do primeiro pareamento, enquanto o WhatsApp ainda não mandou o nome.
string
Presente em BANNED: SENT_TO_TOO_MANY_PEOPLE (mensagens demais para quem não tem o seu número salvo) · BLOCKED_BY_USERS (muita gente bloqueou você) · CREATED_TOO_MANY_GROUPS (grupos demais com quem não tem o seu número) · SENT_TOO_MANY_SAME_MESSAGE (a mesma mensagem para gente demais) · BROADCAST_LIST (mensagens demais para uma lista de transmissão) · UNKNOWN.
number
Em BANNED: segundos até o fim do ban. Ausente quando o WhatsApp não informa.

QRCODE.UPDATED

O fluxo de pareamento, para quando você monta a sua própria tela de conexão.
O pareamento termina com CONNECTION.UPDATED e status: CONNECTED — é o sinal para fechar a sua tela de pareamento.
string
O QR Code como data URL (PNG em base64), pronto para usar num <img>.
string
O conteúdo do QR Code, para quando você mesmo desenha o QR.
number
Qual QR Code é este na tentativa de pareamento atual, começando em 1.
number
Quantos QR Codes são gerados antes do EXPIRED. Ausente significa sem limite.