Whats77
Versão: 1.0.0
Compatibilidade: Retrocompatível com versões 0.1.x
Backend: Whats77 Manager (FastAPI + Redis + Z-API)
📘 Visão Geral
O Whats77 é um facilitador para o envio de mensagens via WhatsApp através da Z-API, agora totalmente integrado ao Whats77 Manager — um orquestrador que cuida de cadência, idempotência, retentativas automáticas e segurança via API Key.
Com esta nova integração, suas automações não precisam mais chamar a Z-API diretamente.
Basta chamar os mesmos métodos:
send_textsend_imagesend_audiosend_document
e o Manager fará todo o controle de fila e envio.
🆕 Além disso, o Whats77 agora suporta envio estruturado em grupo via:
send_group(...)→ usa o endpoint/enqueue_groupdo Manager, garantindo ordem e idempotência por grupo.
🧱 Arquitetura do Manager
whats77_manager/
├── apps/
│ ├── manager_api.py # FastAPI: /enqueue, /enqueue_group, /status, /health
│ ├── worker.py # Worker: consome fila e dispara via Z-API
│ ├── rate_limiter.py # Controle de cadência (Redis)
│ ├── scheduler.py # Retentativas e backoff exponencial
│ ├── storage.py # Idempotência, grupos e DLQ
│ ├── models.py # Schemas (MessageJob, GroupMessageRequest, SendResult)
│ └── zapi_client/
│ ├── whats77.py # Cliente HTTP direto na Z-API
│ └── senders.py # Multi-instâncias Z-API
└── .env
O Manager atua como intermediário:
- ✅ Controla limites e cadência
- ✅ Evita envios duplicados (idempotência)
- ✅ Distribui mensagens entre múltiplas instâncias Z-API
- ✅ Tenta novamente em caso de falha temporária
- 🔒 Requer API Key (
X-API-Key) para autenticação - 📦 Garante ordem e isolamento em grupos de mensagens (
/enqueue_group)
⚙️ Configuração
Arquivo .env
Crie um arquivo .env na raiz do seu projeto:
MANAGER_URL=http://localhost:8000
MANAGER_API_KEY=meu_token_super_seguro
SENDER_ID=0
🔁 Compatibilidade: Se as variáveis acima não existirem, o código tenta usar:
INSTANCE_ID,TOKEN,SECURITY_TOKEN(modo legado).
Configuração Manual
from whats77 import Whats77
# Inicialização manual (sem .env)
whatsapp = Whats77(
manager_url="http://localhost:8000",
manager_api_key="meu_token_super_seguro",
sender_id="0",
)
🚀 Uso Rápido
Inicializar
from whats77 import Whats77
whatsapp = Whats77() # carrega credenciais do .env
Enviar Texto
whatsapp.send_text(
phone_number="+5511999999999",
message="Olá! Esta mensagem foi enviada pelo Whats77 Manager."
)
Enviar Imagem
Aceita URL, data URI ou caminho local (automaticamente convertido para base64):
whatsapp.send_image(
phone_number="+5511999999999",
image_path_or_url="/tmp/imagem.jpg",
caption="Segue imagem de teste",
)
⚙️ Parâmetros:
view_once(opcional, compatível; ignorado pelo Manager)is_base64(opcional; mantido por compatibilidade)
Enviar Documento
Também aceita caminho local ou data URI:
whatsapp.send_document(
phone_number="+5511999999999",
file_path="/tmp/relatorio.pdf",
document_type="pdf",
caption="Segue o relatório.",
)
Enviar Áudio
from whats77 import Whats77
# converter áudio em base64
base64_audio = Whats77.parse_to_base64("/tmp/audio.mp3")
whatsapp.send_audio(
phone_number="+5511999999999",
base64_audio=base64_audio,
)
📦 Envio Estruturado em Grupo (novo)
O Whats77 suporta o envio de múltiplas mensagens em sequência para o mesmo contato (ou grupo) como um pacote lógico, usando o endpoint /enqueue_group do Manager.
Benefícios:
- ✅ Ordem garantida: as mensagens são enviadas na sequência definida (
itemsna ordem) - ✅ Sem intercalação: outras mensagens não quebram a sequência do grupo
- ✅ Idempotência por grupo: o mesmo
group_idnão gera reenvios duplicados - ✅ Mesmas regras de segurança: rate limiting, retentativas e DLQ continuam valendo
Método: send_group(...)
Assinatura:
send_group(
phone_number_or_group: str,
items: list[dict],
group_id: str | None = None,
priority: str | None = None,
) -> None
Parâmetros
-
phone_number_or_group:- Número E.164 (
"5511999999999","+5511999999999") - Ou ID de grupo WhatsApp (
"120363287726811196-group")
- Número E.164 (
-
items: lista de mensagens a enviar, na ordem desejada. Cada item é umdictcom pelo menos:Campo Tipo Obrigatório Descrição typestring ✅ "text","image","audio"ou"document"textstring para type="text"Conteúdo da mensagem image_path_or_urlouimage_urlstring para type="image"Caminho local, URL ou data URI audio_base64string para type="audio"Áudio em base64 file_pathoudocument_pathstring para type="document"Caminho local, data URI ou identificador document_typestring opcional ex: "pdf","xlsx"
Opcional por item:
idempotency_key→ se não informado, oWhats77gera automaticamente.image_caption,caption, etc.
Exemplo: texto + 2 imagens + PDF
from whats77 import Whats77
whatsapp = Whats77()
whatsapp.send_group(
phone_number_or_group="5599999999999",
group_id="relatorio-mensal-2025-01",
items=[
{
"type": "text",
"text": "Olá! Segue o relatório mensal de Janeiro/2025.",
},
{
"type": "image",
"image_path_or_url": "/app/graficos/vendas-jan.png",
"image_caption": "Gráfico de vendas do mês",
},
{
"type": "image",
"image_path_or_url": "/app/graficos/crescimento-jan.png",
"image_caption": "Crescimento comparativo",
},
{
"type": "document",
"file_path": "/app/docs/relatorio-jan-2025.pdf",
"document_type": "pdf",
"caption": "Relatório completo em PDF",
},
],
)
Se você não passar group_id, o Whats77 gera um automaticamente no formato:
group:<destinatario>:<uuid_curto>
🔢 Normalização de Números e IDs de Grupo
from whats77 import Whats77
# Telefone "cru" → E.164 BR
n = Whats77.normalize_phone_number("11999999999")
print(n) # 5511999999999
print(Whats77.is_valid_whatsapp_number("5511999999999"))
# True
IDs de Grupo do WhatsApp
O adaptador também aceita IDs de grupo no formato:
120363287726811196-group
Comportamento:
normalize_phone_number("120363287726811196-group")→ mantém exatamente o valor.is_valid_whatsapp_number("120363287726811196-group")→True.
Ou seja, você pode usar o mesmo objeto Whats77 para enviar:
- Para números individuais (
send_text,send_group, etc.) - Para grupos (
send_text,send_group, etc.) passando o ID do grupo.
🔐 Autenticação
Todas as requisições enviadas ao Manager contêm:
X-API-Key: <sua_chave>
Content-Type: application/json
Se a chave for inválida ou ausente:
{"detail": "Invalid or missing API key"}
🧩 Compatibilidade com o Código Antigo
| Função / Comportamento | Mantida? | Observações |
|---|---|---|
send_text() |
✅ | Idêntica |
send_image() |
✅ | Aceita caminho local / URL / data URI |
send_audio() |
✅ | Idêntica |
send_document() |
✅ | Aceita caminho local / data URI |
send_group() |
🆕 | Novo método para envio sequencial em grupo |
parse_to_base64() |
✅ | Utilitária igual |
normalize_phone_number() / is_valid_whatsapp_number() |
✅ | Agora também aceitam IDs de grupo (*-group) |
Parâmetro is_base64 |
✅ | Mantido por compatibilidade |
Campos instance_id, token |
⚙️ Opcional / legado | Usados só se MANAGER_URL não for configurada |
| Base URL API direta Z-API | ❌ Não usada — o Manager cuida dos envios |
Você pode substituir seu módulo antigo pelo novo
whats77.pysem alterar chamadas existentes. O uso desend_group()é opcional, mas recomendado para fluxos com múltiplas mensagens sequenciais.
🧠 Como Funciona Internamente
-
Whats77.send_*()monta umpayload JSONcontendo:idempotency_key(gerada automaticamente)sender_id,to,text/image_url/document_path/audio_base64priority(defaultpor padrão)
-
Para mensagens individuais, o payload é enviado para:
POST {MANAGER_URL}/enqueue -
Para grupos (
send_group()), o payload é enviado para:POST {MANAGER_URL}/enqueue_group -
O Manager:
-
Valida
X-API-Key -
Enfileira no Redis (
outbox,retry,dlq, etc.) -
O worker processa e dispara via Z-API respeitando:
- Rate limiting
- Retentativas com backoff exponencial
- Horário de silêncio (quiet hours)
-
🧾 Resposta de Exemplo do Manager
Mensagens individuais (/enqueue):
{
"queued": true,
"queue": "queue:outbox:default",
"idempotent": false
}
Grupos (/enqueue_group):
{
"queued": true,
"queue": "queue:outbox:default",
"group_id": "relatorio-mensal-2025-01",
"items_queued": 4,
"items_skipped": 0,
"total_items": 4
}
🧰 Dependências
| Biblioteca | Versão mínima |
|---|---|
requests |
2.0.0 |
python-dotenv |
0.21.0 |
Instale com:
pip install requests python-dotenv
🏁 Migração Rápida
-
Substitua seu arquivo antigo
whats77.pypelo novo adaptador. -
Adicione no
.envas variáveis do Manager:MANAGER_URL=http://localhost:8000 MANAGER_API_KEY=meu_token_super_seguro SENDER_ID=0
-
Rode seu código existente — nenhuma alteração nas chamadas antigas é necessária.
-
Para fluxos com várias mensagens sequenciais (relatórios, campanhas, etc.), comece a usar
send_group()para ter ordem garantida e idempotência por grupo.
Metadata
Release files for whats77 0.1.7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| whats77-0.1.7.tar.gz | 15.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| whats77-0.1.7-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.8 kB
Release files / whats77-0.1.7.tar.gz
| Download URL | whats77-0.1.7.tar.gz |
|---|---|
| Size | 15.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1f89394dc6d9575e67e25411b92c468ea299704ea03157a9da9a06cc84790345
|
|
BLAKE2b-256 checksum How to use checksums |
8f31ab8c8d60efeee93a2870181002552f5bedc796cfe2bad92848b8e3098cec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / whats77-0.1.7-py3-none-any.whl
| Download URL | whats77-0.1.7-py3-none-any.whl |
|---|---|
| Size | 11.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
eb9a56f4c79ad28ff209c5fafbd2ba86a62e7ac95bb1f5e59bf27f47a8b67a5d
|
|
BLAKE2b-256 checksum How to use checksums |
3a1e0f312163d72f50506b1cbce13991437585f862859a9a5dcf9c01bcfc3f26
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Security for whats77 0.1.7
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.