API WhatsApp · Referencia Interativa
API ONLINE

WhatsApp API Reference

Documentacao interativa gerada a partir da spec OpenAPI 3.1. Clique em qualquer endpoint para ver parametros, exemplos de request e response. Copie com um clique.

--
ENDPOINTS
--
CATEGORIAS
3
MODOS DE CONEXAO
120s
TTL PAIRING CODE
AUTH
Autenticacao
Todas as rotas exigem o token de API no header Authorization: {seu_token} (sem prefixo "Bearer "). Exceto /whatsapp/qrcode/{token} que e publico. Tokens sao gerados no painel do usuario.
BASH
# Header correto: Authorization + token direto (SEM "Bearer") curl -X POST https://apifacil.dev/api/v1/whatsapp/enviar-mensagem \ -H "Authorization: SEU_TOKEN_AQUI" \ -H "Content-Type: application/json" \ -d '{"mensagem":"Ola","telefone":"5511999999999"}'
Erro comum: Enviar Authorization: Bearer SEU_TOKEN retorna 401. O middleware valida o token direto no header — nao use prefixo "Bearer ".
CONN
3 Modalidades de Conexao
Escolha o melhor metodo para seu caso
1 · QR Code
POST /iniciar → GET /qrcode → escanear
2 · Pairing Code
POST /solicitar-pareamento → digitar codigo no celular
3 · Importar Sessao
POST /importar-sessao → conecta automatico
1
QR Code (tradicional)
Conexao por escanear codigo — ideal para onboarding manual
Plano: Todos Tempo: ~30s

O usuario abre o WhatsApp do celular, vai em Configuracoes › Aparelhos conectados › Conectar aparelho e escaneia o QR Code exibido pela API. A cada chamada de /iniciar um novo QR Code e gerado (validade ~60s, renova automaticamente).

1
Criar instancia
POST /instancia/criar
2
Iniciar sessao (gera QR)
POST /{id}/iniciar
3
Poll QR Code
GET /{id}/qrcode
4
Exibir QR para usuario escanear
5
Verificar status
GET /{id}/status

Exemplo completo em JavaScript

JAVASCRIPT · FLUXO COMPLETO
// 1. Iniciar sessao (gera QR Code no Redis) await fetch('https://apifacil.dev/api/v1/whatsapp/instancia/14/iniciar', { method: 'POST', headers: { 'Authorization': 'Bearer SEU_TOKEN' } }); // 2. Poll QR Code a cada 3s ate obter async function obterQRCode() { for (let i = 0; i < 20; i++) { const res = await fetch('https://apifacil.dev/api/v1/whatsapp/instancia/14/qrcode', { headers: { 'Authorization': 'Bearer SEU_TOKEN' } }); const json = await res.json(); if (json.data?.qrcode) { // data.qrcode = "data:image/png;base64,iVBOR..." document.getElementById('qr-img').src = json.data.qrcode; return; } await new Promise(r => setTimeout(r, 3000)); } } // 3. Verificar status apos escanear async function verificarStatus() { const res = await fetch('https://apifacil.dev/api/v1/whatsapp/instancia/14/status', { headers: { 'Authorization': 'Bearer SEU_TOKEN' } }); const json = await res.json(); // json.data.status_banco = "connected" | "disconnected" | "inactive" if (json.data.status_banco === 'connected') { console.log('Conectado!'); } }
Dica: O QR Code expira em ~60 segundos. Se expirar, chame /iniciar novamente para gerar um novo. O microservico renova automaticamente enquanto a sessao estiver aberta.
2
Pairing Code (codigo de pareamento)
Conexao por codigo de 8 digitos — ideal para integracoes server-to-server e onboarding sem camera
Plano: Todos TTL: 120s Formato: 8 chars (ABC12345)

O parceiro envia o numero de telefone do cliente. A API limpa credenciais antigas, inicia a sessao e solicita o codigo ao WhatsApp. O cliente digita o codigo manualmente no celular: Configuracoes › Aparelhos conectados › Conectar com codigo de telefone. O codigo expira em 120 segundos.

