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-ide 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 oDELIVEREDe oREADda 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
nullnem 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: noMESSAGE.RECEIVED, o contato que escreveu; noMESSAGE.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.MESSAGE.RECEIVED / MESSAGE.SENT
Texto numa conversa direta: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.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.
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.MESSAGE.SENT de um envio feito pela API:
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 eventoMESSAGE.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. Vejamessage.
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
202com omessageId, mas a mensagem não saiu. OFAILEDtraz esse mesmomessageId, e não háMESSAGE.SENTpara ela. Uma mensagem enviada nunca recebeFAILED. Se a instância só desconectou, as mensagens na fila esperam e saem quando ela reconectar — não viramFAILED. - O status traz só os IDs das mensagens. A conversa e o destinatário são os do
MESSAGE.SENTda mesma mensagem: ligue os dois pelomessageIds. - Grupos: o status significa que a mensagem chegou a ele para pelo menos um
participante. O
DELIVEREDe oREADchegam uma vez cada por mensagem, não uma vez por participante. - Confirmação de leitura: o
READsó 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.