# Instalação AstraCalls padrão

Link: [https://github.com/AstraOnlineWeb/AstraCalls/tree/main](https://github.com/AstraOnlineWeb/AstraCalls/tree/main)

git clone [https://github.com/AstraOnlineWeb/AstraCalls.git](https://github.com/AstraOnlineWeb/AstraCalls.git)

# 📞 AstraCalls

<div align="center" dir="auto" id="bkmrk-" style="text-align: justify;"><div class="markdown-heading" dir="auto">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-astracalls)</div></div>**Chamadas de voz e vídeo do WhatsApp em Go puro, direto do navegador — prontas para produção SaaS.**

VoIP nativo (áudio + vídeo, 1:1 e em grupo), gateway **SIP/PBX**, suíte completa de **mensagens**, **disparos**, **webhooks** confiáveis, integração com **Chatwoot** e deploy em **Docker Swarm + Traefik**.

[![Go](https://camo.githubusercontent.com/7710c170a5882bd59254207b461cefd432cbe354f1fb606f0d05ba802da2f44e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f476f2d312e32362b2d3030414444383f6c6f676f3d676f266c6f676f436f6c6f723d7768697465)](https://go.dev) [![React](https://camo.githubusercontent.com/5db4de9dcd72e7b8e95fe25f33f5520c571e9c3f93522d691a10cff804fb795d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f52656163742d31392d3631444146423f6c6f676f3d7265616374266c6f676f436f6c6f723d626c61636b)](https://react.dev) [![whatsmeow](https://camo.githubusercontent.com/b160e70eb028ac43c1f683f9271c8c47222e2da93ec90f4ee68701ba94d5a37e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f77686174736d656f772d566f49502d3235443336363f6c6f676f3d7768617473617070266c6f676f436f6c6f723d7768697465)](https://github.com/tulir/whatsmeow) [![pion](https://camo.githubusercontent.com/82e947cc55c8d21234c4fcc783086b63b7caf192fa636d74cea1cd3cead911fa/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f70696f6e2d5765625254432d464636423642)](https://github.com/pion/webrtc) [![PostgreSQL](https://camo.githubusercontent.com/348c7c9ddb0f7c351756992d7d1c76b22ea265ad50284df24d9afd72069990b0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506f737467726553514c2d31362d3333363739313f6c6f676f3d706f737467726573716c266c6f676f436f6c6f723d7768697465)](https://www.postgresql.org) [![Docker](https://camo.githubusercontent.com/3dc69af93faed41389605a93c7ec3a222228c8ab1c7fdc678ce2bc88e0219f3a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446f636b65722d616d64363425323025324225323061726d36342d3234393645443f6c6f676f3d646f636b6572266c6f676f436f6c6f723d7768697465)](https://hub.docker.com/r/astraonline/astracalls) [![n8n](https://camo.githubusercontent.com/83d1d8227c6fdcae3f9651782e52be3195a388eb1cd20b307afdf047c6fa4d20/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f6e386e2d6e6f6465732d617374726163616c6c733f6c6162656c3d6e386e2532306e6f6465266c6f676f3d6e386e26636f6c6f723d454134423731)](https://www.npmjs.com/package/n8n-nodes-astracalls) [![License](https://camo.githubusercontent.com/0fb4f7634808706feb5d9bf669e078e2da524534575a39f2f08c74de3d8a1135/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4147504c2d2d332e302d626c75652e737667)](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-licen%C3%A7a)

[Visão Geral](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-vis%C3%A3o-geral) · [Funcionalidades](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-funcionalidades) · [Arquitetura](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-arquitetura) · [Início Rápido](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-in%C3%ADcio-r%C3%A1pido) · [Configuração](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-configura%C3%A7%C3%A3o) · [Deploy](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-deploy-em-produ%C3%A7%C3%A3o-docker-swarm--traefik) · [API](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-api) · [n8n](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-integra%C3%A7%C3%A3o-com-n8n) · [Suporte](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#%EF%B8%8F-suporte-profissional)

---

## 📋 Visão Geral

<div class="markdown-heading" dir="auto" id="bkmrk--4" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-vis%C3%A3o-geral)</div>> O AstraCalls pareia uma ou mais contas do WhatsApp (QR code, **código de pareamento** ou **passkey**) e permite **fazer e receber chamadas de voz e vídeo** de qualquer navegador, ligar para **tronco/ramal SIP**, e operar a conta como canal de **mensagens** (texto, mídia, botões, listas, carrossel, enquete, formulário, pix, produto, status…).
> 
> O microfone e a câmera do navegador chegam ao servidor Go por **WebRTC** (ou por **WebSocket**, com fallback automático quando o WebRTC não passa no firewall). O servidor transcodifica para os codecs do WhatsApp (**MLow** para voz, **H.264** para vídeo) e injeta a mídia na malha de **relay SRTP** do WhatsApp — e o caminho inverso traz o áudio e o vídeo do outro lado de volta ao navegador.
> 
> Toda a pilha VoIP roda **nativamente em Go**: codec MLow, RTP/SRTP/SRTCP, STUN, transporte SCTP/DTLS do relay, pipeline H.264 e a sinalização `<call>`, integrados ao [**whatsmeow**](https://github.com/tulir/whatsmeow) e servidos a um painel **React 19**. A única dependência em C é o codec `opus_mlow` (via cgo) — e é opcional: sem ela o servidor roda em modo **somente sinalização**.
> 
> Várias contas podem ser pareadas e operadas lado a lado, cada uma com QR, status, histórico e banco próprios. Uma conta mantém **várias chamadas 1:1 simultâneas** (uma por atendente), roteadas por call ID.

> **Status:** estável e em produção (última versão estável no [CHANGELOG](https://github.com/AstraOnlineWeb/AstraCalls/blob/main/CHANGELOG.md)). Chamada em **grupo** é funcional (áudio + vídeo, 3+ participantes) mas segue marcada como experimental, atrás da flag `WACALLS_GROUP_CALLS`.

---

## 🚀 Funcionalidades

<div class="markdown-heading" dir="auto" id="bkmrk--7" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-funcionalidades)</div>### ☎️ Chamadas de voz

<div class="markdown-heading" dir="auto" id="bkmrk--9" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#%EF%B8%8F-chamadas-de-voz)</div>- **Saída e entrada 1:1** com áudio bidirecional, várias chamadas simultâneas por conta.
- **Espera (hold/resume) com música**, **atender em espera** e **transferência cega** entre atendentes (troca de dono + ponte, sem tocar a perna do WhatsApp).
- **Mudo / mão levantada** (`mute_v2`, `raise_hand`) nos dois sentidos.
- **Timeout de toque**, recusa que para o telefone de quem ligou, consent freshness (RFC 7675) — a chamada não cai sozinha aos ~20s.
- **Toque fantasma** (`POST /calls/fake`): liga e desliga antes de atender (aviso/alerta).
- **Transporte de áudio no navegador:** WebRTC com **fallback automático para WebSocket** (`WACALLS_DEFAULT_TRANSPORT=auto|webrtc|websocket`); WS de áudio **PCM16 full-duplex** (`GET /calls/{id}/ws`) pronto para agentes de voz/IA.
- **Gravação opt-in por sessão**: MP3 mono mixado dos dois lados, vira nota privada no Chatwoot e evento `recording` no webhook.

### 📹 Chamadas de vídeo

<div class="markdown-heading" dir="auto" id="bkmrk--11" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-chamadas-de-v%C3%ADdeo)</div>- **Vídeo 1:1** (câmera do atendente e do cliente), **upgrade/downgrade** no meio da chamada (áudio → vídeo e volta), religar a câmera, **MediaClock** (áudio e vídeo no mesmo relógio).
- **Orientação automática** (lê a rotação do celular no RTP e no stanza `<video>`) com **botão de girar** como ajuste manual, no painel e no widget.
- **Vídeo no widget do Chatwoot** (WebCodecs, data channel H.264).
- **Disparo de ligações de VÍDEO** com arquivo gravado (`POST /broadcast {video:true}`).

### 👥 Chamada em grupo *(experimental, `WACALLS_GROUP_CALLS=1`)*

<div class="markdown-heading" dir="auto" id="bkmrk--13" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-chamada-em-grupo-experimental-wacalls_group_calls1)</div>- Liga **para um grupo existente** (resolve os membros) com **áudio e vídeo**; o atendente ouve o **mix** de todos e fala para todos; vê a **câmera de cada participante** em tiles rotulados com número + nome.
- Protocolo completo do grupo: offer com `group_info`, chave de **epoch compartilhada com rotação** a cada entrada, relay de grupo (DTLS direto, SFU com HBH-FEC), **SRTCP** (Sender Reports + **PLI**/pedido de keyframe nos dois sentidos), anúncio `<video state>`, participante que sai some do painel.
- Endpoints `POST /calls/group`, `/calls/group/end`, WS `/calls/group/ws` (áudio PCM16) e `/calls/group/video-ws` (H.264), `GET /calls/group/roster`.

### ☎️ Gateway SIP / PBX

<div class="markdown-heading" dir="auto" id="bkmrk--15" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#%EF%B8%8F-gateway-sip--pbx)</div>- **Servidor SIP** (porta 5060 UDP/TCP) para o PBX/softphone do cliente **se registrar** no AstraCalls (credenciais por sessão, mostradas no painel) — tronco ↔ WhatsApp nos dois sentidos, áudio G.711 ↔ MLow.
- **Registro em PBX externo** (o AstraCalls vira um ramal do Asterisk/FreePBX/tronco hospedado), com **servidor, domínio e outbound proxy** separados, re-REGISTER automático e status no painel.
- RTP em **faixa fixa de portas** (`WACALLS_RTP_PORT_MIN/MAX`), publicável em `mode=host`.

### 📞 Conector SIP (PABX IP → AstraChat) — serviço separado

<div class="markdown-heading" dir="auto" id="bkmrk--17" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-conector-sip-pabx-ip--astrachat--servi%C3%A7o-separado)</div>- Binário `sipconnector` na mesma imagem: liga **qualquer PABX IP** ao AstraChat, sem WhatsApp.
- Linha por caixa (o PABX registra no conector **ou** o conector registra no PABX) e **um ramal por atendente** (e-mail → ramal).
- Expõe a **mesma API de chamadas do wacalls** (SSE, accept/reject/DELETE, `/webrtc` para o navegador em PCMU sem transcodificar, `/ws` pcm16 para o agente de voz por IA) e transferência para ramal por **SIP REFER**.
- Detalhes, variáveis e deploy: [`cmd/sipconnector/README.md`](https://github.com/AstraOnlineWeb/AstraCalls/blob/main/cmd/sipconnector/README.md).

### 💬 Mensagens (API estilo WAHA, ~60 endpoints)

<div class="markdown-heading" dir="auto" id="bkmrk--19" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-mensagens-api-estilo-waha-60-endpoints)</div>- **Envio:** texto, imagem, áudio/nota de voz (com waveform), vídeo, **nota de vídeo (PTV)**, documento, sticker, contato, localização, link com preview, **enquete** (e voto), **evento** (e resposta), **pix (BR Code)**, **produto**, **status** (texto/imagem/vídeo/áudio).
- **Interativas que renderizam no número não-oficial:** `interactive` (CTA: abrir URL, copiar código, ligar, resposta rápida), `buttons`, `list`, `carousel` e **formulário (webview)** com respostas no Chatwoot + webhook `form_response`.
- **Mensagem que some após leitura** (`disappearing`), mensagens temporárias por chat.
- **Editar, reagir, encaminhar, marcar como lida, digitando/gravando, presença.**
- **Agendamento** (`/schedule`, persiste e sobrevive a restart), **envio idempotente** (`X-Message-ID`), **busca** no histórico, **download de mídia recebida**.
- **Contatos, grupos, canais, perfil, privacidade, bloqueio, proxy por sessão**.

### 📢 Disparos em massa

<div class="markdown-heading" dir="auto" id="bkmrk--21" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-disparos-em-massa)</div>- `POST /blast`: campanha de texto/imagem com **pacing anti-ban**, status e cancelamento.
- `POST /broadcast`: **disparo de ligações** (áudio ou vídeo) tocando um arquivo gravado.
- `GET /restriction-status`: detecta **restrição/shadow-ban** da conta (`reachout_timelock`).

### 🔔 Webhooks confiáveis

<div class="markdown-heading" dir="auto" id="bkmrk--23" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-webhooks-confi%C3%A1veis)</div>- Eventos por sessão (`message`, `receipt`, `call_*`, `recording`, `form_response`, `group_participants`, `restriction`…), **filtro de eventos**, **assinatura HMAC-SHA256** (`X-Webhook-Signature`), **retry com backoff**, **circuit breaker**, **DLQ** com replay.