Importante: Nao e necessario chamar /iniciar antes — o endpoint /solicitar-pareamento ja limpa credenciais antigas (close-session tipo=2) e inicia a sessao automaticamente. Se voce chamar /iniciar antes, pode conflitar com a sessao recem-iniciada.
1
Solicitar codigo
POST /{id}/solicitar-pareamento
body: {"telefone":"5511999999999"}
2
API limpa credenciais
close-session tipo=2
3
API inicia sessao
start-session
4
API pede codigo ao WhatsApp
request-pairing-code
5
Retorna codigo
"W4NQJMRD" (8 chars)
6
Cliente digita no celular
Config › Aparelhos › Conectar com codigo

Formato do telefone

O telefone deve conter DDI + DDD + numero, apenas digitos, 10 a 15 caracteres. Regex validado: ^\d{10,15}$.

EXEMPLOFORMATOVALIDO?
5511999999999DDI+DDD+numeroSIM
55119999999911 digitosSIM
11999999999sem DDINAO (10 digitos ok mas sem DDI pode falhar)
+55 11 99999-9999com mascaraNAO (regex rejeita)

Exemplo completo em JavaScript (com polling)

JAVASCRIPT · FLUXO COMPLETO
// 1. Solicitar codigo de pareamento async function solicitarPareamento(instanciaId, telefone) { const res = await fetch( `https://apifacil.dev/api/v1/whatsapp/instancia/${instanciaId}/solicitar-pareamento`, { method: 'POST', headers: { 'Authorization': 'Bearer SEU_TOKEN', 'Content-Type': 'application/json' }, body: JSON.stringify({ telefone }) // "5511999999999" } ); const json = await res.json(); if (json.error) { throw new Error(json.message); } // json.data = { pairing_code: "W4NQJMRD", expira_em_segundos: 120 } return json.data; } // 2. Mostrar codigo para cliente digitar no celular const { pairing_code, expira_em_segundos } = await solicitarPareamento(14, '5511999999999'); console.log(`Codigo: ${pairing_code} (expira em ${expira_em_segundos}s)`); // > "Codigo: W4NQJMRD (expira em 120s)" // Cliente vai no celular: Config › Aparelhos conectados › Conectar com codigo // 3. Poll de status para saber quando conectar async function aguardarConexao(instanciaId, timeoutMs = 120000) { const start = Date.now(); while (Date.now() - start < timeoutMs) { const res = await fetch( `https://apifacil.dev/api/v1/whatsapp/instancia/${instanciaId}/status`, { headers: { 'Authorization': 'Bearer SEU_TOKEN' } } ); const json = await res.json(); if (json.data?.status_banco === 'connected') { console.log('Conectado com sucesso!'); return true; } await new Promise(r => setTimeout(r, 3000)); // a cada 3s } return false; // timeout } const conectou = await aguardarConexao(14); if (!conectou) { console.log('Codigo expirou. Solicite um novo.'); } // 4. (Opcional) Recuperar codigo atual do Redis const res = await fetch( 'https://apifacil.dev/api/v1/whatsapp/instancia/14/codigo-pareamento', { headers: { 'Authorization': 'Bearer SEU_TOKEN' } } ); const json = await res.json(); // json.data = { pairing_code: "W4NQJMRD", expirado: false } // se expirado: { pairing_code: null, expirado: true }

Troubleshooting

SINTOMA
CAUSA / SOLUCAO
"Erro ao solicitar codigo de pareamento"
Microservico offline ou nao respondeu em 10s. Verifique se o servidor da instancia esta acessivel. Tente novamente.
"Microservico nao retornou o codigo"
WhatsApp recusou o pareamento. Possiveis causas: numero invalido, numero sem conta WhatsApp, ou sessao anterior nao foi fechada corretamente. Aguarde 30s e tente novamente.
Codigo retornado mas cliente nao consegue digitar
Codigo expirou (120s). Solicite um novo via /solicitar-pareamento. Nao use /codigo-pareamento para gerar novo — ele so consulta o Redis.
Status fica "connecting" para sempre
Cliente digitou codigo errado ou nao confirmou no celular. Peça para refazer o fluxo. Se persistir, chame /desconectar e recomece.
"Sessao ja esta ativa. Desconecte antes..."
Instancia ja conectada. Se quer re-parear, chame POST /{id}/desconectar antes.
telefone invalido (422)
Regex ^\d{10,15}$ rejeitou. Envie apenas digitos, com DDI+DDD+numero. Ex: "5511999999999".
Quando usar Pairing Code vs QR Code?
Pairing Code: integracoes server-to-server, onboarding remoto (sem camera), apps mobile que mandam o codigo via push.
QR Code: onboarding presencial, web apps com camera, fluxo manual.
3
Importar Sessao (WebAuth)
Importa credenciais exportadas pela extensao WhatsApp Session Extractor — ideal para migrar sessoes entre instancias sem re-escanear
Plano: Todos Max: 512KB Auto-connect

