### Install whatsapp-python Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Install the stable release using pip or the development version from source. ```bash pip install whatsapp-python ``` ```bash git clone https://github.com/filipporomani/whatsapp.git cd whatsapp pip install . ``` -------------------------------- ### Install from Source Source: https://github.com/filipporomani/whatsapp-python/wiki/Installation-&-Setup Clone the repository and install the package using pip. This version is not stable and may contain bugs. ```bash git clone https://github.com/filipporomani/whatsapp cd whatsapp pip install . ``` -------------------------------- ### Install whatsapp-python from GitHub Source: https://github.com/filipporomani/whatsapp-python/blob/main/README.md Install the development version directly from the GitHub repository for the latest features and bug fixes. This involves cloning the repository and installing it locally. ```bash git clone https://github.com/filipporomani/whatsapp.git cd whatsapp pip install . ``` -------------------------------- ### Install whatsapp-python using pip Source: https://github.com/filipporomani/whatsapp-python/blob/main/README.md Install the latest release version of the library using pip. ```bash pip install whatsapp-python ``` -------------------------------- ### Install from Pip (Stable) Source: https://github.com/filipporomani/whatsapp-python/wiki/Installation-&-Setup Install or upgrade to the latest stable version of the whatsapp-python library using pip. ```bash # For Windows pip install --upgrade whatsapp-python #For Linux | MAC pip3 install --upgrade whatsapp-python ``` -------------------------------- ### Webhook Event Handling Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Register handlers for incoming messages, webhook events, and verification challenges, then start the server. ```APIDOC ## Webhook Event Handling — `on_message()`, `on_event()`, `on_verification()`, `run()` ### Description Register async handlers for incoming messages, general webhook events, and webhook verification challenges, then start the embedded FastAPI/Uvicorn server. ### Methods - **`@messenger.on_message`**: Decorator to register a handler for incoming messages. - **`@messenger.on_verification`**: Decorator to register a handler for webhook verification challenges. - **`@messenger.on_event`**: Decorator to register a handler for any webhook event. - **`run(host, port)`**: Starts the embedded web server. ### Request Example ```python from whatsapp import WhatsApp, Message messenger = WhatsApp( token="EAAxxxYYY", phone_number_id={"default": "123456789012345"}, verify_token="my-webhook-secret", ) @messenger.on_message async def handle_message(msg: Message): print(f"From: {msg.to} | Name: {msg.name} | Type: {msg.type}") if msg.type == "text": await msg.reply(f"You said: {msg.content}") await msg.mark_as_read() elif msg.type == "image": image_url = messenger.query_media_url(msg.image["id"]) local_file = messenger.download_media(image_url, msg.image["mime_type"], "/tmp/received_image") print(f"Saved image to {local_file}") elif msg.type == "interactive": choice_id = msg.interactive["list_reply"]["id"] choice_title = msg.interactive["list_reply"]["title"] await msg.reply(f"You selected: {choice_title} (id={choice_id})") @messenger.on_verification async def handle_verification(challenge): if challenge: print(f"Webhook verified, challenge={challenge}") else: print("Webhook verification failed!") @messenger.on_event async def handle_any(event): print(f"Raw event received: {event}") # Start the server (blocks) messenger.run(host="0.0.0.0", port=8000) ``` ``` -------------------------------- ### Atomic Commit Message Example Source: https://github.com/filipporomani/whatsapp-python/blob/main/CONTRIBUTING.md Use this format for larger changes to ensure clarity in your commit history. The first line is a brief summary, followed by a blank line and a more detailed explanation. ```bash $ git commit -m "feat: a brief summary of the commit A paragraph describing what changed and its impact." ``` -------------------------------- ### Initialize WhatsApp and AsyncWhatsApp Clients Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Instantiate the synchronous (WhatsApp) or asynchronous (AsyncWhatsApp) client with API token and phone number IDs. The constructor handles Graph API version detection, update checks, and webhook setup. Use 'latest' for auto-detection or specify a version string. ```python import logging from whatsapp import WhatsApp, AsyncWhatsApp logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", ) # Sync client — single phone number messenger = WhatsApp( token="EAAxxxYYY", phone_number_id={"default": "123456789012345"}, logger=True, update_check=True, verify_token="my-webhook-secret", debug=False, version="latest", # auto-detects latest Graph API version ) # Async client — multiple phone numbers async_messenger = AsyncWhatsApp( token="EAAxxxYYY", phone_number_id={"main": "123456789012345", "support": "987654321098765"}, logger=True, update_check=False, verify_token="my-webhook-secret", version="v19.0", # pin to a specific Graph API version ) # Check that credentials are valid print(messenger.authorized) # True / False ``` -------------------------------- ### Standalone Flask Webhook for WhatsApp Integration Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Integrate WhatsApp messaging into an existing Flask application. This example shows how to verify tokens, handle incoming text and image messages, and send replies. ```python import os, logging from flask import Flask, request, Response from whatsapp import WhatsApp, Message from dotenv import load_dotenv load_dotenv() app = Flask(__name__) messenger = WhatsApp(os.getenv("TOKEN"), phone_number_id={"default": os.getenv("PHONE_ID")}) VERIFY_TOKEN = os.getenv("VERIFY_TOKEN", "my-secret") logging.basicConfig(level=logging.INFO) @app.get("/") def verify(): if request.args.get("hub.verify_token") == VERIFY_TOKEN: return str(request.args.get("hub.challenge")) return "Invalid token", 403 @app.post("/") def hook(): data = request.get_json() if data and messenger.changed_field(data) == "messages" and messenger.is_message(data): msg = Message(instance=messenger, data=data) if msg.type == "text": Message(instance=messenger, to=msg.to, content=f"Echo: {msg.content}").send() elif msg.type == "image": url = messenger.query_media_url(msg.image["id"]) path = messenger.download_media(url, msg.image["mime_type"], "/tmp/img") logging.info("Saved image: %s", path) return "OK", 200 if __name__ == "__main__": app.run(port=5000, debug=False) ``` -------------------------------- ### Media Management: Upload, Query, Download, Delete Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Provides functions for managing media files on WhatsApp Cloud. Use `upload_media` to upload local files and get a media ID, `query_media_url` to resolve a media ID to a download URL, `download_media` to save media to disk, and `delete_media` to remove hosted media. ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) # 1. Upload a local file → get a reusable media ID upload_result = messenger.upload_media("/tmp/invoice.pdf") media_id = upload_result["id"] # "1234567890123456" # 2. Resolve a media ID to a temporary download URL media_url = messenger.query_media_url(media_id) # media_url: "https://lookaside.fbsbx.com/whatsapp_business/..." # 3. Download media received from a user # (media_url and mime_type come from get_image / get_audio / etc.) saved_path = messenger.download_media( media_url=media_url, mime_type="application/pdf", file_path="/tmp/downloads/invoice", # extension added automatically → invoice.pdf ) print(saved_path) # "/tmp/downloads/invoice.pdf" # 4. Delete a hosted media file result = messenger.delete_media(media_id) # result: {"deleted": true} ``` -------------------------------- ### Webhook Event Handling with FastAPI/Uvicorn Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Register asynchronous handlers for incoming messages, general webhook events, and webhook verification challenges. The `run()` method starts an embedded FastAPI/Uvicorn server. Ensure your `verify_token` is set correctly for verification. ```python from whatsapp import WhatsApp, Message messenger = WhatsApp( token="EAAxxxYYY", phone_number_id={"default": "123456789012345"}, verify_token="my-webhook-secret", ) @messenger.on_message async def handle_message(msg: Message): print(f"From: {msg.to} | Name: {msg.name} | Type: {msg.type}") if msg.type == "text": await msg.reply(f"You said: {msg.content}") await msg.mark_as_read() elif msg.type == "image": image_url = messenger.query_media_url(msg.image["id"]) local_file = messenger.download_media(image_url, msg.image["mime_type"], "/tmp/received_image") print(f"Saved image to {local_file}") elif msg.type == "interactive": choice_id = msg.interactive["list_reply"]["id"] choice_title = msg.interactive["list_reply"]["title"] await msg.reply(f"You selected: {choice_title} (id={choice_id})") @messenger.on_verification async def handle_verification(challenge): if challenge: print(f"Webhook verified, challenge={challenge}") else: print("Webhook verification failed!") @messenger.on_event async def handle_any(event): print(f"Raw event received: {event}") # Start the server (blocks) messenger.run(host="0.0.0.0", port=8000) ``` -------------------------------- ### Migrate from heyoo to whatsapp-python (<= 1.1.2) Source: https://github.com/filipporomani/whatsapp-python/blob/main/README.md For versions up to 1.1.2, migration involves uninstalling 'heyoo', installing 'whatsapp-python==1.1.2', and changing the import statement from 'heyoo' to 'whatsapp'. No code changes are required. ```python import whatsapp ``` -------------------------------- ### send_image() Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send an image by URL or media ID with an optional caption. First, upload the local file using `upload_media` to get a media ID, then use that ID to send the image. ```APIDOC ## send_image() ### Description Send an image by URL or media ID with an optional caption. ### Method ```python result = messenger.send_image( image=media_id, # or image="https://example.com/photo.jpg" recipient_id="15550001234", caption="Uploaded locally", link=False, # False = treat `image` as a media ID, not a URL ) ``` ### Parameters - **image** (string) - Required - The media ID or URL of the image. - **recipient_id** (string) - Required - The recipient's phone number. - **caption** (string) - Optional - A caption for the image. - **link** (boolean) - Optional - If True, `image` is treated as a URL. If False, `image` is treated as a media ID. Defaults to True. ``` -------------------------------- ### Send Text Messages with whatsapp-python Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Create a Message object and use its .send() method to send a text message. Specify the recipient and content. For multi-number setups, use the optional `sender` argument to select the originating phone number ID. ```python from whatsapp import WhatsApp, Message messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) # Create and send a simple text message msg = messenger.create_message(to="15550001234", content="Hello from whatsapp-python!") result = msg.send() # result: {"messages": [{"id": "wamid.xxx"}]} # Send from a specific number in a multi-number setup messenger2 = WhatsApp( "EAAxxxYYY", phone_number_id={"sales": "111111111111111", "support": "222222222222222"}, ) msg2 = messenger2.create_message(to="15550001234", content="Support team here!") result2 = msg2.send(sender="support") ``` -------------------------------- ### Set Up WhatsApp Event Listener Source: https://github.com/filipporomani/whatsapp-python/wiki/App-events Instantiate WhatsApp with your token and phone number ID, then define and register an asynchronous message handler. The app is then run on a specified host and port. ```python from whatsapp import WhatsApp app = WhatsApp(token, {"key": phone_number_id}, logger) # reference: Installation & setup @app.on_message async def on_message(message): print(message) app.run(host, port, **kwargs) ``` -------------------------------- ### Set up local environment with hatch Source: https://github.com/filipporomani/whatsapp-python/blob/main/README.md Use hatch to set up a local development environment after cloning the repository. This is useful for contributing or testing changes. ```bash git clone https://github.com/filipporomani/whatsapp.git cd whatsapp pip install hatch hatch shell ``` -------------------------------- ### Handle Incoming Messages and React Source: https://github.com/filipporomani/whatsapp-python/wiki/Reacting-to-messages This snippet shows how to initialize the WhatsApp client, set up a message handler to react to incoming messages with an emoji, and run the application. ```python app = WhatsApp(token, phone_number_id = {"key": "xxxxxxxxx"}) @app.on_message async def on_message(message): message.react("👍") app.run("0.0.0.0", 8080) ``` -------------------------------- ### Initialization - WhatsApp / AsyncWhatsApp Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Instantiate the client with your API token and phone number IDs. The constructor fetches the latest Graph API version and sets up the internal FastAPI webhook server. ```APIDOC ## Initialization - WhatsApp / AsyncWhatsApp Instantiate the client with your API token and a dictionary mapping logical names to phone number IDs. The constructor fetches the latest Graph API version, optionally checks PyPI for library updates, and sets up the internal FastAPI webhook server. ```python import logging from whatsapp import WhatsApp, AsyncWhatsApp logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", ) # Sync client — single phone number messenger = WhatsApp( token="EAAxxxYYY", phone_number_id={"default": "123456789012345"}, logger=True, update_check=True, verify_token="my-webhook-secret", debug=False, version="latest", # auto-detects latest Graph API version ) # Async client — multiple phone numbers async_messenger = AsyncWhatsApp( token="EAAxxxYYY", phone_number_id={"main": "123456789012345", "support": "987654321098765"}, logger=True, update_check=False, verify_token="my-webhook-secret", version="v19.0", # pin to a specific Graph API version ) # Check that credentials are valid print(messenger.authorized) # True / False ``` ``` -------------------------------- ### Initialize and Send Async Message Source: https://github.com/filipporomani/whatsapp-python/wiki/Async Demonstrates initializing `AsyncWhatsApp` and sending a message asynchronously. Note that `create_message` is not awaited as it doesn't call an API. The `.send()` method returns a future that can be awaited later. ```python from whatsapp import AsyncWhatsApp, AsyncMessage import asyncio messenger = AsyncWhatsApp('TOKEN', phone_number_id={"key": 'xxxxxxxxx', "key1": 'yyyyyyyyy'}, logger=True, update_check=True, debug=False, version="latest") msg = app.create_message(to="DESTINATION_PHONE_NUMBER", content="Hello world") # the create message function is not awaited as it doesn't call any API async def main(): # we send the message and the call is saved for later as .send() doesn't wait for the request to be finished. msg = await msg.send() # Arbitrary 5 second sleep time so we are sure the request is closed - a while cycle can also be used. await asyncio.sleep(5) # check if the message request is closed and print the result in the terminal if msg.done(): print(f"Result: {msg.result()}") asyncio.run(main()) ``` -------------------------------- ### Message() Constructor Source: https://github.com/filipporomani/whatsapp-python/wiki/Message() Object Initializes a Message object. It can be created directly or using the WhatsApp class's create_message method. ```APIDOC ## Message() You can also create a message object using the `WhatsApp` class. This method doesn't require to pass the `instance` parameter. ```python message = yourclient.create_message(args) ``` Create a new message object. ### Parameters - `instance` **WhatsApp object** - `id` **[str]** - `data` **[dict]** - `content` **[str]** - `to` **[str]** - `rec_type` **[str]** ``` -------------------------------- ### Initialize WhatsApp Object Source: https://github.com/filipporomani/whatsapp-python/wiki/Installation-&-Setup Instantiate the WhatsApp object with your authentication token and phone number ID. The phone_number_id must be a dictionary for versions > 3.4.0. Optional parameters include logger, update_check, debug, and version. ```python >>> from whatsapp import WhatsApp, Message >>> messenger = WhatsApp('TOKEN', phone_number_id={"key": 'xxxxxxxxx', "key1": 'yyyyyyyyy'}, logger=True, update_check=True, debug=False, version="latest") ``` -------------------------------- ### Send Audio by URL Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send an audio file using its URL. The `WhatsApp` object must be initialized with valid credentials. This method supports audio formats like MP3. ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) result = messenger.send_audio( audio="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3", recipient_id="15550001234", ) # result: {"messages": [{"id": "wamid.xxx"}]} ``` -------------------------------- ### Create Message Object using WhatsApp Class Source: https://github.com/filipporomani/whatsapp-python/wiki/Message() Object Instantiate a Message object via the `create_message` method of the WhatsApp class. This method does not require passing the `instance` parameter separately. ```python message = yourclient.create_message(args) # args are described below ``` -------------------------------- ### Async Usage with AsyncWhatsApp and AsyncMessage Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Demonstrates how to use AsyncWhatsApp and AsyncMessage for non-blocking API calls with asyncio. Sending and media methods return asyncio.Future objects. ```APIDOC ## Async Usage — `AsyncWhatsApp` / `AsyncMessage` Use `AsyncWhatsApp` and `AsyncMessage` for non-blocking API calls with `asyncio`. All sending and media methods return `asyncio.Future` objects. ```python import asyncio from whatsapp import AsyncWhatsApp, AsyncMessage messenger = AsyncWhatsApp( token="EAAxxxYYY", phone_number_id={"main": "123456789012345"}, verify_token="my-webhook-secret", debug=False, ) @messenger.on_message async def handle(msg: AsyncMessage): # All I/O methods must be awaited reply_future = await msg.reply("Got your message!") await asyncio.sleep(1) if reply_future.done(): print("Reply sent:", reply_future.result()) # Send a template asynchronously tpl_future = await messenger.send_template( template="hello_world", recipient_id=msg.to, lang="en_US", ) await asyncio.sleep(1) print("Template result:", tpl_future.result()) # Fire off an outbound message from outside a handler async def main(): outbound = messenger.create_message(to="15550001234", content="Async hello!") future = await outbound.send() await asyncio.sleep(3) print(future.result()) asyncio.run(main()) # Start the webhook server messenger.run(host="0.0.0.0", port=8000) ``` ``` -------------------------------- ### Message.send() Source: https://github.com/filipporomani/whatsapp-python/wiki/Message() Object Sends a message. Requires instance, to, and content parameters during Message() initialization. ```APIDOC ## Message.send() Send a message. Required Message() initialization parameters: - instance - to - content ``` -------------------------------- ### Send Document by URL Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send a document (e.g., PDF, DOCX) using its URL. An optional caption can be provided. The `WhatsApp` object requires initialization with an access token and phone number ID. ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) result = messenger.send_document( document="https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf", recipient_id="15550001234", caption="Your monthly invoice", ) ``` -------------------------------- ### send_audio() Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send an audio file by URL or media ID. ```APIDOC ## Sending Audio — `send_audio()` ### Description Send an audio file by URL or media ID. ### Method ```python result = messenger.send_audio( audio="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3", recipient_id="15550001234", ) ``` ### Parameters - **audio** (string) - Required - The media ID or URL of the audio file. - **recipient_id** (string) - Required - The recipient's phone number. ``` -------------------------------- ### Send Video by URL Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send a video file using its URL. An optional caption can be included. Ensure the `WhatsApp` object is initialized with your access token and phone number ID. ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) result = messenger.send_video( video="https://example.com/demo.mp4", recipient_id="15550001234", caption="Product demo", ) # result: {"messages": [{"id": "wamid.xxx"}]} ``` -------------------------------- ### Send Audio via URL Source: https://github.com/filipporomani/whatsapp-python/wiki/Sending audios Use this method to send an audio file by providing its direct URL. Ensure the URL points to a valid audio file. The `recipient_id` specifies the target chat, and `sender` indicates the sender (usually 0 for the main account). ```python >>> messenger.send_audio( audio="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3", recipient_id="255757xxxxxx", sender=0, ) ``` -------------------------------- ### Send Image by Media ID Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Upload a local image file first to obtain a media ID, then send the image using this ID. Set `link=False` to indicate that the `image` parameter is a media ID, not a URL. ```python media_response = messenger.upload_media("/path/to/photo.jpg") media_id = media_response["id"] # e.g. "1234567890123456" result = messenger.send_image( image=media_id, recipient_id="15550001234", caption="Uploaded locally", link=False, # False = treat `image` as a media ID, not a URL ) ``` -------------------------------- ### Send Sticker by Media ID Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send a sticker using its media ID. Set `link=False` to specify that the `sticker` parameter refers to a media ID, not a URL. The `WhatsApp` object needs to be initialized. ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) # Send by media ID (link=False) result = messenger.send_sticker( sticker="170511049062862", recipient_id="15550001234", link=False, ) ``` -------------------------------- ### send_sticker() Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send a sticker by URL or media ID. ```APIDOC ## Sending Stickers — `send_sticker()` ### Description Send a sticker by URL or media ID. ### Method ```python result = messenger.send_sticker( sticker="170511049062862", recipient_id="15550001234", link=False, ) ``` ### Parameters - **sticker** (string) - Required - The media ID or URL of the sticker. - **recipient_id** (string) - Required - The recipient's phone number. - **link** (boolean) - Optional - If True, `sticker` is treated as a URL. If False, `sticker` is treated as a media ID. Defaults to True. ``` -------------------------------- ### send_video() Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send a video by URL or media ID with an optional caption. ```APIDOC ## Sending Videos — `send_video()` ### Description Send a video by URL or media ID with an optional caption. ### Method ```python result = messenger.send_video( video="https://example.com/demo.mp4", recipient_id="15550001234", caption="Product demo", ) ``` ### Parameters - **video** (string) - Required - The media ID or URL of the video. - **recipient_id** (string) - Required - The recipient's phone number. - **caption** (string) - Optional - A caption for the video. ``` -------------------------------- ### Send Reply Buttons Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send an interactive message with up to three quick-reply buttons. The `WhatsApp` object needs to be initialized with access token and phone number ID. The message body and button titles are configurable. ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) result = messenger.send_reply_button( recipient_id="15550001234", button={ "type": "button", "body": {"text": "Would you like to proceed with your order?"}, "action": { "buttons": [ {"type": "reply", "reply": {"id": "yes_confirm", "title": "Yes, confirm"}}, {"type": "reply", "reply": {"id": "no_cancel", "title": "No, cancel"}}, {"type": "reply", "reply": {"id": "more_info", "title": "More info"}}, ] }, }, ) ``` -------------------------------- ### Send Video via URL Source: https://github.com/filipporomani/whatsapp-python/wiki/Sending videos Use this method to send a video by providing its URL. Ensure the recipient ID is correct and the sender is specified. ```python >>> messenger.send_video( video="https://www.youtube.com/watch?v=K4TOrB7at0Y", recipient_id="255757xxxxxx", sender=0, ) ``` -------------------------------- ### send_reply_button() Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send an interactive message with up to three quick-reply buttons. ```APIDOC ## Sending Reply Buttons — `send_reply_button()` ### Description Send an interactive message with up to three quick-reply buttons. ### Method ```python result = messenger.send_reply_button( recipient_id="15550001234", button={ "type": "button", "body": {"text": "Would you like to proceed with your order?"}, "action": { "buttons": [ {"type": "reply", "reply": {"id": "yes_confirm", "title": "Yes, confirm"}}, {"type": "reply", "reply": {"id": "no_cancel", "title": "No, cancel"}}, {"type": "reply", "reply": {"id": "more_info", "title": "More info"}}, ] }, }, ) ``` ### Parameters - **recipient_id** (string) - Required - The recipient's phone number. - **button** (object) - Required - The configuration for the reply buttons. ``` -------------------------------- ### Upload and Send Local Image Source: https://github.com/filipporomani/whatsapp-python/wiki/Sending images Upload a local image file to Whatsapp Cloud API first, then use the returned media ID to send it. Set `link=False` when sending the media. ```python >>> media_id = messenger.upload_media( media='path/to/media', )['id'] >>> messenger.send_image( image=media_id, recipient_id="255757xxxxxx", link=False, sender=0, ) ``` -------------------------------- ### Send Images with whatsapp-python Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send an image using the `send_image` method. Images can be provided via a public URL or a previously uploaded media ID. An optional caption can be included with the image. ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) # Send by public URL result = messenger.send_image( image="https://i.imgur.com/Fh7XVYY.jpeg", recipient_id="15550001234", caption="Check out this photo!", ) ``` -------------------------------- ### Configure Logging Level Source: https://github.com/filipporomani/whatsapp-python/wiki/Installation-&-Setup Set up custom logging levels for the application. By default, only error messages are logged. To disable logging, set the logger parameter to False during WhatsApp object initialization. ```python import logging logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", ) ``` -------------------------------- ### Asynchronous Error Handling with try-except and handle Source: https://github.com/filipporomani/whatsapp-python/wiki/Error-handling For the asynchronous version, errors must be handled manually. After awaiting the request, use a try-except block around app.handle() to catch and print any errors. ```python print("sending button") v = await app.send_button( { "header": "Header Testing", # obviously wrong button, as way more content is needed }, dest_phone_number, sender=1, ) while not v.done(): await asyncio.sleep(1) # wait for the request to finish try: app.handle(v.result()) except Exception as error: print(f"error: {error}") # catch the error ``` -------------------------------- ### Media Management Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Functions for uploading, querying, downloading, and deleting media files. ```APIDOC ## Media Management — `upload_media()`, `query_media_url()`, `download_media()`, `delete_media()` ### Description Upload local files to the WhatsApp Cloud, resolve media IDs to download URLs, download media to disk, and delete hosted media. ### Methods - **`upload_media(file_path)`**: Uploads a local file and returns media information. - **`query_media_url(media_id)`**: Resolves a media ID to a temporary download URL. - **`download_media(media_url, mime_type, file_path)`**: Downloads media from a URL to a local file. - **`delete_media(media_id)`**: Deletes a hosted media file. ### Request Example ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) # 1. Upload a local file → get a reusable media ID upload_result = messenger.upload_media("/tmp/invoice.pdf") media_id = upload_result["id"] # "1234567890123456" # 2. Resolve a media ID to a temporary download URL media_url = messenger.query_media_url(media_id) # media_url: "https://lookaside.fbsbx.com/whatsapp_business/..." # 3. Download media received from a user # (media_url and mime_type come from get_image / get_audio / etc.) saved_path = messenger.download_media( media_url=media_url, mime_type="application/pdf", file_path="/tmp/downloads/invoice", # extension added automatically → invoice.pdf ) print(saved_path) # "/tmp/downloads/invoice.pdf" # 4. Delete a hosted media file result = messenger.delete_media(media_id) # result: {"deleted": true} ``` ``` -------------------------------- ### Message.mark_as_read() Source: https://github.com/filipporomani/whatsapp-python/wiki/Message() Object Marks a message as read. Requires instance and id parameters during Message() initialization. ```APIDOC ## Message.mark_as_read() Mark a message as read. Required Message() initialization parameters: - instance - id ``` -------------------------------- ### Send Location Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send a GPS location pin with a display name and address. Requires the `WhatsApp` object to be initialized with credentials. Latitude and longitude are provided as strings. ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) result = messenger.send_location( lat="1.3521", long="103.8198", name="Marina Bay Sands", address="10 Bayfront Ave, Singapore 018956", recipient_id="15550001234", ) # result: {"messages": [{"id": "wamid.xxx"}]} ``` -------------------------------- ### Send Template Messages with whatsapp-python Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Use the `send_template` method to send pre-approved WhatsApp message templates. This is required for initial outbound messages and after the 24-hour conversation window. Specify the template name, recipient, language, and optional components with variables. ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) # Send the built-in hello_world template (no components) result = messenger.send_template( template="hello_world", recipient_id="15550001234", lang="en_US", ) # result: {"messages": [{"id": "wamid.xxx"}]} # Send a template with variable components result = messenger.send_template( template="order_confirmation", recipient_id="15550001234", lang="en_US", components=[ { "type": "body", "parameters": [ {"type": "text", "text": "ORD-98765"}, {"type": "text", "text": "$49.99"}, ], } ], ) ``` -------------------------------- ### send_button() Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send an interactive list message with a header, body, footer, and selectable row sections. Row titles must not exceed 20 characters. ```APIDOC ## Sending Interactive List Buttons — `send_button()` ### Description Send an interactive list message with a header, body, footer, and selectable row sections. Row titles must not exceed 20 characters. ### Method ```python result = messenger.send_button( recipient_id="15550001234", button={ "header": "Choose a Service", "body": "Please select an option below.", "footer": "Powered by Acme Corp", "action": { "button": "View Options", "sections": [ { "title": "Banking", "rows": [ {"id": "send_money", "title": "Send Money", "description": "Transfer funds"}, {"id": "check_balance", "title": "Check Balance", "description": "View your balance"}, ], }, { "title": "Support", "rows": [ {"id": "live_agent", "title": "Live Agent", "description": "Talk to a human"}, ], }, ], }, }, ) ``` ### Parameters - **recipient_id** (string) - Required - The recipient's phone number. - **button** (object) - Required - The configuration for the list message buttons. ``` -------------------------------- ### Send Interactive List Buttons Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send an interactive list message with a header, body, footer, and selectable row sections. Row titles must not exceed 20 characters. The `WhatsApp` object must be initialized. ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) result = messenger.send_button( recipient_id="15550001234", button={ "header": "Choose a Service", "body": "Please select an option below.", "footer": "Powered by Acme Corp", "action": { "button": "View Options", "sections": [ { "title": "Banking", "rows": [ {"id": "send_money", "title": "Send Money", "description": "Transfer funds"}, {"id": "check_balance", "title": "Check Balance", "description": "View your balance"}, ], }, { "title": "Support", "rows": [ {"id": "live_agent", "title": "Live Agent", "description": "Talk to a human"}, ], }, ], }, }, ) ``` -------------------------------- ### Async Usage with AsyncWhatsApp and AsyncMessage Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Use AsyncWhatsApp and AsyncMessage for non-blocking API calls with asyncio. All sending and media methods return asyncio.Future objects. Ensure all I/O methods are awaited. ```python import asyncio from whatsapp import AsyncWhatsApp, AsyncMessage messenger = AsyncWhatsApp( token="EAAxxxYYY", phone_number_id={"main": "123456789012345"}, verify_token="my-webhook-secret", debug=False, ) @messenger.on_message async def handle(msg: AsyncMessage): # All I/O methods must be awaited reply_future = await msg.reply("Got your message!") await asyncio.sleep(1) if reply_future.done(): print("Reply sent:", reply_future.result()) # Send a template asynchronously tpl_future = await messenger.send_template( template="hello_world", recipient_id=msg.to, lang="en_US", ) await asyncio.sleep(1) print("Template result:", tpl_future.result()) # Fire off an outbound message from outside a handler async def main(): outbound = messenger.create_message(to="15550001234", content="Async hello!") future = await outbound.send() await asyncio.sleep(3) print(future.result()) asyncio.run(main()) # Start the webhook server messenger.run(host="0.0.0.0", port=8000) ``` -------------------------------- ### Sending Text Messages - Message.send() Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Create a Message object with a recipient and content, then call .send(). An optional sender key selects which phone number ID to use when multiple numbers are configured. ```APIDOC ## Sending Text Messages — `Message.send()` Create a `Message` object with a recipient and content, then call `.send()`. An optional `sender` key selects which phone number ID to use when multiple numbers are configured. ```python from whatsapp import WhatsApp, Message messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) # Create and send a simple text message msg = messenger.create_message(to="15550001234", content="Hello from whatsapp-python!") result = msg.send() # result: {"messages": [{"id": "wamid.xxx"}]} # Send from a specific number in a multi-number setup messenger2 = WhatsApp( "EAAxxxYYY", phone_number_id={"sales": "111111111111111", "support": "222222222222222"}, ) msg2 = messenger2.create_message(to="15550001234", content="Support team here!") result2 = msg2.send(sender="support") ``` ``` -------------------------------- ### Sending Images - send_image() Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send an image by URL (default) or by a previously uploaded media ID. An optional caption can be included. ```APIDOC ## Sending Images — `send_image()` Send an image by URL (default) or by a previously uploaded media ID. An optional caption can be included. ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) # Send by public URL result = messenger.send_image( image="https://i.imgur.com/Fh7XVYY.jpeg", recipient_id="15550001234", caption="Check out this photo!", ) ``` ``` -------------------------------- ### Marking Messages as Read with Message.mark_as_read() Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send a read receipt for an incoming message, displaying blue ticks in the sender's WhatsApp app. The result indicates success. ```python from whatsapp import WhatsApp, Message messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) @messenger.on_message async def handle(msg: Message): result = msg.mark_as_read() # result: {"success": true} ``` -------------------------------- ### Sending Template Messages - send_template() Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send a pre-approved WhatsApp message template. Templates are required for the first outbound message to a user and after the 24-hour conversation window expires. ```APIDOC ## Sending Template Messages — `send_template()` Send a pre-approved WhatsApp message template. Templates are required for the first outbound message to a user and after the 24-hour conversation window expires. ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) # Send the built-in hello_world template (no components) result = messenger.send_template( template="hello_world", recipient_id="15550001234", lang="en_US", ) # result: {"messages": [{"id": "wamid.xxx"}]} # Send a template with variable components result = messenger.send_template( template="order_confirmation", recipient_id="15550001234", lang="en_US", components=[ { "type": "body", "parameters": [ {"type": "text", "text": "ORD-98765"}, {"type": "text", "text": "$49.99"}, ], } ], ) ``` ``` -------------------------------- ### Send Contacts using send_contacts() Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Use this method to send one or more vCard-style contact objects to a user. Ensure the contact details are correctly formatted. ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) result = messenger.send_contacts( recipient_id="15550001234", contacts=[ { "name": {"formatted_name": "Jane Doe", "first_name": "Jane", "last_name": "Doe"}, "phones": [{"phone": "+1 555 000 9999", "type": "CELL", "wa_id": "15550009999"}], "emails": [{"email": "jane@example.com", "type": "WORK"}], "addresses": [ { "street": "123 Main St", "city": "Springfield", "state": "IL", "zip": "62701", "country": "United States", "country_code": "US", "type": "HOME", } ], } ], ) ``` -------------------------------- ### Send Document via URL Source: https://github.com/filipporomani/whatsapp-python/wiki/Sending documents Use this method to send a document directly from a URL. Ensure the URL is publicly accessible and points to a valid document file. The `recipient_id` and `sender` must be provided. ```python >>> messenger.send_document( document="http://www.africau.edu/images/default/sample.pdf", recipient_id="255757xxxxxx", sender=0, ) ``` -------------------------------- ### send_location() Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send a GPS location pin with a display name and address. ```APIDOC ## Sending Location — `send_location()` ### Description Send a GPS location pin with a display name and address. ### Method ```python result = messenger.send_location( lat="1.3521", long="103.8198", name="Marina Bay Sands", address="10 Bayfront Ave, Singapore 018956", recipient_id="15550001234", ) ``` ### Parameters - **lat** (string) - Required - The latitude of the location. - **long** (string) - Required - The longitude of the location. - **name** (string) - Required - The display name of the location. - **address** (string) - Required - The address of the location. - **recipient_id** (string) - Required - The recipient's phone number. ``` -------------------------------- ### Synchronous Error Handling with try-except Source: https://github.com/filipporomani/whatsapp-python/wiki/Error-handling Use a try-except statement to catch any errors that occur during message or button sending with the synchronous WhatsApp class. This is handled by default in library methods. ```python print("sending button") try: app.send_button( { "header": "Header Testing", # obviously wrong button, as way more content is needed }, dest_phone_number, sender=1, ) except Exception as e: print(f"send_button: {e}") ``` -------------------------------- ### Webhook Parsing Utilities Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Static helper methods to extract structured data from the raw webhook payload dict received by custom Flask/FastAPI handlers. ```APIDOC ## Webhook Parsing Utilities Static helper methods to extract structured data from the raw webhook payload dict received by custom Flask/FastAPI handlers. ```python from whatsapp import WhatsApp messenger = WhatsApp("EAAxxxYYY", phone_number_id={"default": "123456789012345"}) # data = raw JSON dict from the webhook POST body data = { ... } # WhatsApp Cloud API webhook payload # Determine what changed in this notification field = messenger.changed_field(data) # "messages" | "statuses" | ... if field == "messages" and messenger.is_message(data): mobile = messenger.get_mobile(data) # "15550001234" name = messenger.get_name(data) # "Jane Doe" author = messenger.get_author(data) # "15550001234" (sender's WA ID) msg_id = messenger.get_message_id(data) # "wamid.HBg..." msg_type = messenger.get_message_type(data) # "text" | "image" | "audio" | ... timestamp = messenger.get_message_timestamp(data) # "1712345678" if msg_type == "text": text = messenger.get_message(data) # "Hello!" elif msg_type == "image": image = messenger.get_image(data) # {"id": "...", "mime_type": "image/jpeg"} elif msg_type == "audio": audio = messenger.get_audio(data) # {"id": "...", "mime_type": "audio/ogg"} elif msg_type == "video": video = messenger.get_video(data) # {"id": "...", "mime_type": "video/mp4"} elif msg_type == "document": doc = messenger.get_document(data) # {"id": "...", "filename": "file.pdf"} elif msg_type == "location": loc = messenger.get_location(data) # {"latitude": 1.35, "longitude": 103.82} elif msg_type == "interactive": resp = messenger.get_interactive_response(data) # resp: {"type": "list_reply", "list_reply": {"id": "row_1", "title": "Send Money"}} interactive_type = resp.get("type") choice_id = resp[interactive_type]["id"] choice_title = resp[interactive_type]["title"] else: delivery_status = messenger.get_delivery(data) # "delivered" | "read" | None ``` ``` -------------------------------- ### send_document() Source: https://context7.com/filipporomani/whatsapp-python/llms.txt Send a document (PDF, DOCX, etc.) by URL or media ID with an optional caption. ```APIDOC ## Sending Documents — `send_document()` ### Description Send a document (PDF, DOCX, etc.) by URL or media ID with an optional caption. ### Method ```python result = messenger.send_document( document="https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf", recipient_id="15550001234", caption="Your monthly invoice", ) ``` ### Parameters - **document** (string) - Required - The media ID or URL of the document. - **recipient_id** (string) - Required - The recipient's phone number. - **caption** (string) - Optional - A caption for the document. ```