### 🤝 Chatwoot

<div class="markdown-heading" dir="auto" id="bkmrk--25" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-chatwoot)</div>- Contato/conversa por telefone, mensagens **WhatsApp ↔ Chatwoot** (texto + mídia) com **1 QR só** por número; grupos e canais (opcionais); **assinatura do atendente**, **always online**, **marcar lidas**; **importar histórico sob demanda**; mensagem editada, origem de anúncio (Click to WhatsApp), nota privada da gravação.
- **Widget de chamada** (`widget.js`): botão de telefone na conversa, toca e abre sozinho na chamada recebida, áudio por WebRTC ou WebSocket, **vídeo**, token de widget por conta.
- Correção do **9º dígito BR / LID** em todos os envios; sem contato "lixo" com LID.

### 🔐 Pareamento e segurança

<div class="markdown-heading" dir="auto" id="bkmrk--27" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-pareamento-e-seguran%C3%A7a)</div>- Pareamento por **QR**, **código** (`/pair-code`) e **passkey** (`/pair-passkey`, com extensão de navegador própria em `passkey-extension/`).
- **API key** (`X-API-Key`), **tokens de widget** assinados, guarda **anti-SSRF** no download de mídia por URL, **escopo por conta** nos eventos SSE.

### 📊 Observabilidade e infra