O parceiro instala a extensao WhatsApp Session Extractor (Chrome/Firefox) no navegador onde a sessao WhatsApp Web ja esta logada. A extensao extrai as credenciais criptograficas (identityKey, account, registrationId, noiseCandidates, signedPreKey) em formato JSON. Esse JSON e enviado para a API, que repassa ao microservico Baileys — a instancia conecta automaticamente, sem precisar de QR Code ou codigo.

Vantagem principal: Nao exige que o usuario tenha o celular em maos. Ideal para migrar uma sessao WhatsApp Web ja logada para a API sem precisar re-escanear — util para onboarding de clientes que ja usam WhatsApp Web.
1
Cliente instala extensao
WhatsApp Session Extractor
2
Abre WhatsApp Web logado
web.whatsapp.com
3
Clica em "Exportar Sessao"
Baixa arquivo .json
4
Envia JSON para API
POST /{id}/importar-sessao
5
API valida estrutura
validarShapeSessaoImportada()
6
Instancia conecta sozinha
nao precisa /iniciar

Estrutura do JSON (campos validados)

A API valida que o JSON tem os campos minimos que o Baileys precisa. Se faltar qualquer um, retorna 422 com mensagem explicando que o arquivo foi gerado pela extensao errada.

CAMPOTIPOOBRIGATORIO?DESCRICAO
identityKey.privatestringSIMChave privada de identidade
identityKey.publicstringSIMChave publica de identidade
account.detailsstringSIMDetalhes da conta
account.accountSignatureKeystringSIMChave de assinatura da conta
registrationIdnumberSIMID de registro (numerico)
noiseCandidatesarraySIMCandidatos noise (nao pode ser vazio)
signedPreKey.privatestringSIMChave privada pre-assinada
signedPreKey.signaturestringSIMAssinatura pre-assinada

Exemplo completo em JavaScript

JAVASCRIPT · FLUXO COMPLETO
// 1. Cliente envia o arquivo .json exportado pela extensao const fileInput = document.getElementById('session-file'); const file = fileInput.files[0]; // Valide antes de enviar (max 512KB) if (file.size > 524288) { alert('Arquivo muito grande (max 512KB)'); return; } if (file.type !== 'application/json') { alert('Apenas arquivos JSON sao aceitos'); return; } // 2. Ler conteudo do arquivo const sessionData = await file.text(); // 3. Validar que e um JSON valido antes de enviar try { JSON.parse(sessionData); } catch (e) { alert('Arquivo JSON invalido'); return; } // 4. Enviar para a API const res = await fetch( 'https://apifacil.dev/api/v1/whatsapp/instancia/14/importar-sessao', { method: 'POST', headers: { 'Authorization': 'Bearer SEU_TOKEN', 'Content-Type': 'application/json' }, body: JSON.stringify({ session_data: sessionData }) } ); const json = await res.json(); if (json.error) { // Possiveis erros: // "Sessao ja esta ativa. Desconecte antes de importar." // "session_data e obrigatorio (JSON maximo 512KB)" // "JSON da sessao incompleto. Use o arquivo gerado pela extensao..." console.error(json.message); return; } console.log(json.message); // > "Sessao importada com sucesso. Aguardando conexao." // 5. Poll de status (conecta automaticamente em ~5-10s) async function aguardarConexao(instanciaId) { for (let i = 0; i < 30; i++) { const res = await fetch( `https://apifacil.dev/api/v1/whatsapp/instancia/${instanciaId}/status`, { headers: { 'Authorization': 'Bearer SEU_TOKEN' } } ); const json = await res.json(); if (json.data?.status_banco === 'connected') { console.log('Sessao importada e conectada!'); return true; } await new Promise(r => setTimeout(r, 2000)); } return false; } const ok = await aguardarConexao(14);

Exemplo em PHP (Laravel)

PHP · LARAVEL HTTP
// Recebe upload do cliente e envia para a API $sessionData = $request->file('session_file')->getContent(); // Valida tamanho antes if (strlen($sessionData) > 524288) { return back()->with('error', 'Arquivo muito grande (max 512KB)'); } $response = Http::withToken('SEU_TOKEN') ->post('https://apifacil.dev/api/v1/whatsapp/instancia/14/importar-sessao', [ 'session_data' => $sessionData, ]); if ($response->successful()) { $data = $response->json(); // $data['message'] = "Sessao importada com sucesso. Aguardando conexao." }

