Skip to main content

PyWa Logo

PyWa

The Python framework for building WhatsApp bots.
Fast. Typed. Production-ready. From prototype to production in minutes.

PyPI Version Downloads Python Versions Tests Docs License Code Quality Updates


PyWa is a comprehensive, fully-typed Python framework for the WhatsApp Cloud API. It handles everything — sending messages, receiving webhooks, building interactive flows, managing templates, handling calls — so you can focus on building your bot, not wrestling with the API.

pip install -U "pywa[server]"

✨ Why PyWa?

💬 Rich Messaging Text, images, videos, documents, audio, stickers, locations, contacts, buttons, lists & more
📩 Real-Time Webhooks Messages, button clicks, delivery receipts, read receipts, reactions & account updates
🔔 Listeners Chain conversations naturally — wait for replies, clicks, or reactions inline
📄 Templates Create, send, and manage WhatsApp message templates with full parameter support
♻️ Flows Build rich, multi-screen interactive WhatsApp Flows in pure Python
📞 Calls Handle incoming and outgoing WhatsApp call events
Async Support Full async/await API via pywa_async — same interface, zero friction
🔌 Server Integrations Built-in webhook server, or plug into your existing FastAPI / Flask app
🛡️ Type Safety Fully typed - full autocomplete and static analysis everywhere
🔬 Smart Filters Composable filters with logical operators for precise update routing
🧰 CLI Tools pywa dev for local development, pywa run for production

🚀 Quick Start

1. Echo Bot — 5 lines of code

# main.py
from pywa import WhatsApp, filters, types

wa = WhatsApp(
    phone_id="1234567890",
    token="EAA...",
    app_id=1234567890,
    app_secret="********",
    callback_url="https://your-domain.ngrok-free.app",
    verify_token="my-verify-token",
)


@wa.on_message(filters.text)
def echo(_: WhatsApp, msg: types.Message):
    msg.reply(f"You said: {msg.text}")

Start the webhook server:

pywa dev    # Local development
pywa run    # Production

2. Rich Messages — Buttons, Media & More

from pywa import WhatsApp, types

wa = WhatsApp(phone_id="1234567890", token="EAA...")

# Text with interactive buttons
wa.send_message(
    to="9876543210",
    text="How can I help you today?",
    buttons=[
        types.Button(title="📋 Menu", callback_data="menu"),
        types.Button(title="💬 Support", callback_data="help"),
    ],
)

# Images, documents, audio — one-liners
wa.send_image(to="9876543210", image="https://example.com/photo.jpg", caption="Check this out!")
wa.send_document(to="9876543210", document="report.pdf")

3. Conversational Flows — Listeners

Handlers define entry points. Listeners let you continue the conversation naturally:

@wa.on_message(filters.command("start"))
def start(_: WhatsApp, msg: types.Message):
    name = msg.reply("What's your name?").wait_for_reply(filters=filters.text).text
    msg.reply(f"Nice to meet you, {name}!")

4. Plug Into Your Own Server

from fastapi import FastAPI
from pywa import WhatsApp, filters, types

app = FastAPI()
wa = WhatsApp(..., server=app, webhook_endpoint="/webhook")


@wa.on_message(filters.text)
def echo(_: WhatsApp, msg: types.Message):
    msg.reply(msg.text)


@app.get("/")
def health():
    return {"status": "ok"}

5. Full Async Support

Same API. Just swap the import and add await:

from pywa_async import WhatsApp, filters, types

wa = WhatsApp(...)


@wa.on_message(filters.text)
async def hello(_: WhatsApp, msg: types.Message):
    await msg.react("👋")
    await msg.reply("Hello from async PyWa!")

6. Templates

Create and send WhatsApp message templates with full parameter support:

from pywa import WhatsApp
from pywa.types.templates import *

wa = WhatsApp(..., waba_id=123456)

wa.create_template(
    template=Template(
        name="order_update",
        category=TemplateCategory.MARKETING,
        language=TemplateLanguage.ENGLISH_US,
        parameter_format=ParamFormat.NAMED,
        components=[
            ht := HeaderText("Your order #{{order_id}} has shipped!", order_id="12345"),
            bt := BodyText("Track it with code {{code}}.", code="ABC123"),
            FooterText(text="Powered by PyWa"),
            Buttons(buttons=[
                url := URLButton(text="Track Order", url="https://example.com/track/{{1}}", example="12345"),
                QuickReplyButton(text="Unsubscribe"),
            ]),
        ],
    ),
)

# Send it
wa.send_template(
    to="9876543210",
    name="order_update",
    language=TemplateLanguage.ENGLISH_US,
    params=[
        ht.params(order_id="67890"),
        bt.params(code="XYZ789"),
        url.params(url_variable="67890", index=0),
    ],
)

7. Interactive Flows

Build WhatsApp Flows — multi-screen interactive experiences — entirely in Python:

from pywa import WhatsApp, types
from pywa.types.flows import *

wa = WhatsApp(..., waba_id=123456)

my_flow = FlowJSON(
    screens=[
        Screen(
            id="SIGNUP",
            title="Join Our Newsletter",
            layout=Layout(children=[
                TextHeading(text="Subscribe for updates"),
                name := TextInput(name="name", label="Name", input_type=InputType.TEXT),
                email := TextInput(name="email", label="Email", input_type=InputType.EMAIL, required=True),
                Footer(
                    label="Subscribe",
                    on_click_action=CompleteAction(
                        payload={"name": name.ref, "email": email.ref}
                    ),
                ),
            ]),
        )
    ]
)

wa.create_flow(name="newsletter_signup", categories=[FlowCategory.SIGN_UP], flow_json=my_flow, publish=True)


@wa.on_flow_completion
def on_signup(_: WhatsApp, flow: types.FlowCompletion):
    flow.reply(text=f"Welcome, {flow.response['name']}! You're subscribed at {flow.response['email']}.")

8. Account & Resource Management

Beyond messaging, PyWa gives you full control over your WhatsApp Business resources:

from pywa import WhatsApp

wa = WhatsApp(phone_id="1234567890", token="EAA...", waba_id=123456)

# Business profile
profile = wa.get_business_profile()
wa.update_business_profile(about="Powered by PyWa", description="We build bots!", profile_picture="profile.jpg")

# Media management
media = wa.upload_media(media="photo.jpg")
media.stream(), media.download(), media.reupload(), media.delete()

# QR codes
qr = wa.create_qr_code(prefilled_message="Hi! I saw your QR code")
qr.qr_image_url, qr.code, qr.update(prefilled_message="Hello"), qr.delete()

# Usernames
wa.get_reserved_usernames()
wa.set_username(username="mybusiness")
wa.get_current_username()

# Groups
wa.create_group(subject="VIP Customers")
wa.get_groups()
wa.get_group_join_requests()

# Commerce
wa.get_commerce_settings()
wa.update_commerce_settings(is_catalog_visible=True, is_cart_enabled=
True)
# User management
wa.block_users(users=["9876543210"])
blocked = wa.get_blocked_users()

See the Client guide for the full resource management API — templates, flows, media, QR codes, commerce, groups, calls, and more.

9. Partners & Tech Providers

Building a platform on top of WhatsApp? PyWa supports multi-WABA management, phone number provisioning, and callback routing for Solution Partners and Tech Providers:

from pywa import WhatsApp, types, filters

wa = WhatsApp(phone_id="1234567890", token="EAA...", waba_id=123456)


@wa.on_message(filters.sent_to(phone_number_id=...))
def handle_message_for_specific_phone_number(wa: WhatsApp, msg: types.Message): ...


@wa.on_account_update(filters.account_restriction)
def handle_account_restriction(wa: WhatsApp, update: types.AccountUpdate): ...


@wa.on_message(filters.account_deleted)
def handle_account_deletion(wa: WhatsApp, update: types.AccountUpdate): ...


# Get all WABAs you manage
shared_wabas = wa.get_shared_business_accounts()
owned_wabas = wa.get_owned_business_accounts()

# Provision phone numbers on a WABA
phone = wa.create_phone_number(country_calling_code="1", phone_number="5551234567", verified_name="John Doe")
wa.request_verification_code(phone_id=phone.id, code_method="SMS")
wa.verify_phone_number(code="123456", phone_id=phone.id)
wa.register_phone_number(phone_id=phone.id)

# Route webhooks per-WABA or per-phone
wa.override_waba_callback_url(callback_url="https://your-platform.com/waba/123")
wa.override_phone_callback_url(callback_url="https://your-platform.com/phone/456")

# Migrate templates & flows between WABAs
wa.migrate_templates(source_waba_id=111111, destination_waba_id=222222)
wa.migrate_flows(source_waba_id=111111, destination_waba_id=222222, source_flow_names=["flow_1"])

📦 Installation

# Core (sending messages, no webhook server)
pip install -U pywa

