django-meta-whatsapp is not just an API wrapper — it's a fully-featured, drop-in WhatsApp CRM and messaging platform that lives entirely within your existing Django project. Beautiful Tailwind UI, real-time inbox, bulk campaigns, webhook engine, and REST APIs — all without third-party SaaS subscriptions.
✨ Features
- 📨 Live Unified Inbox — Real-time chat interface with media, reply threading, and message status ticks.
- 🚀 Marketing Campaigns — Schedule and send bulk messages using approved WhatsApp Templates. Track delivery, read rates, and bounce rates.
- 👥 Contact Management — Import CSVs, assign dynamic colored Labels, and auto-sync users who subscribe via WhatsApp deep-links.
- 📋 WhatsApp Flows — Build multi-step native forms inside WhatsApp (Feedback, Lead Gen, Appointments). Full lifecycle: create → upload JSON → publish → send → capture responses via webhook. Includes 3 starter templates and a
whatsapp_flow_completedsignal. - 🎯 Contact Filter Presets — Define named audience filters in settings for one-click campaign targeting.
- 🔗 User Model Integration — Link your Django
Usermodel toWhatsAppContactwith pluggable audience providers. - 🚫 Blocked User Sync — Automatically detect and exclude users who block your business.
- 🧩 Template Sync — Pull all approved WhatsApp message templates directly from Meta with one click.
- 🔗 In-App Signups — Create and manage
wa.medeep links so users can instantly opt-in. - ⚡ Webhooks Engine — Built-in webhook endpoints to automatically ingest incoming messages, delivery receipts, status updates, and Flow completions (
nfm_reply). - 🔑 REST APIs — Send text, location, template; list chats/campaigns (API-key auth).
- 🏢 Multi-Account — One Django project, multiple WhatsApp Business Accounts.
- 🔒 Encrypted Secrets — Access tokens stored symmetrically encrypted (Fernet/AES-128) — key derived from
SECRET_KEYby default.
📦 Installation
# Using uv (Recommended)
uv add django-meta-whatsapp
# Using pip
pip install django-meta-whatsapp
⚙️ Configuration
1. Add to INSTALLED_APPS:
INSTALLED_APPS = [
# ...
"django_meta_whatsapp",
]
2. Mount URLs in urls.py:
from django.urls import path, include
urlpatterns = [
# ...
path("whatsapp/", include("django_meta_whatsapp.urls", namespace="django_meta_whatsapp")),
]
3. Add WHATSAPP settings to settings.py:
WHATSAPP = {
# ── Required ──────────────────────────────────────────
"API_TOKEN": "EAA...",
"PHONE_NUMBER_ID": "1234567890",
"WEBHOOK_VERIFY_TOKEN": "your_secure_random_string",
# ── UI Customization (optional) ───────────────────────
"DASHBOARD_NAME": "My Business CRM",
"DASHBOARD_LOGO": "https://yourwebsite.com/logo.png",
# ── Audience Providers (optional) ─────────────────────
# Map your own model querysets as named campaign audiences
"PHONE_FIELD": "phone", # field on your model with the phone number
"NAME_FIELD": "name", # field on your model with the display name
"AUDIENCES": {
"All Users": "myapp.audiences.all_users",
"VIP Customers": "myapp.audiences.vip_customers",
},
# ── Contact Filter Presets (optional) ─────────────────
# Pre-defined filters shown as a dropdown in the Campaign form
"CONTACT_FILTERS": {
"VIP Customers": '{"labels__name": "VIP"}',
"Subscribed via Link": '{"subscribed_via_signup__isnull": false}',
"New This Month": '{"created_at__gte": "2024-06-01"}',
},
# ── Security & Encryption (optional) ──────────────────
# Derived from SECRET_KEY by default. Used to symmetrically encrypt access tokens in DB.
"ENCRYPTION_KEY": "your_custom_secret_key_or_password",
}
4. Run migrations:
python manage.py migrate
5. Credential Encryption (Secure-by-Default):
Database-stored access tokens (in the WhatsAppAccount model) are automatically encrypted using symmetric encryption (Fernet).
- Default Key: The encryption key is derived automatically from your Django project's
SECRET_KEY. - Custom Key: To use a separate key, define
"ENCRYPTION_KEY"inside yourWHATSAPPsettings. - Upgrades: If you have existing plain text tokens, the database fallback will read them cleanly. Saving the account again will seamlessly encrypt it.
🚀 Quickstart
- Visit
/whatsapp/in your browser. - The UI will prompt you to add a WhatsApp Account if none exists.
- Set your Meta App Webhook URL to
https://yourdomain.com/whatsapp/webhook/. - Sync your templates from the Templates tab.
- Start chatting from the Inbox!
🔗 Linking Your Django User Model
You can link WhatsAppContact to your existing User model without modifying the package. Three approaches are documented:
Option A — Profile Model (recommended):
from django_meta_whatsapp.models import WhatsAppContact
class UserWhatsAppProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="whatsapp_profile")
contact = models.OneToOneField(WhatsAppContact, on_delete=models.SET_NULL, null=True, blank=True)
Option B — Query your User model directly as a campaign audience:
# myapp/audiences.py
from django.contrib.auth import get_user_model
User = get_user_model()
def all_users():
return User.objects.filter(is_active=True, phone__isnull=False)
See the full documentation for signals-based auto-linking and more filter patterns.
🔑 REST API
All endpoints require an X-API-Key header (generated from the dashboard under Settings → API Keys).
# Send a text message
curl -X POST https://yourdomain.com/whatsapp/api/send-message/ \
-H "X-API-Key: your-key" \
-H "Content-Type: application/json" \
-d '{"phone": "919876543210", "message": "Hello!"}'
# Send an approved template
curl -X POST https://yourdomain.com/whatsapp/api/send-template/ \
-H "X-API-Key: your-key" \
-H "Content-Type: application/json" \
-d '{"phone": "919876543210", "template_name": "order_update", "language": "en", "body_params": ["Rahul", "ORD-999"]}'
📖 Full Documentation
https://rahul-baberwal.github.io/django-meta-whatsapp
📋 Changelog
v1.1.0 — WhatsApp Flows
- 📋 WhatsApp Flows — Full lifecycle management: create, upload JSON, publish, deprecate, clone, delete via Meta Graph API.
- 🚀 3 Starter Templates — Built-in Flow JSON templates for Feedback, Lead Generation, and Appointment Booking.
- 📥 Flow Responses — Webhook automatically captures
nfm_replysubmissions, stores them asWhatsAppFlowResponserows. - ⚡
whatsapp_flow_completedsignal — Hook into flow completions from any Django app. - 📊 Stats Tracking —
sent_countandcompletion_countauto-updated on every send and webhook submission. - 🔒 Dynamic Flows Support —
is_dynamicflag + endpoint URI field + RSA public key upload utility. - 🛠 Admin Integration —
WhatsAppFlowAdminandWhatsAppFlowResponseAdminregistered in Django Admin. - 🧭 Sidebar Navigation — Flows entry added to the dashboard sidebar.
v1.0.5 — Encrypted DB Secrets
- 🔒 Database Credential Encryption — Symmetrically encrypt
access_tokenin database records (WhatsAppAccountmodel) using Fernet cryptography. - ⚙️ Custom Encryption Key — Dynamically derived from
SECRET_KEYby default, customizable viaWHATSAPP['ENCRYPTION_KEY']. - 🔄 Plaintext Fallback — Transparent migration with backward-compatibility for existing plaintext credentials.
v1.0.4
- ✅ Updated README with complete settings reference and REST API examples
- ✅ Version badge added to docs (auto-updated each release)
- ✅ Django 4.0 / 5.0 / 5.1 + Python 3.9+ version tags corrected in docs & README
v1.0.3
- ✅ Contact Filter Presets — define named filters in settings, auto-populate campaign form
- ✅ User model linking docs — 3 integration patterns with code examples
- ✅ Dashboard logo updated to custom PNG
- ✅ Sidebar scrollbar hidden for premium feel
v1.0.2
- ✅ Single clean migration (
0001_initial.py) - ✅ Mintlify-style documentation site (
docs/index.html) - ✅ REST API documentation with cURL examples
- ✅
pyproject.toml+uvmigration
v1.0.1
- ✅ Label system with color picker (tom-select)
- ✅ Blocked user sync, In-App Signups, Catalog products
- ✅ WhatsApp Catalog product management
Release files for django-meta-whatsapp 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| django_meta_whatsapp-1.1.0.tar.gz | 3.0 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_meta_whatsapp-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 5.0 MB
Release files / django_meta_whatsapp-1.1.0.tar.gz
| Download URL | django_meta_whatsapp-1.1.0.tar.gz |
|---|---|
| Size | 3.0 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7d5208bb8914ea96ac4a7cbb4e087c4e5d11e4e0b27f793483ce500ca127bca8
|
|
BLAKE2b-256 checksum How to use checksums |
78af52ca6df2386384a88a2bf0eb9b6143ae979bee68dcafc2275084755a7c6f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 26, 2026.
Transparency logRelease files / django_meta_whatsapp-1.1.0-py3-none-any.whl
| Download URL | django_meta_whatsapp-1.1.0-py3-none-any.whl |
|---|---|
| Size | 2.0 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dbf509b4321247d433947ea8df806303bf9b74d010af8c371f8510c21bcaf55e
|
|
BLAKE2b-256 checksum How to use checksums |
58fb458d59a919f46720a21050a984e976afbeb3e9b76d26a4869eef93d48156
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 26, 2026.
Transparency log