Neste documento você irá aprender todos os passos necessários para se enviar uma mensagem de WhatsApp através da biblioteca Messagefy.
Você sairá deste OnBoarding sabendo perfeitamente como:Cadastrar novas contas para sua Organização usando a sua APIKEY
Cadastrar o canal de WebHook, necessários para enviar dados para o seu sistema
Cadastrar o canal de Whatsapp, que será usado para conectar o celular
Conectar usando QRCode ou PairCode
Receber o QRCode e PairCode para conexão
Enviar sua primeira Mensagem
1) Solicite um EndPoint de Sandbox e sua APIKEY de Organização#
Antes de começar, você precisa ter em mãos uma chave de api de organização e o EndPoint do Messagefy.Exemplo:
EndPoint Principal da API: http://localhost:7777
Organization APIKEY: org_019c0020-2309-7dea-a7d6-1163bb1ddc7aFaça o primeiro teste de acesso, usando o método /api/v1/me, que retorna os dados a respeito da sua chave de API:Use o método POST /api/v1/admin/account para criar uma nova conta para sua organização.
Com a criação da nova conta, uma APIKEY exclusiva para uso da conta será automaticamente criada.Anote o accountId para usar na próxima etapa
5) Busque a APIKEY da Conta que foi criada#
Ou, busque a APIKEY de uma conta já existente com /api/v1/admin/apikey?accountId.
A criação da uma nova conta leva à criação de uma APIKEY exclusiva para a conta recem criada, com prefixo acc_, que será usada para todos os procedimentos que envolvem a conta. Nesta etapa vamos descobrir a API_KEY exclusiva da conta.Para listar as APIKEYs de contas você ainda deve-se usar a APIKEY da organização.
Anote a APIKEY da Conta para as próximas etapas.
O canal de WebHook serve para enviar todos as mensagens e respostas de comandos para o seu sistema. Ele é essencial para:Receber mensagens que foram enviadas para o WhatsApp registrado.
Receber respostas de comandos (geração de QRCode, PairCode, Envio de Mensagens, etc).
Acompanhar a situação da sessão do Whatsapp no Messagefy.
Perceba que a partir daqui você deve usar a APIKEY da conta e não da organização.
curl --location --request POST 'http:
--header 'api-key: acc_019bfb71-0000-0000-0000-41cd513cacca' \
--header 'Content-Type: application/json' \
--data '{
"name": "Canal webhook",
"description": "webhook feedback",
"channelType": "http-sender",
"accountId": "019bfb71-0d7b-715a-af8c-84b3e58e73c3",
"parameters": {
"url": "https://webhook.site/d124df93-a65a-44c4-9d5b-22ceb986dac6"
}
}'
em name e description sempre informe algo que informe claramente que se trata do canal de WebHook.
accountId é o código da conta que foi criado no procedimento 5
channelType é sempre http-sender para o canal de WebHook
Informe em parameters.url o endereço http onde vc deseja receber os WebHooks
É indispensável que vc tenha acesso aos dados que serão enviados para o endereço de WebHook (parameters.url).
Caso esteja apenas testando a rotina, informe um endereço onde você possa receber temporariamente os payloads. Ex: Gere e use uma url do webhook.site . {
"channelId": "019c04a3-3eee-7dcc-9964-530445ee28c6",
"feedbackChannelId": null,
"name": "Canal webhook",
"description": "webhook feedback",
"account": {
"accountId": "019c0496-9ad6-70cb-b5fa-326e4f970fa5",
"name": "MessageFy",
"description": "Conta principal do MessageFy",
"status": {
"accountStatusId": 2,
"name": "Ativo",
"icon": null,
"description": "Pronto para uso",
"canManageChildObjects": true,
"canSendAndReceiveMessage": true
},
"organization": {
"organizationId": "019c0496-96de-7df6-91b0-124c3ff0b930",
"name": "ChatGuru",
"description": "Organização do ChatGuru",
"status": {
"organizationStatusId": 2,
"name": "Ativo",
"icon": null,
"description": "Pronto para uso",
"canManageChildObjects": true,
"canSendAndReceiveMessage": true
}
}
},
"channelType": {
"channelTypeId": 4,
"key": "http-sender",
"name": "HTTP API & WebHook Sender",
"description": "",
"requiredFeedbackChannel": false,
"canBeFeedbackChannel": true,
"requireReceiverChannel": false,
"canBeReceiverChannel": false
},
"status": {
"channelStatusId": 4,
"name": "Running",
"icon": null,
"description": "Pronto para uso",
"canSendAndReceiveMessage": true,
"canConfigure": false
},
"provider": {
"providerId": "019c0496-8e9a-71b0-ad0c-2afbbaa86f44",
"key": "http-sender",
"name": "http-sender",
"description": null,
"icon": null,
"channelTypeId": 0,
"channelTypeKey": null,
"channelTypeName": null,
"priority": 1,
"dockerImage": null,
"platform": null,
"maxChannelsPerInstance": null,
"requiresCluster": false,
"requiresMessageBroker": false,
"requiresDatabase": false
},
"parameters": {
"url": "https://webhook.site/#!/view/d124df93-a65a-44c4-9d5b-22ceb986dac6"
},
"devices": null
}
Anote o channelId que foi gerado para o canal de WebHook
Este canal é utilizado para conexão do Celular ao Whatsapp, sendo que mensagens recebidas, respostas de comandos, QRCodes e PairCodes de conexão e outros eventos serão enviados para canal de WebHook que foi criado na etapa 6.
Portanto, é necessário informar neste canal o channelId que foi gerado na etapa anterior.curl --location --request POST 'http:
--header 'api-key: acc_019c0496-aa45-7de6-800a-9f3788edcb60' \
--header 'Content-Type: application/json' \
--data '{
"name": "Whatsapp Web",
"description": "Whatsapp usando o Whatsmeow",
"channelType": "whatsapp-web",
"accountId": "019c0496-9ad6-70cb-b5fa-326e4f970fa5",
"feedbackChannelId": "019bfb74-0554-7682-8bde-31f677e3df23",
"parameters": {}
}'
em name e description sempre informe algo que informe claramente que se trata do canal do Whatsapp.
accountId é o código da conta que foi criado no procedimento 5
channelType é sempre whatsapp-web
Informe em feedbackChannelId o channelId do canal de WebHook
{
"channelId": "019c04a9-b6ab-79af-bf09-713fc1ed282a",
"feedbackChannelId": "019c04a3-3eee-7dcc-9964-530445ee28c6",
"name": "Whatsapp Web",
"description": "Whatsapp não oficial Whatsmeow",
"account": {
"accountId": "019c0496-9ad6-70cb-b5fa-326e4f970fa5",
"name": "MessageFy",
"description": "Conta principal do MessageFy",
"status": {
"accountStatusId": 2,
"name": "Ativo",
"icon": null,
"description": "Pronto para uso",
"canManageChildObjects": true,
"canSendAndReceiveMessage": true
},
"organization": {
"organizationId": "019c0496-96de-7df6-91b0-124c3ff0b930",
"name": "ChatGuru",
"description": "Organização do ChatGuru",
"status": {
"organizationStatusId": 2,
"name": "Ativo",
"icon": null,
"description": "Pronto para uso",
"canManageChildObjects": true,
"canSendAndReceiveMessage": true
}
}
},
"channelType": {
"channelTypeId": 2,
"key": "whatsapp-web",
"name": "WhatsApp Não Oficial",
"description": "Instâncias que se comportam como uma instância do Whatsapp Web",
"requiredFeedbackChannel": true,
"canBeFeedbackChannel": false,
"requireReceiverChannel": false,
"canBeReceiverChannel": false
},
"status": {
"channelStatusId": 4,
"name": "Running",
"icon": null,
"description": "Pronto para uso",
"canSendAndReceiveMessage": true,
"canConfigure": false
},
"provider": {
"providerId": "019c0496-8d97-784a-9efb-a999ec9ca95f",
"key": "whatsmeow",
"name": "whatsmeow",
"description": null,
"icon": null,
"channelTypeId": 0,
"channelTypeKey": null,
"channelTypeName": null,
"priority": 1,
"dockerImage": null,
"platform": null,
"maxChannelsPerInstance": null,
"requiresCluster": false,
"requiresMessageBroker": false,
"requiresDatabase": false
},
"parameters": {},
"devices": null
}
O channelId deste canal é o utilizado para enviar mensagens, solicitar QRCode de conexão, etc. Todos os procedimentos com o Whatsapp dependem deste channelId.
8) Status do Whatsapp#
Agora que vc já tem um canal de Whatsapp configurado, você pode solicitar a conexão, enviar comandos e mensagens. Mas antes, vamos verificar a situação da sua instância que é responsável por gerenciar esta conexão.Perceba que a partir daqui vc sempre vai usar o APIKEY da Conta e o channelId do canal de Whatsapp!
Os resultados de requisições realizados para o canal de Whatsapp são sempre um packageID. O resultado real do comando será enviado para o endereço de WebHook que foi informado no canal WebHook.
Payload enviado para o seu WebHook:#
9) Solicitar conexão do Whatsapp#
Agora vamos conectar a instância do Messagefy ao Whatsapp. Para isso podemos user um comando solicitando a conexão via QRCode ou via PairCode.curl --location --request POST 'http:
--header 'api-key: acc_019c0496-aa45-7de6-800a-9f3788edcb60' \
--header 'Content-Type: application/json' \
--data '{
"channelId": "019c04a9-b6ab-79af-bf09-713fc1ed282a",
"content": {
"commandType": "SESSION_START",
"type": "SESSION_START_QR_CODE"
}
}'
A solicitação de conexão usando QRCode dispensa qualquer parâmetro adicional. Basta informar corretamente o channelId.
curl --location --request POST 'http:
--header 'api-key: acc_019c0496-aa45-7de6-800a-9f3788edcb60' \
--header 'Content-Type: application/json' \
--data '{
"channelId": "019c04a9-b6ab-79af-bf09-713fc1ed282a",
"content": {
"commandType": "SESSION_START",
"type": "SESSION_START_PAIR_CODE",
"mobileNumber": "5511987654321"
}
}'
A solicitação de conexão usando PairCode exige que seja informado o número do celular do Whatsapp que você deseja conectar (atributo mobileNumber com DDI, DDD e número do telefone, apenas números e sem espaços ou outros caracteres), além de informar corretamente o channelId.
{
"packageId": "41620d24-3d1a-4d9a-8dcb-50be17d33f86"
}
Os resultados de requisições realizados para o canal de Whatsapp são sempre um packageID. O resultado real do comando será enviado para o endereço de WebHook que foi informado no canal WebHook.
Response enviado para o seu WebHook:#
No caso do QRCode, o Whatsapp continuará enviando novos QRCode por aproximadamente 4 minutos caso o anterior não tenha sido lido.
Você receberá um WebHook de cada um destes novos QRCodes e um novo deve ser exibido para seu usuário para que ele realize a conexão.
Caso o usuário não se conecte#
O usuário tem aproximadamente 4 minutos para informar o PairCode ou ler o QRCode. Caso isso não seja feito um evento INSTANCE_USER_CONNECT_TIMEOUT será enviado para o seu WebHook.{
"packageId":"019c04ff-37a1-735e-874c-d681bb09f9c5",
"channelId":"019c04a9-b6ab-79af-bf09-713fc1ed282a",
"organizationID":"019c0496-96de-7df6-91b0-124c3ff0b930",
"organizationName":null,
"accountId":"019c0496-9ad6-70cb-b5fa-326e4f970fa5",
"accountName":null,
"correlationId":null,
"content":{
"type":"INSTANCE_USER_CONNECT_TIMEOUT",
"timestamp":"2026-01-28T14:26:00.7139198+00:00"
},
"timestamp":"2026-01-28T14:26:00.7370856+00:00",
"providerMetadata":null
}
Caso o usuário não se conecte e vc receba o INSTANCE_USER_CONNECT_TIMEOUT, você devera solicitar um novo PairCode ou QRCode novamente e repetir o processo.9.5) Autorização por Passkey (Shortcake)#
Em algumas contas, após o QRCode ser lido (ou o PairCode ser informado no celular), o WhatsApp exige uma etapa adicional de autorização via passkey (WebAuthn) antes de finalizar o pareamento. Essa cerimônia é gerenciada dentro do web.whatsapp.com e é conhecida internamente como Shortcake.Rollout atual: essa etapa hoje só é exigida para contas dentro do rollout do WhatsApp (EU / UK). Contas fora do rollout — incluindo a grande maioria dos números BR — pulam essa etapa e vão direto do QRCode/PairCode para o CONNECTED do passo 8. Se, alguns segundos após a leitura, o PASSKEY_REQUEST não chegar no seu WebHook, o pareamento está seguindo o fluxo tradicional.
A bridge apenas repassa os eventos de passkey e aceita o comando PASSKEY_CONFIRM. Ela não implementa timers, timeouts, lembretes, auto-abort nem auto-dismiss — a responsabilidade por controlar tempo, exibir UI e coletar a confirmação humana é sempre do consumidor da API.
9.5.1) Recebendo PASSKEY_REQUEST no seu WebHook#
Assim que o servidor do WhatsApp exigir a passkey durante o pareamento, um evento PASSKEY_REQUEST será enviado para o seu WebHook. O payload de dados é vazio — o próprio tipo é o sinal para exibir a UI de autorização.{
"packageId":"019c0600-1122-70aa-8bbb-cccdddeeef00",
"channelId":"019c04a9-b6ab-79af-bf09-713fc1ed282a",
"organizationID":"019c0496-96de-7df6-91b0-124c3ff0b930",
"organizationName":null,
"accountId":"019c0496-9ad6-70cb-b5fa-326e4f970fa5",
"accountName":null,
"correlationId":null,
"content":{
"type":"PASSKEY_REQUEST",
"commandType":"PASSKEY_REQUEST",
"timestamp":"2026-07-01T22:00:00.0000000+00:00"
},
"timestamp":"2026-07-01T22:00:00.1234567+00:00",
"providerMetadata":null
}
Ao receber PASSKEY_REQUEST, redirecione o usuário para https://web.whatsapp.com/ e oriente que ele clique em "Continuar" para autorizar a passkey usando o dispositivo dele.
A cerimônia WebAuthn só pode ser executada por páginas com origem whatsapp.com (o navegador exige rpId: "whatsapp.com"). Painéis externos — inclusive o painel da Chat Guru / Messagefy — não podem invocar navigator.credentials.get(...) diretamente; qualquer tentativa gera SecurityError. O único caminho é o próprio WhatsApp Web.
9.5.2) Recebendo PASSKEY_CONFIRMATION no seu WebHook#
Depois que o usuário completa a autorização em web.whatsapp.com, a bridge dispara PASSKEY_CONFIRMATION contendo um código de verificação legível. Esse código serve exclusivamente para conferência visual entre o que aparece em web.whatsapp.com e o que é apresentado ao usuário — ele nunca é reenviado para a bridge / MessageFy. O que acontece depois depende do campo skipHandoffUX (ver abaixo).{
"packageId":"019c0601-2233-70bb-8ccc-ddeeff001122",
"channelId":"019c04a9-b6ab-79af-bf09-713fc1ed282a",
"organizationID":"019c0496-96de-7df6-91b0-124c3ff0b930",
"organizationName":null,
"accountId":"019c0496-9ad6-70cb-b5fa-326e4f970fa5",
"accountName":null,
"correlationId":null,
"content":{
"type":"PASSKEY_CONFIRMATION",
"code":"1234-5678",
"skipHandoffUX":false,
"commandType":"PASSKEY_CONFIRMATION",
"timestamp":"2026-07-01T22:00:10.0000000+00:00"
},
"timestamp":"2026-07-01T22:00:10.2345678+00:00",
"providerMetadata":null
}
code: string no formato XXXX-XXXX. Use apenas para conferência visual com o código exibido em web.whatsapp.com. O código nunca volta para a bridge / MessageFy no PASSKEY_CONFIRM — o payload de retorno contém apenas abort.
skipHandoffUX: bool que indica se a própria bridge já concluiu o pareamento automaticamente. Determina se o próximo passo (9.5.3) é necessário:true → a bridge já chamou SendPasskeyConfirmation internamente e o pareamento está sendo finalizado de forma automática. Não é necessário enviar PASSKEY_CONFIRM; basta aguardar o CONNECTED. Exibir o code é opcional (útil para transparência / auditoria); se houver UI de conferência, faça o dismiss automático quando o CONNECTED chegar, pois ele pode chegar no meio da exibição.
false → a bridge está bloqueada aguardando o consumidor. Você precisa exibir o code ao usuário para conferência visual e enviar PASSKEY_CONFIRM (ver 9.5.3) para confirmar ou cancelar.
9.5.3) Enviar PASSKEY_CONFIRM confirmando ou cancelando#
Este passo só é necessário quando skipHandoffUX = false. Quando skipHandoffUX = true, a bridge já concluiu o pareamento automaticamente e enviar PASSKEY_CONFIRM é redundante — apenas aguarde o CONNECTED. Enviar o comando fora de hora pode até atrapalhar o fluxo caso a bridge já tenha desconectado / reconectado.
Após o usuário conferir o código, envie o comando PASSKEY_CONFIRM de volta para a bridge, pelo mesmo endpoint dos demais comandos do canal. Note que o payload contém apenas abort — o código não é reenviado, ele existe somente para a comparação visual descrita em 9.5.2.curl --location --request POST 'http:
--header 'api-key: acc_019c0496-aa45-7de6-800a-9f3788edcb60' \
--header 'Content-Type: application/json' \
--data '{
"channelId": "019c04a9-b6ab-79af-bf09-713fc1ed282a",
"content": {
"commandType": "PASSKEY_CONFIRM",
"type": "PASSKEY_CONFIRM",
"abort": false
}
}'
curl --location --request POST 'http:
--header 'api-key: acc_019c0496-aa45-7de6-800a-9f3788edcb60' \
--header 'Content-Type: application/json' \
--data '{
"channelId": "019c04a9-b6ab-79af-bf09-713fc1ed282a",
"content": {
"commandType": "PASSKEY_CONFIRM",
"type": "PASSKEY_CONFIRM",
"abort": true
}
}'
false → conclui o pareamento. O próximo WebHook será o CONNECTED (o mesmo evento descrito no passo 8).
true → cancela o pareamento. O canal volta para desconectado e um novo SESSION_START do passo 9 é necessário para tentar novamente.
Assim como os demais comandos, o retorno imediato é apenas um packageId. O resultado real (CONNECTED ou desconexão) chega no WebHook do canal configurado no passo 6.
9.5.4) Tratamento de erro: PASSKEY_ERROR#
Qualquer falha do fluxo de passkey (cancelamento no WhatsApp Web, erro de WebAuthn, timeout do servidor, etc.) chega no seu WebHook como PASSKEY_ERROR.{
"packageId":"019c0602-3344-70cc-8ddd-ee00112233ff",
"channelId":"019c04a9-b6ab-79af-bf09-713fc1ed282a",
"organizationID":"019c0496-96de-7df6-91b0-124c3ff0b930",
"organizationName":null,
"accountId":"019c0496-9ad6-70cb-b5fa-326e4f970fa5",
"accountName":null,
"correlationId":null,
"content":{
"type":"PASSKEY_ERROR",
"error":"user_cancelled",
"continuation":false,
"commandType":"PASSKEY_ERROR",
"timestamp":"2026-07-01T22:05:00.0000000+00:00"
},
"timestamp":"2026-07-01T22:05:00.9876543+00:00",
"providerMetadata":null
}
error: string com o código / mensagem do erro. Exiba ao usuário.
false → o erro ocorreu antes do usuário confirmar (i.e. antes de PASSKEY_CONFIRM). Basta reapresentar a orientação de autorização, sem reiniciar todo o pareamento.
true → o erro ocorreu depois que o consumidor já tinha enviado PASSKEY_CONFIRM. Nesse caso o pareamento não pôde ser concluído e o usuário precisa reiniciar o processo inteiro — volte ao passo 9 com um novo SESSION_START.
9.5.5) Fluxo resumido desta etapa#
1.
Consumer recebe PASSKEY_REQUEST no WebHook.
2.
Consumer redireciona o usuário para https://web.whatsapp.com/ e orienta clicar em "Continuar".
3.
Usuário autentica com a passkey do dispositivo.
4.
Consumer recebe PASSKEY_CONFIRMATION com o code e o campo skipHandoffUX. A partir daqui o fluxo se divide em dois casos:
Caso A — skipHandoffUX = true (auto-confirmação pela bridge):5a. A bridge já concluiu o pareamento automaticamente; não envie PASSKEY_CONFIRM.
6a. Consumer apenas aguarda CONNECTED (fluxo idêntico ao final do passo 8). Exibir o code é opcional e serve só para transparência / auditoria; se houver UI de conferência, faça o dismiss automático ao receber CONNECTED.
Caso B — skipHandoffUX = false (confirmação humana obrigatória):5b. Consumer exibe o code para o usuário conferir visualmente com o código apresentado em web.whatsapp.com (o código não retorna para a bridge / MessageFy).
6b. Consumer envia PASSKEY_CONFIRM com abort: false (confirmar) ou abort: true (cancelar).
7b. Consumer recebe CONNECTED (fluxo idêntico ao final do passo 8) — ou o canal fica desconectado.
Em qualquer ponto, um PASSKEY_ERROR pode chegar; siga a regra de continuation descrita em 9.5.4 para decidir se basta reapresentar a UI ou se é necessário reiniciar do passo 9.10) Recebendo mensagens#
Com o canal conectado ao Whatsapp, você comecará a receber WebHooks no canal que foi configurado na etapa 6.11) Enviar mensagens#
Todos os detalhes de com enviar mensagens podem ser vistos neste capítulo: