pywa - Python WhatsApp Bot Framework

raw JSON →
3.9.0 verified Fri May 01 auth: no python

Pywa (Python WhatsApp API) is a powerful, fast, and easy-to-use framework for building WhatsApp bots in Python. It wraps the WhatsApp Business API (Cloud API) and provides a clean, event-driven interface for handling messages, callbacks, and sending rich media. Version 3.9.0 requires Python >=3.10. The library follows a monthly release cadence.

pip install pywa
error AttributeError: 'WhatsApp' object has no attribute 'on_message'
cause Using an outdated version where the decorator syntax was different or not yet supported. Also, forgetting to import the decorator from pywa.
fix
Update pywa to >=3.0.0 and use from pywa import WhatsApp and decorate with @wa.on_message().
error TypeError: __init__() got multiple values for argument 'phone_id'
cause Passing arguments positionally in wrong order; `verify_token` is now the first positional argument (if using positional style) or better use keyword arguments.
fix
Use keyword arguments: WhatsApp(phone_id='...', token='...', server='...', verify_token='...')
error requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: / (Caused by NewConnectionError)
cause The server argument expects the full URL to the webhook endpoint. If you omit the trailing slash or don't start with http://, it may fail.
fix
Set server='http://localhost:8080' (include http:// and no trailing slash) or use a valid URL.
error ValueError: The 'verify_token' must be a non-empty string
cause Passing an empty string or None as verify_token; it must be provided and non-empty.
fix
Provide a non-empty string as verify_token parameter.
breaking In pywa 3.x, the constructor changed: `verify_token` is now positional (first argument) and `server` parameter changed to accept a string URL instead of a tuple. Old code passing arguments positionally may break.
fix Use keyword arguments: WhatsApp(phone_id=..., token=..., server=..., verify_token=...)
deprecated The `on_callback_button` handler is deprecated since 3.4.0; use `on_callback_query` instead.
fix Replace `@wa.on_callback_button()` with `@wa.on_callback_query()`
gotcha Webhook signature verification is not mandatory by default. If you don't set a `verify_token`, you risk processing unverified requests. Always set a secure `verify_token` in production.
fix Pass a `verify_token` in the constructor and verify on your server platform (e.g., using the 'cryptography' library if you enable signature checking).
breaking In pywa 3.0, the `send_message` method no longer returns the raw API response as `requests.Response` but returns a `MessageStatus` object. Accessing `.json()` on the return value will fail.
fix Use the `id` attribute of the returned `MessageStatus` object instead of parsing the response.

Initialize the WhatsApp client, define a message handler, and start the webhook server.

import os
from pywa import WhatsApp

wa = WhatsApp(
    phone_id=os.environ['PHONE_ID'],
    token=os.environ['TOKEN'],
    server='http://localhost:8080',
    verify_token='my_verify_token'
)

@wa.on_message()
def handle_message(client: WhatsApp, message):
    client.send_message(to=message.from_user, text=f'You said: {message.text}')

wa.run()