# With built-in webhook server (recommended)
pip install -U "pywa[server]"

# For Flow encryption support
pip install -U "pywa[cryptography]"

# Everything
pip install -U "pywa[server,cryptography]"

Requirements: Python 3.10+


📚 Documentation

Full documentation is available at pywa.readthedocs.io.

Topic Description
Getting Started Setup, first bot, and key concepts
Client Sending messages, media, and managing resources
Handlers Decorators, filters, and webhook routing
Listeners Conversational flows and inline waiting
Updates Message, callback, status, and system updates
Filters Composable, reusable update filtering
Templates Create, send, and manage message templates
Flows Build interactive multi-screen flows
Calls Handle voice call events

🤝 Contributing

Contributions are welcome! Check out the Contributing Guide to get started.

💬 Community

Questions? Ideas? Join the conversation:

⚖️ License

PyWa is open-source software licensed under the MIT License.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pywa-4.3.1.tar.gz (373.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pywa-4.3.1-py3-none-any.whl (363.1 kB view details)

Uploaded Python 3

File details

Details for the file pywa-4.3.1.tar.gz.

File metadata

  • Download URL: pywa-4.3.1.tar.gz
  • Upload date:
  • Size: 373.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pywa-4.3.1.tar.gz
Algorithm Hash digest
SHA256 eee3b95102bbbd1c25d81ba926fca11f5333d880f540200eac8c52303ae59c66
MD5 b2d6cf41815a853d1b92ccbf57f5470b
BLAKE2b-256 019eab8d95b9cdfe9a368c72d103f825a5cdb16a6fce6e614aeccc366c9675e7

See more details on using hashes here.

Provenance

The following attestation bundles were made for pywa-4.3.1.tar.gz:

Publisher: publish.yml on david-lev/pywa

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pywa-4.3.1-py3-none-any.whl.

File metadata

  • Download URL: pywa-4.3.1-py3-none-any.whl
  • Upload date:
  • Size: 363.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pywa-4.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6424f1bf5bd498e77523825081a9270c8f882f26a3847543ebce467c95d3b2bf
MD5 31e2bbaf28c077e283f9eefffe4f1da8
BLAKE2b-256 7d5255535aa5b1da5e9413e6d56d3e672fb67a0b3d34b3169d9b15b97d7ffa8b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pywa-4.3.1-py3-none-any.whl:

Publisher: publish.yml on david-lev/pywa

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

4.4.0

2 files

This release

4.3.1 This release

2 files

4.3.0

2 files

4.2.1

2 files

4.2.0

2 files

4.1.0

2 files

4.0.0

2 files

3.9.0

2 files

3.8.0

2 files

3.7.0

2 files

3.6.1

2 files

3.6.0

2 files

3.5.2

2 files

3.5.1

2 files

3.5.0

2 files

3.4.0

2 files

3.3.0

2 files

3.2.0

2 files

3.1.1

2 files

3.1.0

2 files

3.0.0

2 files

2.11.0

2 files

2.10.0

2 files

2.9.0

2 files

2.8.0

2 files

2.7.0

2 files

2.6.0

2 files

2.5.2

2 files

2.5.1

2 files

2.5.0

2 files

2.4.0

2 files

2.3.0

2 files

2.2.0

2 files

2.1.0

2 files

2.0.5

2 files

2.0.4

2 files

2.0.3

2 files

2.0.2

2 files

2.0.1

2 files

2.0.0

2 files

1.26.0

2 files

1.25.0

2 files

1.24.0

2 files

1.23.0

2 files

1.22.0

2 files

1.21.0

2 files

1.20.2

2 files

1.20.1

2 files

1.20.0

2 files

1.18.1

2 files

1.18.0

2 files

1.17.0

2 files

1.16.2

2 files

1.16.0

2 files

1.15.0

2 files

1.14.0

2 files

1.13.0

2 files

1.12.1

2 files

1.12.0

2 files

1.11.1

2 files

1.11.0

2 files

1.10.0

2 files

1.9.0

2 files

1.8.0

2 files

1.7.3

2 files

1.7.2

2 files

1.7.1

2 files

1.7.0

2 files

1.6.0

2 files

1.5.4

2 files

1.5.3

2 files

1.5.2

2 files

1.5.1

2 files

1.5.0

2 files

1.4.1

2 files

1.4.0

2 files

1.3.0

2 files

1.2.0

1 file

1.1.0

1 file

1.0.2

1 file

1.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page