<div class="markdown-heading" dir="auto" id="bkmrk--29" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-observabilidade-e-infra)</div>- `GET /livez`, `/readyz`, `/metrics` (Prometheus), versão/commit do build em `GET /api/config` e no painel.
- **PostgreSQL por sessão** (estilo WAHA), **imagem multi-arch** (amd64 + arm64) publicada pelo CI em [Docker Hub](https://hub.docker.com/r/astraonline/astracalls).

---

## 🏗️ Arquitetura

<div class="markdown-heading" dir="auto" id="bkmrk--32" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#%EF%B8%8F-arquitetura)</div>```
┌──────────────────────────────────────────────────────────────────────────────┐
│          NAVEGADOR (painel React)   +   Widget no Chatwoot   +   PBX/SIP      │
│   mic/câmera · WebRTC (Opus + H.264 DC) ou WebSocket (PCM16) · HTTP + SSE     │
└──────────────────────────────────┬───────────────────────────────┬───────────┘
                                   │ /api/sessions/{sid}/calls/…    │ SIP 5060 + RTP
                                   ▼                               ▼
┌──────────────────────────── GO SERVER (cmd/server) ──────────────────────────┐
│  SessionManager  contas (whatsmeow client + CallManager + GroupCallManager)  │
│  Broker          SSE escopado por conta (sessões, chamadas, vídeo, ações)    │
│  Bridge / WS     pion WebRTC ou WebSocket ⇄ PCM 16 kHz / H.264               │
│  SIP Gateway     sipgo (UAS + UAC), ponte RTP G.711 ⇄ PCM                    │
│  Messaging       ~60 endpoints de envio, agendamento, blast, broadcast       │
│  Webhook         retry/backoff, circuit breaker, DLQ, HMAC                   │
│  Chatwoot        integração bidirecional + widget + import de histórico      │
│  Recorder        MP3 por chamada (ffmpeg)                                    │
│                                                                              │
│  internal/wa     adaptador VoipSocket sobre o whatsmeow                      │
│  internal/voip   call (1:1 + grupo) · signaling · media (MLow, SRTP/SRTCP,   │
│                  cripto de grupo) · transport (relay SCTP/DTLS, STUN, H.264) │
└────────────────┬─────────────────────────────────────┬────────────────────────┘
                 │ sinalização <call>                   │ mídia SRTP / H.264
                 ▼                                      ▼
        ┌────────────────┐                  ┌───────────────────────────┐
        │  WhatsApp WS   │                  │  relay do WhatsApp (1:1)  │
        │  (whatsmeow)   │                  │  relay de GRUPO (SFU)     │
        └────────────────┘                  └───────────────────────────┘
                                                        │
                                             ┌─────────────────────────┐
                                             │  PostgreSQL 16          │
                                             │  wacalls_main + 1/sessão│
                                             └─────────────────────────┘

```

<div class="snippet-clipboard-content notranslate position-relative overflow-auto" id="bkmrk--34" style="text-align: justify;"><div>  
</div></div>### Estrutura

<div class="markdown-heading" dir="auto" id="bkmrk--35" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#estrutura)</div><table id="bkmrk-caminho-responsabili" style="width: 100%;"><thead><tr><th style="width: 24.075%;">Caminho</th><th style="width: 75.9403%;">Responsabilidade</th></tr></thead><tbody><tr><td style="width: 24.075%;">`cmd/server`</td><td style="width: 75.9403%;">HTTP/SSE, sessões + store (Postgres), ponte WebRTC/WS, auth, mensagens, agendamento, blast/broadcast, webhook, Chatwoot, gravação, **SIP** (`sip_gateway.go`, `sip_uac.go`, `sip_rtp.go`), **grupo** (`groupcall.go`)</td></tr><tr><td style="width: 24.075%;">`internal/wa`</td><td style="width: 75.9403%;">`VoipSocket` — envia/recebe stanzas `<call>` via whatsmeow</td></tr><tr><td style="width: 24.075%;">`internal/voip/core`</td><td style="width: 75.9403%;">Tipos de domínio, constantes, interface `VoipSocket`</td></tr><tr><td style="width: 24.075%;">`internal/voip/wanode`</td><td style="width: 75.9403%;">Helpers de node WhatsApp e JID</td></tr><tr><td style="width: 24.075%;">`internal/voip/media`</td><td style="width: 75.9403%;">Codec MLow, RTP, **SRTP/SRTCP**, SSRC, resampling, derivação de chaves (1:1 e **epoch de grupo**)</td></tr><tr><td style="width: 24.075%;">`internal/voip/transport`</td><td style="width: 75.9403%;">Relay SCTP (1:1), **relay de grupo** (DTLS direto + Allocate de grupo), STUN, empacotamento H.264</td></tr><tr><td style="width: 24.075%;">`internal/voip/signaling`</td><td style="width: 75.9403%;">Build/parse de `<call>` (offer/accept/vídeo/grupo/rekey), cripto da call-key</td></tr><tr><td style="width: 24.075%;">`internal/voip/call`</td><td style="width: 75.9403%;">`CallManager` (1:1) e `GroupCallManager` (grupo), pipeline de vídeo, mixer de áudio</td></tr><tr><td style="width: 24.075%;">`client/`</td><td style="width: 75.9403%;">Painel React 19 + Vite + Tailwind v4 + shadcn/ui (discador, chamadas, vídeo, grupo, sessões, SIP, Chatwoot, histórico, login)</td></tr><tr><td style="width: 24.075%;">`client/public/widget.js`</td><td style="width: 75.9403%;">Widget de chamada (áudio + vídeo) embutível no Chatwoot</td></tr><tr><td style="width: 24.075%;">`client/public/openapi.yaml` · `api-docs.html`</td><td style="width: 75.9403%;">Documentação OpenAPI/Swagger da API (`/api-docs.html` no servidor)</td></tr><tr><td style="width: 24.075%;">`passkey-extension/`</td><td style="width: 75.9403%;">Extensão Chrome para pareamento por passkey</td></tr></tbody></table>

---

## ⚙️ Início Rápido

<div class="markdown-heading" dir="auto" id="bkmrk--38" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#%EF%B8%8F-in%C3%ADcio-r%C3%A1pido)</div>```
git clone https://github.com/AstraOnlineWeb/AstraCalls.git
cd AstraCalls
git submodule update --init          # codec opus_mlow (necessário p/ áudio ao vivo)

go mod download                      # dependências Go
cd client && npm install && cd ..    # dependências do painel React
```

<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" id="bkmrk--40" style="text-align: justify;"><div>  
</div></div>É preciso um **PostgreSQL** (usuário com `CREATEDB`):

```
export WACALLS_PG_URL='postgres://wacalls:senha@127.0.0.1:5432/postgres?sslmode=disable'
```

<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" id="bkmrk--41" style="text-align: justify;"><div>  
</div></div>### Rodar (somente sinalização — sem compilador C; pareia e chama, sem áudio)

<div class="markdown-heading" dir="auto" id="bkmrk--42" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#rodar-somente-sinaliza%C3%A7%C3%A3o--sem-compilador-c-pareia-e-chama-sem-%C3%A1udio)</div>```
go run ./cmd/server -addr :8080          # adicione -debug para logs verbosos
```

<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" id="bkmrk--44" style="text-align: justify;"><div>  
</div></div>### Rodar (áudio ao vivo — codec MLow nativo via cgo)

<div class="markdown-heading" dir="auto" id="bkmrk--45" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#rodar-%C3%A1udio-ao-vivo--codec-mlow-nativo-via-cgo)</div>```
CGO_ENABLED=1 \
CGO_LDFLAGS="-L$PWD/native -Wl,-rpath,$PWD/native" \
go run -tags mlow ./cmd/server -addr :8080 -debug
```

<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" id="bkmrk--47" style="text-align: justify;"><div>  
</div></div>> O áudio real exige cgo + `native/libopus_mlow.so` (compilada de [opus\_mlow](https://github.com/edgardmessias/opus_mlow)). A imagem Docker já vem com tudo.

Abra `http://localhost:8080`, clique em **Nova sessão** e escaneie o QR em **WhatsApp → Aparelhos conectados** (ou use código de pareamento / passkey).

### Painel React em modo dev

<div class="markdown-heading" dir="auto" id="bkmrk--48" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#painel-react-em-modo-dev)</div>```
cd client
npm run dev      # Vite na :5173, faz proxy de /api → http://localhost:8080
```

<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" id="bkmrk--50" style="text-align: justify;"><div>  
</div></div>---

## 🔧 Configuração

<div class="markdown-heading" dir="auto" id="bkmrk--52" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-configura%C3%A7%C3%A3o)</div>### Flags

<div class="markdown-heading" dir="auto" id="bkmrk--54" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#flags)</div><table id="bkmrk-flag-padr%C3%A3o-signific"><thead><tr><th>Flag</th><th>Padrão</th><th>Significado</th></tr></thead><tbody><tr><td>`-addr`</td><td>`:8080`</td><td>Endereço HTTP</td></tr><tr><td>`-pg-url` / `-pg-namespace`</td><td>env</td><td>URL do Postgres e prefixo dos bancos por sessão</td></tr><tr><td>`-static`</td><td>`client/dist`</td><td>Diretório do painel estático</td></tr><tr><td>`-debug`</td><td>`false`</td><td>Logs verbosos (inclui o log interno do whatsmeow)</td></tr><tr><td>`-max-calls-per-session`</td><td>`8`</td><td>Chamadas simultâneas por sessão (`0` = ilimitado)</td></tr></tbody></table>

### Variáveis de ambiente

<div class="markdown-heading" dir="auto" id="bkmrk--56" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#vari%C3%A1veis-de-ambiente)</div><table id="bkmrk-env-padr%C3%A3o-significa" style="width: 100%;"><thead><tr><th style="width: 27.8908%;">Env</th><th style="width: 10.3749%;">Padrão</th><th style="width: 61.7496%;">Significado</th></tr></thead><tbody><tr><td style="width: 27.8908%;">`WACALLS_PG_URL`</td><td style="width: 10.3749%;">—</td><td style="width: 61.7496%;">URL de manutenção do Postgres (usuário com `CREATEDB`)</td></tr><tr><td style="width: 27.8908%;">`WACALLS_PG_NAMESPACE`</td><td style="width: 10.3749%;">`wacalls`</td><td style="width: 61.7496%;">Prefixo dos bancos (`wacalls_main` + `wacalls_<id>`)</td></tr><tr><td style="width: 27.8908%;">`WACALLS_API_KEY`</td><td style="width: 10.3749%;">—</td><td style="width: 61.7496%;">Se setada, exige `X-API-Key` em `/api/*` (**use em produção**)</td></tr><tr><td style="width: 27.8908%;">`WACALLS_PUBLIC_IP`</td><td style="width: 10.3749%;">—</td><td style="width: 61.7496%;">IP público p/ NAT 1:1 / ICE-TCP / SDP do SIP. `auto` descobre o IP real mesmo dentro do Docker/NAT de nuvem (interface pública → STUN → HTTPS); o IP achado e a fonte aparecem em `GET /api/config` (`publicIp`, `publicIpSource`)</td></tr><tr><td style="width: 27.8908%;">`WACALLS_UDP_PORT`</td><td style="width: 10.3749%;">—</td><td style="width: 61.7496%;">Porta de mídia WebRTC (UDP + ICE-TCP)</td></tr><tr><td style="width: 27.8908%;">`WACALLS_DEFAULT_TRANSPORT`</td><td style="width: 10.3749%;">`auto`</td><td style="width: 61.7496%;">Transporte de áudio do navegador: `auto` (WebRTC → fallback WS), `webrtc`, `websocket`</td></tr><tr><td style="width: 27.8908%;">`WACALLS_MAX_CALLS`</td><td style="width: 10.3749%;">`8`</td><td style="width: 61.7496%;">Equivalente a `-max-calls-per-session`</td></tr><tr><td style="width: 27.8908%;">`WACALLS_RING_TIMEOUT_SECONDS`</td><td style="width: 10.3749%;">—</td><td style="width: 61.7496%;">Expira chamada recebida que nunca é encerrada</td></tr><tr><td style="width: 27.8908%;">`WACALLS_UNIFIED_SESSION_MINUTES`</td><td style="width: 10.3749%;">`5`</td><td style="width: 61.7496%;">Intervalo mínimo entre os sinais "unified session" enviados ao conectar, como faz o WhatsApp Web (`0` desliga)</td></tr><tr><td style="width: 27.8908%;">`WACALLS_DEVICE_NAME`</td><td style="width: 10.3749%;">`Windows`</td><td style="width: 61.7496%;">Nome do aparelho em "Dispositivos conectados" (vale para pareamentos novos)</td></tr><tr><td style="width: 27.8908%;">`WACALLS_DEVICE_BROWSER`</td><td style="width: 10.3749%;">`chrome`</td><td style="width: 61.7496%;">Ícone/plataforma do aparelho: `chrome`, `edge`, `firefox`, `safari` ou `desktop`</td></tr><tr><td style="width: 27.8908%;">`WACALLS_RECORDING_DIR`</td><td style="width: 10.3749%;">`$TMPDIR/wacalls-recordings`</td><td style="width: 61.7496%;">Onde ficam os MP3s (retenção ~48h)</td></tr><tr><td style="width: 27.8908%;">`WACALLS_PUBLIC_BASE_URL`</td><td style="width: 10.3749%;">—</td><td style="width: 61.7496%;">Base pública p/ URLs de gravação, formulários e widget (ex.: `https://call.seudominio.com`)</td></tr><tr><td style="width: 27.8908%;">`WACALLS_WIDGET_KEY`</td><td style="width: 10.3749%;">—</td><td style="width: 61.7496%;">Chave-mestra para emitir tokens de widget (`POST /api/widget-tokens`)</td></tr><tr><td style="width: 27.8908%;">`WACALLS_WIDGET_SIGNING_SECRET`</td><td style="width: 10.3749%;">—</td><td style="width: 61.7496%;">Segredo de assinatura dos tokens de widget</td></tr><tr><td style="width: 27.8908%;">`WACALLS_SIP_ADDR`</td><td style="width: 10.3749%;">`0.0.0.0:5060`</td><td style="width: 61.7496%;">Endereço do servidor SIP (UDP + TCP)</td></tr><tr><td style="width: 27.8908%;">`WACALLS_SIP_ADVERTISE_PORT`</td><td style="width: 10.3749%;">`5060`</td><td style="width: 61.7496%;">Porta SIP anunciada no `Contact` (registro em PBX externo)</td></tr><tr><td style="width: 27.8908%;">`WACALLS_RTP_PORT_MIN` / `_MAX`</td><td style="width: 10.3749%;">`40000` / `40049`</td><td style="width: 61.7496%;">Faixa fixa de portas RTP do SIP (publique em `mode=host`)</td></tr><tr><td style="width: 27.8908%;">`WACALLS_SIP_DEBUG`</td><td style="width: 10.3749%;">off</td><td style="width: 61.7496%;">Logs detalhados de mídia SIP/grupo (**só para diagnóstico** — gera muito log)</td></tr><tr><td style="width: 27.8908%;">`WACALLS_GROUP_CALLS`</td><td style="width: 10.3749%;">off</td><td style="width: 61.7496%;">`1` liga a chamada em grupo (experimental)</td></tr></tbody></table>

> **Gravação de chamada (opt-in por sessão).** Ligue em `PUT /api/sessions/{sid}/recording {"enabled":true}` (ou pelo toggle "Gravar" no painel). O áudio dos dois lados é mixado num MP3 mono 16 kHz que vira **nota privada** no Chatwoot e evento `recording` no webhook; o arquivo fica em `GET /recordings/{callId}.mp3`. Requer `ffmpeg` (já na imagem).

---

## 🐳 Deploy em produção (Docker Swarm + Traefik)

<div class="markdown-heading" dir="auto" id="bkmrk--59" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-deploy-em-produ%C3%A7%C3%A3o-docker-swarm--traefik)</div>A imagem oficial é **multi-arquitetura** (`linux/amd64` + `linux/arm64`) e é publicada pelo CI a cada push: `astraonline/astracalls:develop` (contínua) e `astraonline/astracalls:vX.Y.Z`

- `:latest` (releases).

```
# deploy da stack (Postgres + servidor em rede de host + proxy Traefik)
docker stack deploy -c sua-stack.yml astracalls

# atualizar para a imagem mais nova
docker service update --image astraonline/astracalls:develop --force astracalls_astracalls
```

<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" id="bkmrk--61" style="text-align: justify;"><div>  
</div></div>Notas de produção:

- O servidor roda em **rede de host** para a mídia WebRTC/SIP enxergar a interface real.
- Um serviço **socat** com labels do Traefik publica o HTTP em **HTTPS** (necessário porque `getUserMedia` só funciona em contexto seguro).
- O **PostgreSQL** dedicado escuta apenas em `127.0.0.1` (não exposto à internet).
- Defina `WACALLS_PUBLIC_IP` (ou `auto`), `WACALLS_UDP_PORT`, `WACALLS_PG_URL`, `WACALLS_PUBLIC_BASE_URL` e uma `WACALLS_API_KEY` forte.
- Para o **SIP**, publique `5060/udp`, `5060/tcp` e a faixa `WACALLS_RTP_PORT_MIN..MAX/udp` em `mode=host`, e aponte `WACALLS_PUBLIC_IP` para o IP real da máquina.
- Em nuvens que bloqueiam UDP de entrada, o **ICE-TCP** (WebRTC) e o transporte **WebSocket** (`WACALLS_DEFAULT_TRANSPORT=auto`) mantêm o áudio funcionando.
- Para buildar a própria imagem: `docker build -t astraonline/astracalls:develop .` (o Dockerfile compila o codec a partir do submódulo `opus_mlow`).

---

## 🔌 API

<div class="markdown-heading" dir="auto" id="bkmrk--63" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-api)</div>A documentação completa (OpenAPI 3, **179 rotas**) é servida pelo próprio servidor em **`/api-docs.html`** (Swagger UI) e está em [`client/public/openapi.yaml`](https://github.com/AstraOnlineWeb/AstraCalls/blob/main/client/public/openapi.yaml).

Todas as rotas são escopadas por sessão (`/api/sessions/{sid}/…`). Os eventos chegam por um único canal SSE (`GET /api/events?clientId=…`), marcados com o `sessionId` de origem. Se `WACALLS_API_KEY` estiver setada, envie `X-API-Key` (ou `?apiKey=` no SSE/WS).

<table id="bkmrk-%C3%81rea-rotas-%28resumo%29-"><thead><tr><th>Área</th><th>Rotas (resumo)</th></tr></thead><tbody><tr><td>**Sessões**</td><td>`GET/POST /api/sessions`, `DELETE /{sid}`, `/logout`, `/pair`, `/pair-code`, `/pair-passkey`, `/proxy`, `/recording`, `/restriction-status`</td></tr><tr><td>**Chamadas**</td><td>`POST /calls` (`{phone, video?, record?}`), `/calls/{id}/webrtc` (SDP), `GET /calls/{id}/ws` (PCM16), `/accept`, `/reject`, `DELETE /calls/{id}`, `/hold`, `/resume`, `/pickup`, `/transfer`, `/mute`, `/hand`, `/video/{request|accept|reject|stop}`, `/spy` (espiar: WebRTC recvonly / `GET /spy/ws` PCM16), `/volume` (ganho 0..3), `/silence` (silenciar o toque só na tela), `POST /calls/fake`, `GET /calls`, `GET /history`</td></tr><tr><td>**Grupo**</td><td>`POST /calls/group`, `POST /calls/group/end`, `GET /calls/group/ws`, `GET /calls/group/video-ws`, `GET /calls/group/roster`</td></tr><tr><td>**Disparos**</td><td>`POST /broadcast` (ligações, áudio/vídeo), `POST /blast` + `GET /blasts`, `/blasts/{id}`, `/blasts/{id}/cancel`</td></tr><tr><td>**Mensagens**</td><td>`POST /messages/{text|image|audio|video|ptv|document|sticker|contact|location|link-preview|poll|poll-vote|event|event-response|pix|product|product-native|interactive|buttons|list|carousel|form|disappearing|seen|typing|forward}`, `PUT /messages/{edit|react}`, `GET /messages`, `/messages/search`, `/messages/{id}/media`, `/messages/new-message-id`, `DELETE /messages`, `/schedule`</td></tr><tr><td>**Status / presença**</td><td>`POST /status/{text|image|video|audio}`, `POST /presence`, `/presence/{jid}/subscribe`</td></tr><tr><td>**Contatos / grupos / canais**</td><td>`GET /contacts`, `/contacts/check`, `/contacts/{jid}`, `/picture`, `/business`, `/block`, `/unblock`, `GET /blocklist`; `GET/POST /groups`, `/groups/{gid}/…` (participantes, convite, pedidos, configurações, foto, assunto, descrição, sair; `POST /groups/{gid}/history/share` e `shareHistory` no add: compartilhar o histórico recente com quem entrou); `GET/POST /communities`, `/communities/{cid}` (+ grupos), `/communities/{cid}/groups` (listar/criar), `/groups/link`, `/groups/unlink`, `/participants` (+ `/participants/add`); `GET /channels`, `/channels/{id}/…` (seguir, mutar, mensagens)</td></tr><tr><td>**Chats / perfil / privacidade**</td><td>`GET /chats`, `/chats/{chatId}/messages`, `PUT /chats/{chatId}/disappearing`, `PUT /disappearing`; `GET /profile`, `/profile/qr`, `PUT /profile/status`; `GET/PUT /privacy`, `GET /privacy/status`</td></tr><tr><td>**Webhooks**</td><td>`GET/POST/DELETE /webhook` (eventos, `secret` HMAC), `GET /webhooks/status`, `/webhooks/dlq`, `POST /webhooks/dlq/{id}/replay`, `/webhooks/reenable`</td></tr><tr><td>**Chatwoot**</td><td>`GET/POST/DELETE /chatwoot`, `POST /chatwoot/webhook`, `/chatwoot/import-history`, `/chatwoot/groups/{gid}/open`, `/chatwoot/channels/{id}/open`, `GET /api/chatwoot/resolve`</td></tr><tr><td>**SIP**</td><td>`GET /api/sip/status`, `GET/POST /sip` (credenciais p/ o PBX registrar aqui), `GET/POST /sip-ext` (registrar num PBX externo: host, porta, usuário, senha, ramal, proxy)</td></tr><tr><td>**Widget / formulários**</td><td>`GET /api/widget-key`, `POST /api/widget-tokens`, `GET /forms/{token}`, `POST /forms/{token}/submit` (públicas, token como capability)</td></tr><tr><td>**Infra**</td><td>`GET /api/config` (flags, versão, commit), `GET /livez`, `/readyz`, `/metrics`, `GET /recordings/{id}`</td></tr></tbody></table>

---

## 🔗 Integração com n8n

<div class="markdown-heading" dir="auto" id="bkmrk--66" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-integra%C3%A7%C3%A3o-com-n8n)</div>Automatize o WhatsApp no **n8n sem escrever código**: o node oficial [`n8n-nodes-astracalls`](https://www.npmjs.com/package/n8n-nodes-astracalls) já está publicado no npm, todo em português.

**Instalação:** no n8n, abra **Configurações → Community Nodes → Install**, digite `n8n-nodes-astracalls` e clique em **Install**. No Docker, use `N8N_COMMUNITY_PACKAGES=n8n-nodes-astracalls`.

**Credencial:** a URL do seu AstraCalls e a API Key (`WACALLS_API_KEY`).

<table id="bkmrk-node-o-que-faz-astra"><thead><tr><th>Node</th><th>O que faz</th></tr></thead><tbody><tr><td>**AstraCalls**</td><td>55 operações em 8 recursos: **Mensagem** (texto, mídia, documento, enquete, botões, lista, formulário nativo, reagir, editar, apagar…), **Chamada** (ligar, ligação fantasma, disparo de ligações com áudio/vídeo), **Grupo**, **Comunidade**, **Contato**, **Sessão**, **Formulário** e **Requisição Personalizada** (qualquer uma das 179 rotas)</td></tr><tr><td>**AstraCalls Trigger**</td><td>Inicia o fluxo com 15 eventos: mensagem recebida, leitura, reação, voto em enquete, formulário respondido, entrada/saída de grupo, gravação de chamada, desconexão da sessão… Configura o webhook da sessão sozinho ao ativar</td></tr></tbody></table>

- **Fácil de usar:** a sessão é escolhida numa lista (nome + número), o destino aceita número com ou sem o 9º dígito e a mídia vem por URL ou de um arquivo de etapa anterior.
- **Pronto para responder:** o gatilho entrega `de`, `nome`, `texto` e `responderPara` prontos para usar no envio, e ignora as mensagens da própria conta (sem loop).
- **Agentes de IA:** o node pode ser usado como ferramenta pelos agentes de IA do n8n.

📘 **[Tutorial passo a passo](https://github.com/AstraOnlineWeb/AstraCalls/blob/main/guias/n8n.md)**: instalar, criar a credencial, enviar a primeira mensagem e montar um robô que responde, com [fluxo pronto para importar](https://github.com/AstraOnlineWeb/AstraCalls/blob/main/guias/n8n/responder-mensagem.json) e [10 fluxos de exemplo](https://github.com/AstraOnlineWeb/AstraCalls/blob/main/guias/n8n.md#-10-fluxos-de-exemplo-prontos) (menu com botões, atendente de IA, enquete, disparo de ligações…).

## 🤖 MCP para agentes de IA

<div class="markdown-heading" dir="auto" id="bkmrk--68" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-mcp-para-agentes-de-ia)</div>O AstraCalls traz um **servidor MCP** (Model Context Protocol) embutido: Claude, ChatGPT, Cursor, VS Code, n8n e outros agentes de IA usam o WhatsApp direto, sem instalar nada.

**Chaves por sessão (recomendado):** no painel, botão **MCP** da sessão → **Nova chave**. A chave fica presa àquele número, pode ser **somente leitura** e é revogada a qualquer momento. Ela não permite parear, desconectar nem mexer em webhooks, Chatwoot, SIP ou proxy. O painel mostra, uma única vez, a URL e as configurações prontas para copiar. Pela API: `GET/POST /api/sessions/{sid}/mcp-keys` e `DELETE /api/sessions/{sid}/mcp-keys/{id}`.

<table id="bkmrk-cliente-como-conecta"><thead><tr><th>Cliente</th><th>Como conectar</th></tr></thead><tbody><tr><td>claude.ai, ChatGPT (conector personalizado)</td><td>URL `https://SEU-ASTRACALLS/mcp/<chave>`</td></tr><tr><td>Claude Code</td><td>`claude mcp add --transport http astracalls https://SEU-ASTRACALLS/mcp --header "Authorization: Bearer <chave>"`</td></tr><tr><td>Claude Desktop, Cursor, VS Code</td><td>`mcpServers` → `{"type":"http","url":"https://SEU-ASTRACALLS/mcp","headers":{"Authorization":"Bearer <chave>"}}`</td></tr><tr><td>n8n</td><td>Ferramenta **MCP Client** do agente de IA, endereço `/mcp` e autenticação *Bearer*</td></tr></tbody></table>

**Acesso de administrador:** `https://SEU-ASTRACALLS/api/mcp` com a API Key da instância (`WACALLS_API_KEY`) enxerga todas as sessões; o agente escolhe o número por nome, telefone ou ID.

**44 ferramentas:** enviar texto, mídia, documento, localização, contato, enquete, botões e lista; reagir, editar, apagar, marcar como lida e "digitando…"; **ler conversas e buscar mensagens**; ligar, encerrar, toque fantasma e disparo de ligações; contatos, grupos e comunidades; limite de conversas novas e restrição; e `api_request` para as demais rotas da sessão.

> Quem tem a chave usa o número: trate-a como senha e revogue as que não usa mais.

---

## 🧪 Testes

<div class="markdown-heading" dir="auto" id="bkmrk--71" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-testes)</div>```
go test ./...                 # mídia (SRTP/SRTCP, STUN, RTP, H.264, cripto de grupo), sinalização, servidor
cd client && npm run build    # type-check + build de produção do painel
```

<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" id="bkmrk--73" style="text-align: justify;"><div>  
</div></div>---

## 🔒 Segurança

<div class="markdown-heading" dir="auto" id="bkmrk--75" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-seguran%C3%A7a)</div>- Em produção, **sempre** defina `WACALLS_API_KEY` — sem ela qualquer um com acesso HTTP pode criar contas, fazer chamadas, enviar mensagens e ler histórico.
- O banco de cada sessão guarda **credenciais do WhatsApp**. Mantenha o Postgres protegido e fora da internet.
- Exponha sempre por **HTTPS** (`getUserMedia` exige contexto seguro).
- Use `secret` no webhook e verifique `X-Webhook-Signature` no consumidor.
- O SIP na 5060 recebe varredura da internet o tempo todo: só sessões com credenciais válidas registram (Digest MD5); considere restringir a porta por firewall aos IPs dos PBXs.

---

## 🛠️ Suporte Profissional

<div class="markdown-heading" dir="auto" id="bkmrk--78" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#%EF%B8%8F-suporte-profissional)</div>Precisa de ajuda para melhorar, customizar ou implementar o projeto?

📱 **WhatsApp:** +55 61 9 9687-8959

💼 Temos uma equipe especializada para:

✅ Customizações e melhorias ✅ Implementação e deploy completo ✅ Configuração de arquitetura SaaS ✅ Integração com outras APIs ✅ Desenvolvimento de features específicas ✅ Suporte técnico dedicado ✅ Consultoria em automação WhatsApp ✅ Treinamento e documentação

---

## 📄 Licença

<div class="markdown-heading" dir="auto" id="bkmrk--81" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" data-component="Octicon" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/AstraOnlineWeb/AstraCalls/tree/main#-licen%C3%A7a)</div>O AstraCalls é distribuído sob a licença **GNU AGPL-3.0** — veja [LICENSE](https://github.com/AstraOnlineWeb/AstraCalls/blob/main/LICENSE).

Isso significa que qualquer uso em rede (inclusive SaaS) exige disponibilizar o código-fonte das modificações aos usuários do serviço.

O AstraCalls é um fork do [WaCalls](https://github.com/JotaDev66/WaCalls), que é licenciado sob **MIT**. Conforme exigido pela MIT, o aviso de copyright original (© 2026 jotadev66) é preservado em [LICENSE.WaCalls](https://github.com/AstraOnlineWeb/AstraCalls/blob/main/LICENSE.WaCalls). As porções originais permanecem sob os termos MIT; o trabalho derivado, como um todo, é licenciado sob AGPL-3.0.