# APIFacil WhatsApp API v2 > API v2 do WhatsApp. Autenticacao via header `Authorization: seu_token` (SEM Bearer). Todas as rotas usam middleware auth.api (Sanctum) com rate limiting. ## Base URL ``` Producao: https://apifacil.dev/api/v2 Local: http://localhost:8001/api/v2 ``` ## Autenticacao Todas as rotas publicas requerem o header `Authorization` com o token de API direto (sem prefixo `Bearer`): ``` Authorization: seu_token_aqui Content-Type: application/json ``` Tokens sao gerados no painel do usuario. Rate limiting aplicado em todos os endpoints. ## Response Padrao Todas as respostas seguem o formato: ```json { "error": false, "message": "Mensagem descritiva", "data": { ... } } ``` Erros: `error: true`, `message` com descricao, HTTP status code apropriado (400, 401, 403, 404, 422, 429, 500). ## Especificacao Formal - **OpenAPI 3.1**: `/v2/openapi.json` — spec completa para gerar clients automaticamente. ## 3 Modalidades de Conexao ### 1. QR Code (tradicional) Fluxo: `POST /whatsapp/instancia/{id}/iniciar` -> poll `GET /whatsapp/instancia/{id}/qrcode` -> escanear com celular. QR Code expira em ~60s. Chame /iniciar novamente para gerar novo. ### 2. Pairing Code (telefone) `POST /whatsapp/instancia/{id}/solicitar-pareamento` com body `{"phone":"5511999999999"}`. Retorna `pairingCode` (8 caracteres alfanumericos, ex: W4NQJMRD, expira em 120s). Nao chame /iniciar antes — o endpoint inicia a sessao automaticamente. Cliente digita no celular: Configuracoes > Aparelhos conectados > Conectar com codigo. Telefone: DDI+DDD+numero, apenas digitos, 10 a 15 chars. ### 3. Importar Sessao `POST /whatsapp/instancia/{id}/importar-sessao`. Importa uma sessao previamente pareada do armazenamento PostgreSQL. A sessao conecta automaticamente. ## Endpoints por Categoria ### Instancias | Metodo | Path | Descricao | |--------|------|-----------| | POST | `/whatsapp/instancia/criar` | Criar instancia (com configuracao e fila padrao) | | GET | `/whatsapp/instancia/listar` | Listar instancias (com configuracao, fila, servidor) | | GET | `/whatsapp/instancia/{id}/detalhes` | Detalhes (aceita ID numerico ou codigo UUID) | | GET | `/whatsapp/instancia/{id}/status` | Status (banco + microservico, inclui QR Code e pairing code) | | DELETE | `/whatsapp/instancia/{id}` | Deletar instancia (irreversivel) | ### Conexao | Metodo | Path | Descricao | |--------|------|-----------| | POST | `/whatsapp/instancia/{id}/iniciar` | Iniciar sessao (gera QR Code) | | GET | `/whatsapp/instancia/{id}/qrcode` | Obter QR Code (base64) | | POST | `/whatsapp/instancia/{id}/solicitar-pareamento` | Solicitar Pairing Code (body: phone) | | GET | `/whatsapp/instancia/{id}/codigo-pareamento` | Obter codigo atual | | POST | `/whatsapp/instancia/{id}/importar-sessao` | Importar sessao do PostgreSQL | | POST | `/whatsapp/instancia/{id}/pausar` | Pausar sessao (mantem credenciais) | | POST | `/whatsapp/instancia/{id}/desconectar` | Desconectar (remove credenciais, re-pareamento necessario) | ### Mensagens | Metodo | Path | Descricao | |--------|------|-----------| | POST | `/whatsapp/mensagem/{id}/enviar` | Enviar mensagem (text, image, video, audio, document, location) | | GET | `/whatsapp/instancia/{id}/mensagens` | Listar mensagens (paginado, filtros: per_page, data_inicial, data_final, tipo) | | GET | `/whatsapp/instancia/{id}/mensagens/{mensagemId}` | Consultar mensagem especifica (com webhook logs) | ### Configuracoes | Metodo | Path | Descricao | |--------|------|-----------| | PUT | `/whatsapp/instancia/{id}/configuracao` | Atualizar webhook e config_json | ### Utilitarios | Metodo | Path | Descricao | |--------|------|-----------| | POST | `/whatsapp/instancia/{id}/verificar-numero` | Verificar se numero tem WhatsApp (body: phone) | | POST | `/whatsapp/instancia/{id}/foto-perfil` | Obter foto de perfil (body: phone) | ## Enviar Mensagem `POST /whatsapp/mensagem/{id}/enviar` — `{id}` e o ID numerico ou codigo UUID da instancia. ### Parametros | Campo | Tipo | Obrigatorio | Descricao | |-------|------|-------------|-----------| | `to` | string | Sim | Telefone (DDI+DDD+numero) ou JID | | `type` | string | Sim | text, image, video, audio, document, location | | `content` | string | type=text | Conteudo da mensagem de texto | | `mediaUrl` | uri | type=midia | URL publica da midia (image, video, audio, document). Alternativa a mediaBase64. | | `mediaBase64` | string | type=midia | Midia em base64 (alternativa a mediaUrl). Aceita prefixo `data:...;base64,` ou base64 puro. | | `caption` | string | nao | Legenda da midia (image, video, document) | | `fileName` | string | nao | Nome do arquivo (document) | | `latitude` | number | type=location | Latitude | | `longitude` | number | type=location | Longitude | | `locationName` | string | nao | Nome do local | | `address` | string | nao | Endereco do local | | `enqueue` | boolean | nao (default true) | true=enfileira com delay, false=envio imediato | ### Exemplos Texto: ```json { "to": "5511999999999", "type": "text", "content": "Ola, como vai?" } ``` Imagem (URL publica): ```json { "to": "5511999999999", "type": "image", "mediaUrl": "https://exemplo.com/imagem.jpg", "caption": "Foto do produto" } ``` Imagem (base64): ```json { "to": "5511999999999", "type": "image", "mediaBase64": "iVBORw0KGgoAAAANSUhEUgAA...", "caption": "Foto do produto" } ``` Audio (base64): ```json { "to": "5511999999999", "type": "audio", "mediaBase64": "//uQAAAAAAAAAAAAAAAA..." } ``` Documento (URL publica): ```json { "to": "5511999999999", "type": "document", "mediaUrl": "https://exemplo.com/arquivo.pdf", "fileName": "contrato.pdf", "caption": "Segue o contrato" } ``` Documento (base64): ```json { "to": "5511999999999", "type": "document", "mediaBase64": "JVBERi0xLjAKMSAwIG9iajw8...", "fileName": "contrato.pdf", "caption": "Segue o contrato" } ``` Localizacao: ```json { "to": "5511999999999", "type": "location", "latitude": -23.5613, "longitude": -46.6565, "locationName": "Escritorio", "address": "Av. Paulista, 1000" } ``` Envio imediato (sem fila): ```json { "to": "5511999999999", "type": "text", "content": "Mensagem urgente", "enqueue": false } ``` ### Responses **200** (envio direto, enqueue=false): ```json { "error": false, "message": "Mensagem enviada", "data": { "messageId": "3EB0123456789ABCDEF", "status": "sent" } } ``` **202** (enfileirado, enqueue=true padrao): ```json { "error": false, "message": "Mensagem enfileirada para processamento", "data": { "sessionId": "inst_a1b2c3d4-...", "to": "5511999999999", "type": "text", "queued": true } } ``` **400** (instancia nao conectada): ```json { "error": true, "message": "Instancia nao esta conectada. Inicie a sessao primeiro.", "data": null } ``` ## Status da Instancia `GET /whatsapp/instancia/{id}/status` retorna: ```json { "error": false, "message": "Status da instancia", "data": { "id": 1, "status_banco": "connected", "status_microservico": "connected", "qr_code": null, "pairing_code": null, "reconnect_attempts": 0, "last_connected_at": "2026-07-24T12:00:00.000000Z" } } ``` Quando aguardando QR Code, `qr_code` contem o QR Code em base64 e `status_microservico` = "qr_code". Quando aguardando pareamento, `pairing_code` contem o codigo e `status_microservico` = "pairing". ## Criar Instancia `POST /whatsapp/instancia/criar`: ```json { "nome": "WhatsApp Comercial", "servidor_id": null } ``` Response 201: ```json { "error": false, "message": "Instancia criada com sucesso", "data": { "id": 1, "nome": "WhatsApp Comercial", "codigo": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "session_id": "inst_a1b2c3d4-e5f6-7890-abcd-ef1234567890", "phone_number": null, "status": "disconnected", "configuracao": { "id": 1, "instancia_id": 1, "webhook_url": null, "webhook_ativo": false, "webhook_grupo": null, "config_json": {} }, "fila": { "id": 1, "instancia_id": 1, "nome": "Instancia 1", "queue_name": "apifacil:whatsapp_v2:queue:instance:1", "tipo": "instancia", "concorrencia": 1, "delay_min_ms": 1000, "delay_max_ms": 3000, "schedule_enabled": false, "schedule_start_hour": 8, "schedule_end_hour": 22, "ativo": true } } } ``` `servidor_id` e opcional (UUID do servidor). Se vazio, o sistema atribui automaticamente o servidor com menor carga. ## Configuracao `PUT /whatsapp/instancia/{id}/configuracao`: ```json { "webhook_url": "https://meusite.com/webhook", "webhook_ativo": true, "webhook_grupo": "https://meusite.com/webhook-grupo", "config_json": { "tipos_envio": ["text", "image"] } } ``` `config_json.tipos_envio`: lista de tipos que NAO disparam webhook (bloqueados). Ex: `["text", "image"]` bloqueia webhooks para mensagens de texto e imagem. Response 200: ```json { "error": false, "message": "Configuracao atualizada", "data": { "id": 1, "instancia_id": 1, "webhook_url": "https://meusite.com/webhook", "webhook_ativo": true, "webhook_grupo": "https://meusite.com/webhook-grupo", "config_json": { "tipos_envio": ["text", "image"] } } } ``` ## Filas e Processamento Por padrao (`enqueue=true`), mensagens sao enfileiradas em Redis (BullMQ) com delay aleatorio configuravel por instancia (delay_min_ms a delay_max_ms). O response retorna 202 imediatamente com `queued: true`. Para envio imediato (`enqueue=false`), o microservico envia direto e retorna 200 com `messageId` e `status`. A fila de cada instancia tem: - **concorrencia**: limite de envios simultaneos (default: 1) - **delay_min_ms / delay_max_ms**: delay aleatorio entre envios (default: 1000-3000ms) - **schedule_enabled**: janela de horario para envio (default: desativado) - **schedule_start_hour / schedule_end_hour**: horario de inicio e fim (default: 8-22) ## Webhooks Configurados via `PUT /whatsapp/instancia/{id}/configuracao`. O microservico envia POST para `webhook_url` (mensagens privadas) ou `webhook_grupo` (grupos) com Content-Type: application/json. `webhook_ativo` e o master switch (false desliga TODOS os webhooks). Eventos: `message_sent` (mensagem enviada por voce), `message_received` (mensagem recebida do contato), `message_status` (atualizacao de status: delivered/read/played) e `message_error` (erro ao enviar). O campo `from_me` indica a direcao. O campo `status` no payload indica o estado atual (pending, sent, delivered, read, played, failed). Em replies, os campos `quoted_message_id` e `quoted_participant` identificam a mensagem original. ## Códigos de Erro | HTTP | Descricao | |------|-----------| | 400 | Instancia nao conectada ou parametros invalidos | | 401 | Token invalido ou ausente | | 403 | Limite do plano excedido | | 404 | Instancia ou mensagem nao encontrada | | 422 | Validacao de dados falhou | | 429 | Rate limit excedido | | 500 | Erro interno ou microservico indisponivel | ## Diferencas da v1 - Novo microservico (TypeScript) - Armazenamento de sessao em PostgreSQL - Filas individuais por instancia com delay aleatorio configuravel - Schedule (janela de horario) por fila - API REST limpa sem dependencias da v1 - Tabelas separadas (whatsapp_v2_*) - Porta do microservico: 8009 (v2) vs 8008 (v1) - Instancias da v1 nao sao compativeis com v2 (re-pareamento necessario) ## Links - OpenAPI JSON: `/v2/openapi.json` - Painel: `http://localhost:8001/login`