No project description provided
Project description
django-whatsapp-api-wrapper
Importante: Esta biblioteca está em desenvolvimento ativo e ainda não possui cobertura de testes automatizados. As APIs podem mudar entre versões menores. Utilize com cautela em produção, valide os fluxos críticos e, se possível, contribua com issues/PRs.
Um wrapper simples para enviar mensagens via WhatsApp Cloud API e expor um endpoint de webhook, pronto para integrar em qualquer projeto Django.
Instalação
python -m pip install django-whatsapp-api-wrapper
Configuração (Django)
- Adicione o app em
INSTALLED_APPS:
INSTALLED_APPS = [
# ...
"django_whatsapp_api_wrapper",
]
- Inclua as URLs no
urls.pyprincipal:
from django.urls import path, include
urlpatterns = [
# ...
path("whatsapp-api-wrapper/", include("django_whatsapp_api_wrapper.urls")),
]
- Defina as variáveis de ambiente (ou no seu
.env):
WHATSAPP_CLOUD_API_TOKEN=
WHATSAPP_CLOUD_API_PACKAGE_VERSION=0.1.1
WHATSAPP_CLOUD_API_VERSION=v23.0
WHATSAPP_CLOUD_API_PHONE_NUMBER_ID=
WHATSAPP_CLOUD_API_WABA_ID=
WHATSAPP_CLOUD_API_VERIFY_TOKEN=
- Configure a autenticação para as rotas de templates (opcional, mas recomendado):
# settings.py
# Opção 1: Usar Token Authentication do DRF (padrão)
WHATSAPP_API_AUTHENTICATION_CLASSES = [
'rest_framework.authentication.TokenAuthentication',
]
# Opção 2: Usar JWT (se você já tem configurado)
WHATSAPP_API_AUTHENTICATION_CLASSES = [
'rest_framework_simplejwt.authentication.JWTAuthentication',
]
# Opção 3: Usar API Key simples
WHATSAPP_API_AUTHENTICATION_CLASSES = [
'django_whatsapp_api_wrapper.authentication.APIKeyAuthentication',
]
WHATSAPP_API_KEY = "sua_api_key_secreta_aqui"
# Permissões (padrão: IsAuthenticated)
WHATSAPP_API_PERMISSION_CLASSES = [
'rest_framework.permissions.IsAuthenticated',
]
Importante: Se não configurar a autenticação, as rotas de templates usarão TokenAuthentication por padrão. As rotas de mensagens herdam a mesma configuração.
O endpoint de webhook ficará disponível em:
- GET/POST:
/whatsapp-api-wrapper/webhook/ - Verificação (GET):
/whatsapp-api-wrapper/webhook/?hub.mode=subscribe&hub.verify_token=<TOKEN>&hub.challenge=123
Extensibilidade do Webhook
Você pode customizar o processamento do webhook no projeto hospedeiro de duas formas:
- Via setting com handler plugável:
# settings.py
WHATSAPP_WEBHOOK_HANDLER = "meuapp.whatsapp.handle_webhook"
# meuapp/whatsapp.py
from django.http import JsonResponse
def handle_webhook(request, payload):
# sua lógica aqui (salvar eventos, acionar tasks, etc)
return JsonResponse({"ok": True})
- Via signal
webhook_event_received:
from django.dispatch import receiver
from django_whatsapp_api_wrapper.signals import webhook_event_received
@receiver(webhook_event_received)
def on_whatsapp_event(sender, payload, request, **kwargs):
# sua lógica aqui
pass
Mensagens
Envio e recebimento de mensagens via Cloud API.
Envio (Python)
from django_whatsapp_api_wrapper import WhatsApp
from django_whatsapp_api_wrapper.messages import types as WATypes
wp = WhatsApp()
# Texto (construa o objeto e passe o objeto diretamente)
text = WATypes.Text(body="olá do wrapper", preview_url=False)
m_text = wp.build_message(to="551199999999", type="text", data=text)
m_text.send()
# Template
tpl = WATypes.Template(name="opa", language={"code": "pt_BR"}, components=[])
m_tpl = wp.build_message(to="551199999999", type="template", data=tpl)
m_tpl.send()
# Sticker (exemplo com media ID)
stk = WATypes.Sticker(id="MEDIA_ID")
m_stk = wp.build_message(to="551199999999", type="sticker", data=stk)
m_stk.send()
# Imagem por URL
img = WATypes.Image(link="https://exemplo.com/foto.jpg", caption="Legenda")
m_img = wp.build_message(to="551199999999", type="image", data=img)
m_img.send()
Webhook
- Recebe eventos (mensagens/atualizações de status) em
GET/POST /whatsapp-api-wrapper/webhook/. - Verificação (GET):
/whatsapp-api-wrapper/webhook/?hub.mode=subscribe&hub.verify_token=<TOKEN>&hub.challenge=123. - Personalize via setting
WHATSAPP_WEBHOOK_HANDLERou escute o signalwebhook_event_received(veja seção Extensibilidade do Webhook acima).
Endpoints HTTP de Mensagens (DRF)
Prefixo base: /whatsapp-api-wrapper/messages/
⚠️ Importante: Todos os endpoints de mensagens requerem autenticação (veja seção Autenticação acima).
- Enviar mensagem (genérico)
POST /whatsapp-api-wrapper/messages/send/
Body (exemplos por tipo):
Texto
{ "to": "551199999999", "type": "text", "text": {"preview_url": false, "body": "Olá!"} }
Texto (reply)
{ "to": "551199999999", "type": "text", "context": {"message_id": "wamid.xxx"}, "text": {"body": "Resposta"} }
Template
{ "to": "551199999999", "type": "template", "template": {"name": "opa", "language": {"code": "pt_BR"}, "components": []} }
Imagem por URL
{ "to": "551199999999", "type": "image", "image": {"link": "https://exemplo.com/foto.jpg", "caption": "Legenda"} }
- Enviar texto
POST /whatsapp-api-wrapper/messages/text/
{ "to": "551199999999", "body": "Olá!", "preview_url": false }
Exemplo com curl:
curl -X POST \
-H "Authorization: Token seu_token_aqui" \
-H "Content-Type: application/json" \
-d '{"to": "551199999999", "body": "Olá!", "preview_url": false}' \
"$BASE/whatsapp-api-wrapper/messages/text/"
- Responder com texto
POST /whatsapp-api-wrapper/messages/text/reply/
{ "to": "551199999999", "reply_to": "wamid.xxx", "body": "Resposta", "preview_url": false }
- Enviar template
POST /whatsapp-api-wrapper/messages/template/
{ "to": "551199999999", "name": "opa", "language": {"code": "pt_BR"}, "components": [] }
Respostas: mesmas do Graph (inclui messages[0].id com prefixo wamid).
Mensagens por tipo (Python + HTTP)
Observação: Para todos os tipos abaixo você pode:
- Python: instanciar o objeto em
django_whatsapp_api_wrapper.messages.typese passar diretamente comodata=<objeto>nobuild_message. - HTTP: usar o endpoint genérico
POST /whatsapp-api-wrapper/messages/send/comtype=<tipo>e o objeto correspondente no corpo. - Atalhos existentes:
text/,text/reply/,template/.
Texto
- Python:
text = WATypes.Text(body="Olá!", preview_url=False)
wp.build_message(to="551199999999", type="text", data=text).send()
- HTTP (atalho):
POST /messages/text/
{ "to": "551199999999", "body": "Olá!", "preview_url": false }
- HTTP (genérico):
POST /messages/send/
{ "to": "551199999999", "type": "text", "text": {"body": "Olá!", "preview_url": false} }
Texto (reply)
- Python:
text = WATypes.Text(body="Resposta")
wp.build_message(to="551199999999", type="text", data=text).send()
# Para reply via HTTP use context.message_id
- HTTP (atalho):
POST /messages/text/reply/
{ "to": "551199999999", "reply_to": "wamid.xxx", "body": "Resposta", "preview_url": false }
- HTTP (genérico):
POST /messages/send/
{ "to": "551199999999", "type": "text", "context": {"message_id": "wamid.xxx"}, "text": {"body": "Resposta"} }
Template
- Python:
tpl = WATypes.Template(name="opa", language={"code": "pt_BR"}, components=[])
wp.build_message(to="551199999999", type="template", data=tpl).send()
- HTTP (atalho):
POST /messages/template/
{ "to": "551199999999", "name": "opa", "language": {"code": "pt_BR"}, "components": [] }
- HTTP (genérico):
POST /messages/send/
{ "to": "551199999999", "type": "template", "template": {"name": "opa", "language": {"code": "pt_BR"}, "components": []} }
Imagem
- Python:
img = WATypes.Image(link="https://exemplo.com/foto.jpg", caption="Legenda")
wp.build_message(to="551199999999", type="image", data=img).send()
- HTTP (genérico):
POST /messages/send/
{ "to": "551199999999", "type": "image", "image": {"link": "https://exemplo.com/foto.jpg", "caption": "Legenda"} }
Áudio
- Python:
aud = WATypes.Audio(id="MEDIA_ID") # ou link="https://..."
wp.build_message(to="551199999999", type="audio", data=aud).send()
- HTTP (genérico):
POST /messages/send/
{ "to": "551199999999", "type": "audio", "audio": {"id": "MEDIA_ID"} }
Documento
- Python:
doc = WATypes.Document(link="https://exemplo.com/arquivo.pdf", filename="arquivo.pdf")
wp.build_message(to="551199999999", type="document", data=doc).send()
- HTTP (genérico):
POST /messages/send/
{ "to": "551199999999", "type": "document", "document": {"link": "https://exemplo.com/arquivo.pdf", "filename": "arquivo.pdf"} }
Vídeo
- Python:
vid = WATypes.Video(id="MEDIA_ID", caption="Demo")
wp.build_message(to="551199999999", type="video", data=vid).send()
- HTTP (genérico):
POST /messages/send/
{ "to": "551199999999", "type": "video", "video": {"id": "MEDIA_ID", "caption": "Demo"} }
Sticker
- Python:
stk = WATypes.Sticker(id="MEDIA_ID")
wp.build_message(to="551199999999", type="sticker", data=stk).send()
- HTTP (genérico):
POST /messages/send/
{ "to": "551199999999", "type": "sticker", "sticker": {"id": "MEDIA_ID"} }
Localização
- Python:
loc = WATypes.Location(latitude=-23.56, longitude=-46.63, name="SP", address="Av. Paulista")
wp.build_message(to="551199999999", type="location", data=loc).send()
- HTTP (genérico):
POST /messages/send/
{ "to": "551199999999", "type": "location", "location": {"latitude": -23.56, "longitude": -46.63, "name": "SP", "address": "Av. Paulista"} }
Contacts
- Python:
contact = WATypes.Contact(name={"formatted_name": "Maria"}, phones=[{"phone": "+551199999999", "type": "CELL"}])
wp.build_message(to="551199999999", type="contacts", data=[contact]).send() # lista de contatos
- HTTP (genérico):
POST /messages/send/
{ "to": "551199999999", "type": "contacts", "contacts": [{ "name": {"formatted_name": "Maria"}, "phones": [{"phone": "+551199999999", "type": "CELL"}] }] }
Reaction
- Python:
react = WATypes.Reaction(message_id="wamid.xxx", emoji="😀")
wp.build_message(to="551199999999", type="reaction", data=react).send()
- HTTP (genérico):
POST /messages/send/
{ "to": "551199999999", "type": "reaction", "reaction": {"message_id": "wamid.xxx", "emoji": "😀"} }
Interativo (Reply Buttons)
- Python:
interactive = WATypes.Interactive(
type="button",
header={"type": "text", "text": "Título"},
body={"text": "Mensagem"},
footer={"text": "Rodapé"},
action={"buttons": [{"title": "OK", "id": "ok"}, {"title": "Cancelar", "id": "cancel"}]}
)
wp.build_message(to="551199999999", type="interactive", data=interactive).send()
- HTTP (genérico):
POST /messages/send/
{ "to": "551199999999", "type": "interactive", "interactive": {
"type": "button",
"header": {"type": "text", "text": "Título"},
"body": {"text": "Mensagem"},
"footer": {"text": "Rodapé"},
"action": {"buttons": [
{"type": "reply", "title": "OK", "id": "ok"},
{"type": "reply", "title": "Cancelar", "id": "cancel"}
]}
} }
Autenticação
Proteção das Rotas de API
Por padrão, todas as rotas de templates (/templates/) e mensagens (/messages/) são protegidas e requerem autenticação. O webhook permanece público (necessário para o WhatsApp).
Opções de Autenticação
1. Token Authentication (Padrão)
# settings.py
WHATSAPP_API_AUTHENTICATION_CLASSES = [
'rest_framework.authentication.TokenAuthentication',
]
Uso:
curl -H "Authorization: Token seu_token_aqui" \
"$BASE/whatsapp-api-wrapper/templates/"
2. JWT Authentication
# settings.py
WHATSAPP_API_AUTHENTICATION_CLASSES = [
'rest_framework_simplejwt.authentication.JWTAuthentication',
]
Uso:
curl -H "Authorization: Bearer seu_jwt_token" \
"$BASE/whatsapp-api-wrapper/templates/"
3. API Key Authentication
# settings.py
WHATSAPP_API_AUTHENTICATION_CLASSES = [
'django_whatsapp_api_wrapper.authentication.APIKeyAuthentication',
]
WHATSAPP_API_KEY = "sua_api_key_secreta"
Uso:
curl -H "X-WhatsApp-API-Key: sua_api_key_secreta" \
"$BASE/whatsapp-api-wrapper/templates/"
4. Múltiplas Autenticações
# settings.py
WHATSAPP_API_AUTHENTICATION_CLASSES = [
'rest_framework.authentication.TokenAuthentication',
'django_whatsapp_api_wrapper.authentication.APIKeyAuthentication',
]
Permissões Customizadas
# settings.py
WHATSAPP_API_PERMISSION_CLASSES = [
'rest_framework.permissions.IsAuthenticated',
# ou 'rest_framework.permissions.IsAdminUser',
# ou 'myapp.permissions.CustomPermission',
]
Templates
Endpoints REST (DRF) para gerenciar Message Templates do WhatsApp (proxy para Graph API). Todos os endpoints abaixo partem do prefixo que você incluir no projeto, por exemplo: .../whatsapp-api-wrapper/.
⚠️ Importante: Todos os endpoints de templates requerem autenticação (veja seção Autenticação acima).
Requisitos de ambiente: WHATSAPP_CLOUD_API_TOKEN, WHATSAPP_CLOUD_API_VERSION, WHATSAPP_CLOUD_API_WABA_ID.
Aqui a documentação OFICIAL:
https://www.postman.com/meta/whatsapp-business-platform/folder/2ksdd2s/whatsapp-cloud-api
Listar e criar
- GET
GET /templates/?limit=&after=&before= - POST
POST /templates/com payload conforme a Graph API.
Exemplo de criação:
curl -X POST \
"$BASE/whatsapp-api-wrapper/templates/" \
-H "Content-Type: application/json" \
-d '{
"name": "authentication_code_copy_code_button",
"language": "en_US",
"category": "AUTHENTICATION",
"components": [
{"type": "BODY", "add_security_recommendation": true},
{"type": "FOOTER", "code_expiration_minutes": 10},
{"type": "BUTTONS", "buttons": [{"type": "OTP", "otp_type": "COPY_CODE", "text": "Copy Code"}]}
]
}'
Buscar por ID e editar
- GET
GET /templates/<template_id>/ - POST
POST /templates/<template_id>/para editar (mesmo formato do corpo de criação).
Buscar e excluir por nome
- GET
GET /templates/by-name/?name=<TEMPLATE_NAME> - DELETE
DELETE /templates/by-name/?name=<TEMPLATE_NAME>
Excluir por ID (hsm_id) e nome
- DELETE
DELETE /templates/delete-by-id/?hsm_id=<HSM_ID>&name=<NAME>
Obter namespace
- GET
GET /templates/namespace/
Notas:
- Os payloads aceitos seguem a documentação oficial de Message Templates da Meta (Graph API). Este wrapper só valida campos básicos e encaminha a requisição.
- As respostas retornadas são as mesmas da Graph API (status code e corpo JSON), para facilitar troubleshooting.
Notas
- Nome do pacote no PyPI:
django-whatsapp-api-wrapper - Nome do módulo/import:
django_whatsapp_api_wrapper
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_whatsapp_api_wrapper-0.14.0.tar.gz.
File metadata
- Download URL: django_whatsapp_api_wrapper-0.14.0.tar.gz
- Upload date:
- Size: 55.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.6.1 CPython/3.11.6 Darwin/25.2.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
48292c985b73c1a5e28fc63825d0e35d2f9a512097d7eba73c2e354b4331156d
|
|
| MD5 |
7de72f15a63cd8c36989ff117a4de9e8
|
|
| BLAKE2b-256 |
51891c3c05833a6832db45d297b280a5bb7e77a5c987a58fac3ec9d8e2c492ee
|
File details
Details for the file django_whatsapp_api_wrapper-0.14.0-py3-none-any.whl.
File metadata
- Download URL: django_whatsapp_api_wrapper-0.14.0-py3-none-any.whl
- Upload date:
- Size: 85.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.6.1 CPython/3.11.6 Darwin/25.2.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9389090eff96ac94f6e351c9e4de44d1fe3253cda5b11548037c77eac1d6d290
|
|
| MD5 |
aabd8294e9243b1adfb28daad21ddd8e
|
|
| BLAKE2b-256 |
50f2b3eace6f27a11b02b6491438e2fe83275086f151607e01f7f29081a20f2b
|