Troubleshooting

SINTOMA
CAUSA / SOLUCAO
"JSON da sessao incompleto..."
Faltam campos obrigatorios (identityKey, account, registrationId, noiseCandidates, signedPreKey). O arquivo nao foi gerado pela extensao WhatsApp Session Extractor — use a extensao correta.
"JSON da sessao invalido"
O json_decode() falhou. Arquivo corrompido ou truncado. Re-exporte pela extensao.
"session_data e obrigatorio (JSON maximo 512KB)"
Campo vazio ou arquivo maior que 512KB. O tamanho inclui todo o JSON string.
"Sessao ja esta ativa..."
Instancia ja conectada. Chame POST /{id}/desconectar antes de importar.
Importa mas status fica "disconnected"
Credenciais expiradas ou invalidas (WhatsApp logoutou a sessao). Re-exporte pela extensao e tente novamente.
"Erro ao importar sessao" (500)
Microservico offline ou timeout (300s). Verifique o servidor da instancia.
Conecta mas cai depois de alguns minutos
WhatsApp detectou sessao duplicada (ainda logada em outro lugar). Desconecte WhatsApp Web no celular antes de importar.

QR Code vs Pairing Code vs Importar Sessao

CRITERIOQR CodePairing CodeImportar Sessao
Requer celular em maosSIMSIMNAO
Requer cameraSIMNAONAO
Requer WhatsApp Web logadoNAONAOSIM
Requer extensao browserNAONAOSIM
Tempo medio de conexao~30s~15s~5-10s
Migrar sessao existenteNAONAOSIM
Onboarding server-to-serverNAOSIMSIM
Onboarding mobile appSIMSIMNAO
Atencao: Apos importar a sessao, NAO use o WhatsApp Web no mesmo navegador — o WhatsApp pode detectar sessao duplicada e deslogar uma das duas. Sempre desconecte WhatsApp Web no celular antes de importar.
Carregando endpoints
HOOK
Webhooks
Eventos enviados para sua URL

Configure via PUT /whatsapp/configuracao/{id} (apenas planos pagos). O microservico envia POST para sua URL com Content-Type: application/json e User-Agent: API Facil/1.0, timeout 10s.

URLs de webhook (roteamento)

CAMPODESTINOUSA?
webhook_urlMensagens privadas + eventos de interacaoSIM
webhook_grupoMensagens de grupoSIM
webhook_statusMudanca de status da instanciaNAO — campo existe mas nao envia
webhook_ativoLiga/desliga TODOS os webhooksSIM (master switch)
webhook_status existe no banco e na API mas nao e usado para envio — apenas webhook_url e webhook_grupo recebem POST. Eventos de status da instancia sao disparados pelo microservico internamente (nao via webhook configuravel).

Evento 1: whatsapp_insert (mensagem enviada/recebida)

Disparado para todo evento de mensagem — enviada pelo voce, recebida do contato, ou erro de envio. Roteado para webhook_url (privado) ou webhook_grupo (grupo).

JSON · whatsapp_insert
{ "event": "whatsapp_insert", "id": 12345, "message_id": "3EB0123456789", "instancia_id": 14, "instancia_codigo": "INST001", "mensagem": "Ola, tudo bem?", "caption": null, "origem": "5511999999999", "destino": "5511888888888", "enviado": true, "erro": false, "tipo_envio": "MENSAGEM_ENVIADA", "grupo": false, "lido": false, "respondido": false, "reproduzido": false, "status": "ENVIADO", "origem_chamada": "API", "created_at": "2025-07-01T10:00:00-03:00", "pushName": "Joao Silva", "is_business": false, "remote_jid": "5511999999999@s.whatsapp.net", "remote_jid_alt": null, "participant": null, "participant_alt": null, "jid_contato": null, "eh_lid": false, "numero_telefone_origem": "5511999999999", "numero_telefone_destino": "5511888888888", "numero_origem_lid": null, "numero_destino_lid": null, "addressing_mode": "pn", "responder_para": null }

Valores de tipo_envio (whatsapp_insert)

