Atividade Recente
Enviar SMS
Mensagens Enviadas
| Data | Remetente | Destino | Mensagem | Partes | Estado | Método | Ações |
|---|
Contactos
| Nome | Telefone | Grupo | Ações |
|---|
Utilizadores
| Nome | Empresa | Role | Créditos | Dispositivos | Estado | Último Login | Ações |
|---|
Faturas
| Nº Fatura | Utilizador | Créditos | Valor | Estado | Data | Ações |
|---|
Histórico de Créditos
| Data | Tipo | Montante | Saldo Antes | Saldo Depois | Descrição |
|---|
Controlo do Modem
Dispositivos Android
| Dispositivo | Número | Estado | Bateria | SMS Hoje | Limite Diário | SMS Total | Utilizadores | Último Contacto | Ações |
|---|
Atribuições Utilizador → Dispositivo
| Utilizador | Dispositivo | Prioridade | Estado | Créditos | Ações |
|---|
Instruções APK
Para usar um telemóvel Android como gateway de SMS:
1. Instale a APK SMS Gateway Bridge no telemóvel
2. Registe o dispositivo aqui e copie o Device Token
3. Na APK, insira o URL do servidor e o token
4. A APK mantém uma conexão WebSocket permanente
5. Quando o servidor receber um pedido de SMS, envia para o telemóvel
6. O telemóvel envia o SMS via rede GSM nativa
⚠️ Mantenha o telemóvel ligado ao carregador e com dados móveis ativos.
O Seu API Token
A carregar...
Documentação da API
Gerador de APK Android
Sobre o Gerador de APK
Compile o APK do SMS Gateway diretamente no servidor. Pode gerar um APK genérico ou um APK personalizado com as configurações de um utilizador já embarcadas.
APK Genérico
APK padrão sem configurações. O utilizador terá que configurar manualmente ou importar ficheiro JSON.
APK Personalizado
Gere APK com configurações de um utilizador já inseridas. Pronto a usar!
Vá aos Utilizadores e clique no botão
Histórico de Builds
| Data | Tipo | Utilizador | Status | Tamanho | Ações |
|---|---|---|---|---|---|
| Nenhum build realizado ainda | |||||
Ajuda - Exportar & Importar Configurações
O que é a Exportação de Configurações?
Permite exportar as credenciais e configurações de um utilizador para um ficheiro JSON que pode ser importado no Android App ou noutros desenvolvimentos.
Como Exportar Configurações
- Aceda ao menu Utilizadores
- Clique no botão Editar do utilizador desejado
- No modal de edição, clique em Exportar Config
- O ficheiro será descarregado:
sms-gateway-email-config.json
Estrutura do Ficheiro
{
"version": "1.0",
"server": {
"url": "http://servidor:9080",
"api_url": "http://servidor:9080/api",
"websocket_url": "ws://servidor:9081/ws/android",
"device_token": "token_64_caracteres_dispositivo"
},
"user": {
"id": "...", "name": "...", "email": "...",
"api_token": "token_64_caracteres", "credits": 100
}
}
Importar no Android App
- Transfira o ficheiro JSON para o dispositivo Android
- Abra o SMS Gateway App
- Clique em Importar Config
- Selecione o ficheiro JSON descarregado
- Configuração aplicada automaticamente!
- Clique em Conectar
Usar em Outros Desenvolvimentos
const config = JSON.parse(fileContent);
fetch(`${config.server.api_url}/sms/send`, {
headers: { 'X-API-Token': config.user.api_token },
method: 'POST',
body: JSON.stringify({ to: '+351...', message: 'Olá!' })
});
config = json.load(open('config.json'))
requests.post(f"{config['server']['api_url']}/sms/send",
headers={'X-API-Token': config['user']['api_token']},
json={'to': '+351...', 'message': 'Olá!'})
Segurança
- NUNCA partilhar ficheiros de configuração publicamente
- O API Token dá acesso total à conta
- Armazenar em locais seguros e encriptados
- Rotacionar tokens periodicamente
WhatsApp API (Evolution)
Um único serviço, várias instâncias
Temos uma Evolution API central partilhada. Cada projecto (CliniMag, GymBooking, wooc50c, woocxd, novos) cria a sua própria "instância" nessa API e liga o seu telemóvel via QR. Os tokens de cada instância são isolados — um projecto não vê o WhatsApp de outro.
URLs canónicas
| Serviço | URL | Uso |
|---|---|---|
| Evolution API (base) | https://whatsappApi.magweb.ddnsfree.com ✅ |
Todos os backends dos projectos chamam esta URL |
| Manager oficial | https://whatsappapi.magweb.ddnsfree.com/manager |
UI completa (contactos, chats, integrações) |
| Painel interno (aqui) | sidebar → WhatsApp → Instâncias |
UI simplificada, login unificado, sem expor API key |
| URL local (LAN) | http://192.168.1.141:8181 |
Acesso directo sem passar pelo NPM |
| DNS docker interno | http://clinimag-evolution:8080 |
Chamadas entre containers na rede infra_net |
Credenciais do Manager oficial
Ao abrir /manager pede duas coisas:
- Server URL:
https://whatsappapi.magweb.ddnsfree.com - API Key Global:
CliniMag_Evolution_2024
Criar uma nova instância
- Painel interno (aqui): Sidebar → Instâncias → Nova Instância
- Escolhe nome (convenção:
<projecto>-default, ex:wooc50c-default) - QR code aparece imediatamente
- No telemóvel: WhatsApp → Definições → Dispositivos ligados → Ligar dispositivo → escanear
- Guarda o token da instância (aparece na página de detalhe, com botão copiar) — é este que o backend do projecto usa
Integrar num projecto novo
Três variáveis de ambiente no docker-compose.yml / .env do backend do projecto:
EVOLUTION_API_URL=https://whatsappApi.magweb.ddnsfree.com EVOLUTION_API_KEY=CliniMag_Evolution_2024 EVOLUTION_INSTANCE_NAME=<projecto>-default
Depois basta chamar POST /message/sendText/<instância>. Exemplos:
async function sendWhatsApp(number, text) {
const r = await fetch(
`${process.env.EVOLUTION_API_URL}/message/sendText/${process.env.EVOLUTION_INSTANCE_NAME}`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
apikey: process.env.EVOLUTION_API_KEY
},
body: JSON.stringify({ number, text })
}
);
if (!r.ok) throw new Error(`WA API ${r.status}`);
return r.json();
}
// Uso: sendWhatsApp('351912345678', 'Olá, a sua consulta é amanhã às 10h');
public async Task<bool> SendWhatsAppAsync(string number, string text)
{
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("apikey", _config["Evolution:ApiKey"]);
var payload = new { number, text };
var url = $"{_config["Evolution:Url"]}/message/sendText/{_config["Evolution:Instance"]}";
var res = await client.PostAsJsonAsync(url, payload);
return res.IsSuccessStatusCode;
}
function wp_send_whatsapp($number, $text) {
$url = getenv('EVOLUTION_API_URL') . '/message/sendText/' . getenv('EVOLUTION_INSTANCE_NAME');
return wp_remote_post($url, [
'headers' => [
'Content-Type' => 'application/json',
'apikey' => getenv('EVOLUTION_API_KEY')
],
'body' => json_encode(['number' => $number, 'text' => $text])
]);
}
import os, requests
def send_whatsapp(number: str, text: str):
url = f"{os.getenv('EVOLUTION_API_URL')}/message/sendText/{os.getenv('EVOLUTION_INSTANCE_NAME')}"
r = requests.post(url,
headers={'apikey': os.getenv('EVOLUTION_API_KEY'), 'Content-Type': 'application/json'},
json={'number': number, 'text': text})
r.raise_for_status()
return r.json()
curl -X POST https://whatsappApi.magweb.ddnsfree.com/message/sendText/clinimag-default \
-H "apikey: CliniMag_Evolution_2024" \
-H "Content-Type: application/json" \
-d '{"number":"351912345678","text":"Teste!"}'
Endpoints principais
| Método | Path | Descrição |
|---|---|---|
| GET | /instance/fetchInstances | Listar todas as instâncias |
| POST | /instance/create | Criar instância nova (devolve QR) |
| GET | /instance/connect/<name> | Obter/regenerar QR code |
| GET | /instance/connectionState/<name> | Estado: open / connecting / close |
| PUT | /instance/restart/<name> | Reiniciar sessão |
| DELETE | /instance/logout/<name> | Fazer logout (mantém instância) |
| DELETE | /instance/delete/<name> | Apagar instância inteira |
| POST | /message/sendText/<name> | Enviar texto |
| POST | /message/sendMedia/<name> | Enviar imagem/PDF/vídeo |
| POST | /message/sendLocation/<name> | Enviar localização GPS |
| POST | /chat/whatsappNumbers/<name> | Verificar se número existe no WA |
| POST | /webhook/set/<name> | Configurar webhook para eventos |
Receber mensagens (webhook)
Se quiseres receber notificações em tempo real (mensagens recebidas, mudanças de estado, tick azul), configura um webhook. O SMS Gateway já tem um endpoint interno pronto a receber:
POST /webhook/set/<instância>
{
"webhook": {
"enabled": true,
"url": "https://sms.magweb.ddnsfree.com/api/whatsapp/webhook/<instância>",
"byEvents": false,
"base64": false,
"events": ["MESSAGES_UPSERT","CONNECTION_UPDATE","SEND_MESSAGE","MESSAGES_UPDATE","QRCODE_UPDATED"]
}
}
Atalho na UI: Instâncias → clica na instância → secção Webhook → "Usar webhook interno" → Guardar. Depois qualquer mensagem recebida vai directamente para a nossa BD e aparece em Msgs WhatsApp.
Convenções para projectos Magalhães
| Projecto | Instância | Uso |
|---|---|---|
| CliniMag | clinimag-default | Notificações de consultas |
| CliniMag (Ímpar Terapias) | clinimag-impar-terapias | Instância dedicada do cliente |
| GymBooking | gymbooking-default | Lembretes de aulas |
| AssistPro | assistpro-default | Assistência técnica |
| wooc50c | wooc50c-default | Notif. encomendas Sage 50c |
| woocxd | woocxd-default | Notif. encomendas XD Software |
Troubleshooting
- Estado
closeapós ficar quieto: WhatsApp desliga sessões inactivas >14 dias ou se abrires WhatsApp Web noutro sítio. Reactivar: Painel → Instância → Restart + novo QR scan. - Erro
401 device_removed: alguém removeu o dispositivo em WhatsApp → Dispositivos ligados. Reautenticar QR. - Mensagem não entregue: confirmar formato do número (com indicativo, sem
+:351912345678). Verificar se existe no WA comPOST /chat/whatsappNumbers/<instância>. - Webhook não é chamado: URL tem de ser acessível de fora do container Evolution. Deve responder
200 OKem <10s. Ver logs comdocker logs clinimag-evolution. - Erro
column wavoipToken does not exist: migração Prisma incompleta, executar uma vez:docker exec mariadb mysql -uroot -pOrtodox086 whatsapp_db -e " ALTER TABLE Instance ADD COLUMN wavoipToken VARCHAR(100) NULL; ALTER TABLE Setting ADD COLUMN wavoipToken VARCHAR(100) NULL; "
Documentação adicional
- Manual técnico completo:
D:\Repos\whatsappApi\MANUAL_TECNICO.md(também em.htmle.pdf) - Documentação oficial Evolution: doc.evolution-api.com/v2/
- Guia de integração (Node/C#/Python/PHP/Bash):
D:\Repos\whatsappApi\INTEGRATION.md - Arquitectura:
D:\Repos\whatsappApi\README.md