Skip to content

4.0.0

Choose a tag to compare

@david-lev david-lev released this 08 Jun 21:42
· 108 commits to master since this release
058ec8f

Pywa v4.0.0 is here!

Update with pip: pip3 install -U pywa

This is a massive update to Pywa, introducing BSUID, full group management, a built-in webhook server, Coexistence support, and more.

Important

Migration to v4 introduces breaking changes. Please review carefully before upgrading.

✨ Highlights

  • User Identity & BSUID: Full support for Business-Scoped User IDs (BSUIDs), parent BSUIDs, usernames, and country_code. User.wa_id is now optional.
  • Groups: Full group management support (create, update, delete, manage invite links/join requests). Added msg.chat to distinguish private chats from groups.
  • Webhooks & CLI: New built-in server workflow (pywa dev, pywa run, WhatsApp.run()) and start_ngrok_tunnel for easy local development and testing.
  • Messages & Media: Added EditedMessage, DeletedMessage, and Outgoing equivalents for Coexistence support. Added send_carousel and reply_carousel. Media objects now store their caption.
  • Business Management: Retrieve shared/owned WABAs, create/verify phone numbers on WABAs, and manage usernames (set_username, delete_username, etc.).
  • Templates: Better validation, easier component lookup, stricter URL variable checks, and Template.duplicate(...) now supports target_waba_id.

πŸ”₯ Breaking changes

  • User Identity: User.wa_id may be None if a user enables a username. Store User.bsuid instead.
  • ChatOpened: Removed completely (types.ChatOpened, handlers, and filters) β†’ Use message, callback, or listener entry points.
  • Listeners: Direct wa.listen(to="...") calls removed β†’ Use explicit listener identifiers instead.
  • System Messages: Message.system removed β†’ System events are now handled via PhoneNumberChange and IdentityChange.
  • Media: Message.download_media(in_memory=True) removed β†’ Use msg.get_media_bytes() or msg.stream_media().
  • Sent Updates: Destination is now exposed as sent.chat (with .id and .type) instead of a plain string in sent.to_user.

See full details and migration steps in the migration guide.

πŸ“š Resources

πŸ’‘ Examples

  • User Identity Storage (BSUID Readiness)

Old code often used wa_id as the only stable user key. In 4.x, store bsuid and treat wa_id as optional.

from pywa import WhatsApp, types

wa = WhatsApp(...)

def save_user_to_db(user: types.User):
    db.save_user(
        bsuid=user.bsuid,
        wa_id=user.wa_id,
        username=user.username,
        parent_bsuid=user.parent_bsuid,
        country_code=user.country_code,
        name=user.name,
    )

@wa.on_message
def on_message(_: WhatsApp, msg: types.Message):
    save_user_to_db(msg.from_user)
    msg.reply(f"Hello {msg.from_user.name}!")
  • Run Webhooks with the New Built-in Server & Ngrok

You no longer need to strictly set up FastAPI or Flask just to host webhooks locally.

from pywa import WhatsApp, filters, types, utils

# Automatically setup an Ngrok tunnel for local testing
callback_url = utils.start_ngrok_tunnel(
    auth_token="NGROK_AUTH_TOKEN",
    domain="your-domain.ngrok-free.app",
)

wa = WhatsApp(
    phone_id="1234567890",
    token="EAA...",
    app_id="1234567890",
    app_secret="********",
    callback_url=callback_url,
    verify_token="my-verify-token",
)

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

Run the application via the new CLI commands:

pywa dev
# or for production-style serving:
pywa run

Full Changelog: 3.9.0...4.0.0