TIPO_ENVIODESCRICAO
MENSAGEM_ENVIADATexto enviado por voce
MENSAGEM_RECEBIDATexto recebido do contato
MENSAGEM_ERROFalha ao enviar texto
IMAGEM_ENVIADAImagem enviada
AUDIO_ENVIADOAudio enviado
VIDEO_ENVIADOVideo enviado
DOCUMENTO_ENVIADOArquivo enviado
BOTAO_ENVIADOMensagem com botao enviada
LOCALIZACAO_ENVIADALocalizacao enviada
MENSAGEM_GRUPO_RECEBIDOMensagem recebida em grupo
MENSAGEM_GRUPO_ENVIADOMensagem enviada em grupo

Evento 2: whatsapp_update (interacao)

Disparado quando uma mensagem e marcada como lida, respondida ou reproduzida. Sempre vai para webhook_url. Para desativar, set ativar_atualizacoes_interacao=false no config_json.

JSON · whatsapp_update
{ "event": "whatsapp_update", "id": 12345, "mensagem_id": "3EB0123456789", "instancia_id": 14, "codigo": "INST001", "mensagem": "Ola, tudo bem?", "origem": "5511999999999", "destino": "5511888888888", "tipo_envio": "MENSAGEM_ENVIADA", "grupo": false, "respondido": false, "lido": true, "reproduzido": false, "erro": false, "enviado": true, "origem_chamada": "API", "numero_origem_lid": null, "numero_destino_lid": null, "is_business": false, "created_at": "2025-07-01T10:00:00-03:00", "updated_at": "2025-07-01T10:05:00-03:00" }

Sistema de retry (whatsapp_insert)

Apenas whatsapp_insert tem retry automatico. whatsapp_update nao tem (so 1 tentativa).

TENTATIVAQUANDOSTATUS
1Imediato (apos evento)Se 2xx: enviado. Se falha: agenda retry.
2+1 minutoSe 2xx: enviado. Se falha: agenda retry.
3+5 minutosSe 2xx: enviado. Se falha: agenda retry.
4+30 minutosSe 2xx: enviado. Se falha: marca erro permanente.

O cron do microservico roda a cada minuto e processa ate 50 retries por rodada. Historico de tentativas fica em webhook_payloads e webhook_responses na notificacao. Para reenviar manualmente: POST /whatsapp/notificacao/reprocessar-webhook com body {"id": 12345}.

Exemplo: receptor de webhook em Node.js (Express)

JAVASCRIPT · EXPRESS
const express = require('express'); const app = express(); app.use(express.json()); app.post('/webhook', (req, res) => { const { event, id, mensagem, origem, destino, tipo_envio, enviado, grupo } = req.body; if (event === 'whatsapp_insert') { console.log(`Mensagem ${enviado ? 'enviada' : 'recebida'}: ${mensagem}`); console.log(`De: ${origem} Para: ${destino} Tipo: ${tipo_envio}`); if (tipo_envio === 'MENSAGEM_RECEBIDA') { // Processar mensagem recebida do contato } } else if (event === 'whatsapp_update') { console.log(`Update: lido=${req.body.lido} respondido=${req.body.respondido}`); } // Responder 2xx rapidamente (timeout 10s no remetente) res.status(200).json({ received: true }); }); app.listen(3000, () => console.log('Webhook receiver on :3000'));

Exemplo: receptor em PHP (Laravel)

PHP · LARAVEL
// routes/web.php Route::post('/webhook', function (Request $req) { $event = $req->input('event'); // "whatsapp_insert" | "whatsapp_update" $id = $req->input('id'); $mensagem = $req->input('mensagem'); $origem = $req->input('origem'); $tipoEnvio = $req->input('tipo_envio'); if ($event === 'whatsapp_insert' && $tipoEnvio === 'MENSAGEM_RECEBIDA') { // Processar mensagem recebida Log::info("Mensagem recebida de {$origem}: {$mensagem}"); } return response()->json(['received' => true], 200); });
Dica: Seu receptor deve responder 2xx em ate 10 segundos (timeout do remetente). Se demorar mais, o microservico considerara falha e agendara retry. Processamento pesado deve ser assincrono (fila/queue).
PLAN
Planos e Recursos
RecursoFreePago
Mensagens de textoSIMSIM
WebhooksNAOSIM
Envio de imagensNAOSIM
Envio de videosNAOSIM
Envio de arquivosNAOSIM
Envio de audiosNAOSIM
Botoes interativosNAOSIM