Wappa 🤖
Open Source Framework for WhatsApp Business Applications
Build intelligent WhatsApp bots, workflows, and chat applications with clean architecture and modern Python.
v0.13.0 — Clean-break release —
inbox_idreplacestenant_id/owner_idas core identity, all compatibility shims removed, webhook schemas consolidated underwappa/webhooks/, inbound dispatch context added for multi-inbox routing. See CHANGELOG.md for the full breakdown.
🚀 What is Wappa?
Wappa is a modern Python framework that transforms WhatsApp Business API into a powerful platform for building:
- 🤖 Smart Chatbots - AI-powered conversational experiences
- 📋 Workflows - Multi-step business processes
- 🎯 Agents - Intelligent customer service automation
- 💬 Chat Applications - Full-featured messaging platforms
Built for developers who want clean code, not webhook complexity.
✨ Key Features
🎯 Simple & Clean
from wappa import Wappa, WappaEventHandler
class MyBot(WappaEventHandler):
async def process_message(self, webhook):
await self.messenger.send_text("Hello!", webhook.user.user_id)
app = Wappa()
app.set_event_handler(MyBot())
app.run()
🏗️ Production-Ready Architecture
- Clean Architecture - Domain-driven design with dependency injection
- Type-Safe - Full Pydantic models for all WhatsApp data structures
- Multi-Inbox - Built for scaling across multiple business numbers
- Plugin System - Extensible with Redis, CORS, rate limiting, and custom plugins
📱 Complete WhatsApp Support
- All Message Types - Text, media, interactive buttons, lists, templates
- Rich Interactions - Buttons, lists, call-to-action messages
- Media Handling - Images, videos, audio, documents with automatic upload/download
- Templates - Pre-approved business message templates
🆔 Recipient Contract and BSUID Support
- Stable Internal Contract - Wappa keeps the framework-facing parameter as
recipientacrossself.messenger.send_*, API routes, and request models - Transport Resolution - In the WhatsApp adapter,
recipientis resolved to:towhen the identifier is a phone numberrecipientwhen the identifier is a BSUID
- BSUID-Aware Outbound - Text, media, interactive, template, and specialized messages use the same internal recipient resolution
- No Framework Fallback - If a message type cannot be sent via BSUID, Wappa does not automatically downgrade to phone-number transport
Important BSUID Risk
Wappa currently treats BSUID support as a transport concern, not as a delivery fallback workflow.
This means:
- your application can keep calling
send_*withrecipient=...exactly as before - Wappa will choose the correct WhatsApp request field internally
- but if Meta rejects a BSUID for a specific message type, Wappa will return an explicit error instead of retrying with a phone number
This is intentional for now. The fallback policy depends on each Wappa implementation because only the application knows:
- whether a phone number is available
- whether falling back is legally or product-wise acceptable
- whether that specific message should be retried with a different recipient identity
If your bot needs automatic fallback, implement it in your application layer around self.messenger, your user identity store, or your delivery orchestration logic.
🛠️ Developer Experience
# Initialize new project
wappa init my-bot
# Start development server with auto-reload
wappa dev app/main.py
# Browse interactive examples
wappa examples
💾 Flexible State Management
# Memory, JSON file, or Redis caching
app = Wappa(cache="redis") # or "memory" or "json"
# Automatic state persistence
await self.state_cache.set("conversation", {"step": "greeting"})
Inbox-scoped Template transport
Embedding applications send Templates through Wappa's public runtime capability; they do not construct WhatsApp clients, handlers, sessions, or pipelines:
from wappa.messaging import (
OutboundRuntime,
PhoneNumberTemplateRecipient,
TextTemplateTransportRequest,
)
transport = OutboundRuntime.from_app(fastapi_app).templates(inbox_id)
result = await transport.send(
TextTemplateTransportRequest(
recipient=PhoneNumberTemplateRecipient(value="573001112233"),
template_name="welcome",
category="utility",
)
)
result.outcome is accepted, rejected, transport_unavailable, or
indeterminate. Acceptance proves a platform Message ID, not delivery or a Host
Application commit. Wappa's standalone Template HTTP routes are opt-in with
Wappa(include_template_transport_api=True).
An embedding application that owns its own authenticated boundary drops Wappa's unauthenticated mutation surface with one argument:
app = Wappa(cache="redis", route_profile="embedded")
That omits every route which sends a message, deletes a media asset, or
rewrites a recipient's cached state. Media upload/download/lookup, limits,
validation, Template info, webhooks, health, and every wappa.messaging
service stay exactly as they are. Standalone applications need no change.
🏭 Factory Pattern for Cross-Platform Messages (v0.3.0)
Text/read-status payloads and media payloads have separate owners:
WhatsAppMessageFactory and WhatsAppMediaFactory. WhatsAppMessenger
consumes both through dependency injection, keeping pure payload construction
separate from I/O without duplicating media construction rules.
# Defaults keep the library ergonomic:
messenger = WhatsAppMessenger(
client=client,
media_handler=media_handler,
interactive_handler=interactive_handler,
template_handler=template_handler,
specialized_handler=specialized_handler,
inbox_id=inbox_id,
)
# Or inject custom factories for advanced use cases (testing, multi-inbox extensions):
messenger = WhatsAppMessenger(
client=client,
# ... handlers ...
inbox_id=inbox_id,
message_factory=MyCustomMessageFactory(),
media_factory=MyCustomMediaFactory(),
)
Why only text/media have factories? Interactive messages, templates, and specialized types (contact, location) are platform-specific — Telegram has inline keyboards instead of WhatsApp buttons/lists, templates are WA-only, and Instagram has quick replies but no lists. Factories are reserved for concepts that truly cross platforms. Platform-specific types are owned by their corresponding handlers.
📦 Installation
Using uv (Recommended)
# Create new project
uv init my-wappa-project
cd my-wappa-project
# Add Wappa
uv add wappa
# Initialize project structure
wappa init .
Using pip
pip install wappa
# Initialize new project
wappa init my-wappa-project
cd my-wappa-project
Using Poetry
poetry new my-wappa-project
cd my-wappa-project
poetry add wappa
# Initialize project structure
wappa init .
🏃♂️ Quick Start
1. Get WhatsApp Business API Credentials
- Visit Meta for Developers
- Create a WhatsApp Business App
- Get your credentials:
- Access Token
- Phone Number ID
- Business Account ID
2. Create Your Bot
# Initialize project
wappa init my-bot
cd my-bot
# Configure environment
cp .env.example .env
# Edit .env with your WhatsApp credentials
3. Run Development Server
# Start with auto-reload
wappa dev app/main.py
# Or manually
uv run python -m app.main
4. Test Your Bot
Send a message to your WhatsApp Business number and watch it echo back!
🎛️ Architecture Overview
graph TD
A[👤 WhatsApp User] -->|Message| B[📡 Webhook Endpoint]
B --> C[🔄 Event Dispatcher]
C --> D[⚡ Your Event Handler]
D --> E[💬 Messenger Interface]
E --> F[📱 WhatsApp API]
D --> G[💾 State Management]
D --> H[🧠 Business Logic]
G --> I[🗄️ Redis/Memory/JSON Cache]
H --> J[🔗 External Services]
style D fill:#333481,color:#fff,stroke:#333481,stroke-width:3px
style E fill:#4A90E2,color:#fff,stroke:#4A90E2,stroke-width:3px
style G fill:#333481,color:#fff,stroke:#333481,stroke-width:3px
style A fill:#25D366,color:#fff,stroke:#25D366,stroke-width:3px
style F fill:#25D366,color:#fff,stroke:#25D366,stroke-width:3px
- Event-Driven: Webhook → Event Handler → Response
- Type-Safe: Full Pydantic models for all WhatsApp data structures
- FastAPI Core: Built on modern async Python with automatic OpenAPI docs
- Production Ready: Docker support, Redis caching, structured logging
📚 Documentation
Quick Links
- 🚀 Quick Start - Get running in 5 minutes
- 🏗️ Architecture Guide - Understanding the framework
- 📡 API Reference - Complete messaging API
- 💾 State Management - Caching and persistence
- 🚀 Deploy to Railway - Production deployment
- 🛠️ WhatsApp Setup - Configure WhatsApp Business API
Example Projects
Explore 6 complete example applications:
# Browse examples interactively
wappa examples
# Copy specific example
wappa examples redis-cache-demo
- Simple Echo - Basic message echoing
- JSON Cache Demo - File-based state persistence
- Redis Cache Demo - High-performance caching
- OpenAI Transcription - Voice message processing
- Full-Featured Bot - Complete production example
- Basic Project - Minimal setup template
🛠️ Advanced Usage
Builder Pattern for Complex Apps
from wappa import WappaBuilder
app = await (WappaBuilder()
.with_whatsapp(
token="your_token",
phone_id="your_phone_id",
business_id="your_business_id"
)
.with_redis_cache("redis://localhost:6379")
.with_cors_enabled()
.with_rate_limiting(requests_per_minute=100)
.build())
app.set_event_handler(MyAdvancedHandler())
app.run()
Plugin System
from wappa.plugins import DatabasePlugin, CorsPlugin
app = Wappa(cache="redis")
app.add_plugin(DatabasePlugin("postgresql://..."))
app.add_plugin(CorsPlugin(allow_origins=["*"]))
app.set_event_handler(MyHandler())
app.run()
CLI Commands
# Project management
wappa init [directory] # Initialize new project
wappa examples [target] # Browse/copy examples
# Development
wappa dev app/main.py # Development server with auto-reload
wappa prod app/main.py # Production server
# Help
wappa --help # Show all commands
🚀 Deployment
Railway (Recommended)
# Install Railway CLI
npm install -g @railway/cli
# Login and deploy
railway login
railway init
railway add redis
railway up
# Set environment variables
railway variables set WP_ACCESS_TOKEN=your_token
railway variables set WP_PHONE_ID=your_phone_id
railway variables set WP_BID=your_business_id
See complete Railway deployment guide.
Docker
FROM python:3.12-slim
WORKDIR /app
COPY . .
RUN pip install uv
RUN uv sync --frozen
EXPOSE 8000
CMD ["uv", "run", "python", "-m", "app.main"]
🧪 Development
Setup Development Environment
# Clone repository
git clone https://github.com/sashanclrp/wappa.git
cd wappa
# Install dependencies
uv sync --group dev
# Run tests
uv run pytest
# Code formatting
uv run ruff check .
uv run ruff format .
Project Structure
wappa/
├── wappa/ # Core framework
│ ├── core/ # Application core & plugins
│ ├── messaging/ # WhatsApp messaging implementation
│ ├── persistence/ # Cache backends (Memory/JSON/Redis)
│ ├── cli/ # CLI tools & project templates
│ └── api/ # FastAPI routes & dependencies
├── examples/ # Example applications
├── docs/ # Documentation source
└── tests/ # Test suite
🤝 Community & Support
💬 Join the Community
- 💭 Discord Community - Get help, share projects, and connect with other developers
- 🐛 GitHub Issues - Bug reports and feature requests
- 📖 GitHub Discussions - Questions and community discussions
📞 Get Support
- 📚 Documentation - Comprehensive guides and API reference
- 💡 Examples - 6 complete working examples
- 🔧 Configuration Guide - WhatsApp Business API setup
🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
- 🐛 Found a bug? Open an issue
- 💡 Have an idea? Start a discussion
- 🔧 Want to contribute? Check out good first issues
📋 Requirements
- Python 3.12+ - Modern Python with latest type hints
- WhatsApp Business API - Meta for Developers account
- Redis (optional) - For production caching and state management
📄 License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
🙏 Acknowledgments
- Meta - For the WhatsApp Business API
- FastAPI - For the excellent async Python framework
- Redis - For high-performance caching
- Open Source Community - For inspiration and contributions
Built with ❤️ by Mimeia • Open Source • Apache 2.0 License
Transform your business communication with WhatsApp automation.
Metadata
Release files for wappa 0.26.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| wappa-0.26.2.tar.gz | 8.4 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| wappa-0.26.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.8 MB
Release files / wappa-0.26.2.tar.gz
| Download URL | wappa-0.26.2.tar.gz |
|---|---|
| Size | 8.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
080464597d4e94315ab4835644223999a25657e6f0f361a4274cd2ce74aaf8dc
|
|
BLAKE2b-256 checksum How to use checksums |
fd4c84b66fdbaef77b17cc2e7d762161575f988490b0fad2028a4b761c26a089
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / wappa-0.26.2-py3-none-any.whl
| Download URL | wappa-0.26.2-py3-none-any.whl |
|---|---|
| Size | 8.3 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7cd0c70993388da5c7b9d35f1911a47073c24f50993d5e4aa9105065df9ff08e
|
|
BLAKE2b-256 checksum How to use checksums |
138eaa11cb4999125349fb4d0c5cecfd57af4859bc6857430fa1bf8846ec5c5a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|