https://a.storyblok.com/f/270183/1368x665/71639c72db/25dec_dev-blog_python-fast-whatsapp.jpg

Send and Receive WhatsApp Messages With Python, FastAPI, and Vonage

最終更新日 December 10, 2025

所要時間:7 分

Introduction

Want to build a WhatsApp bot using Python? Need to send and receive WhatsApp messages programmatically? This tutorial shows you how to create a real-time messaging service using Python, FastAPI, and the Vonage Messages API.

With a WhatsApp chatbot as your foundation, you’ll be able to automate support, reminders, and marketing flows, like sending confirmations, handling customer inquiries, or triggering follow-ups.

We’ll use the Vonage Python SDK to connect a WhatsApp number within a FastAPI server that receives and replies to messages in real time.

>> TL;DR See the complete project on GitHub

Animated GIF of a WhatsApp chat where a user sends a message and receives an automated reversed-text reply from a Python FastAPI botWhatsApp chat showing an automated reply from a Python FastAPI app using the Vonage Messages API

Prerequisites

To follow this tutorial, you'll need:

Vonage API Account

To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

Step 1: Create Your Vonage App and Webhooks

Your FastAPI application will be relatively simple, with a single file. But before creating it, we’ll start by creating a Vonage app to be ready with all the necessary configurations.

Create a Messages API Application

Create your Vonage application in the Vonage Dashboard. Give the app a name and turn on the Messages capability. For now, we’ll use placeholder endpoints, which we’ll replace in the next section (Expose Your Local FastAPI Server).

Screenshot of the Vonage dashboard showing the 'Create an application' form. The application is named WhatsApp-FastAPI and includes JWT authentication setup, AI data sharing disabled, and Messages capability enabled with ngrok webhook URLs for inbound and status events.Setting up a Vonage Messages API application for WhatsApp using FastAPI and ngrok.In your Vonage application settings:

  1. Set the Inbound URL to https://YOUR_NGROK_URL/inbound.

  2. Set the Status URL to https://YOUR_NGROK_URL/status.

  3. Generate a public and private key by clicking the button. Ensure to move your private.key file to the project root directory (whatsapp-fastapi) in the next section.

  4. Save the changes.

Then link your WABA by clicking the “Link external accounts” tab:

Screenshot of the Vonage Messages API dashboard showing the 'WhatsApp-FastAPI' application. It displays the Application ID, API Key, and status indicating the WhatsApp number 'Vonage DevRel' is linked with the application. A red 'Unlink' button is visible on the right.Viewing the WhatsApp-FastAPI application in the Vonage dashboard with an active WhatsApp number linked.

Expose Your Local FastAPI Server

To receive webhooks, your application will rely on ngrok to expose your local server.

In a second terminal tab:

ngrok http 3000

Copy the NGROK_URL that looks something like:

https://abc123.ngrok.io

Go back to your Vonage application and update the webhook URLs to replace YOUR_NGROK_URL with your actual ngrok URLs. For example:

  • Inbound URL: https://abc123.ngrok.io/inbound

  • Status URL: https://abc123.ngrok.io/status

Click Save to finalize the setup.

>> Learn more about testing with ngrok

Step 2: Create Your Python FastAPI Project

Project Setup

Create your project folder:

mkdir whatsapp-fastapi
cd whatsapp-fastapi
touch main.py .env

Then, create and activate a virtual environment so you can install the required Python packages:

python3 -m venv venv
source venv/bin/activate
pip install fastapi uvicorn python-dotenv vonage
  • fastapi: A modern, high-performance web framework for building APIs quickly with async support and automatic documentation.

  • vonage: The official Vonage Python SDK, used to send and receive WhatsApp messages through the Vonage Messages API.

  • uvicorn: A lightning-fast ASGI server used to run your FastAPI app in development or production.

  • python-dotenv: Loads environment variables securely from a .env file so you don’t hardcode credentials in your codebase.

Configure Your Environment

In your .env file, add the following (replace with your actual credentials). This file keeps your credentials secure and out of your source code.

VONAGE_APPLICATION_ID=your_application_id
VONAGE_PRIVATE_KEY=./private.key
VONAGE_WHATSAPP_NUMBER=your_vonage_virtual_number
  • VONAGE_APPLICATION_ID: Your Vonage application ID, found in the API dashboard.

  • VONAGE_PRIVATE: Your private key file. Ensure to move your downloaded private.key file to the project root directory (whatsapp-fastapi).

  • VONAGE_WHATSAPP_NUMBER: Your Vonage virtual phone number associated with your WABA.

    • Phone numbers should be in international format without any + or 00. For example, a US number would be 15552345678

>> Learn more about Python Environment Variables.

Initialize FastAPI and Vonage SDK

Now let’s set the stage for sending and receiving WhatsApp messages by wiring up your FastAPI application and initializing the Vonage client.

Your main.py will serve as the entry point for your FastAPI app.

# main.py
import os
import logging
import json
from dotenv import load_dotenv
from fastapi import FastAPI, Request, Response
from vonage import Auth, Vonage
from vonage_messages import WhatsappText

We start by importing the necessary libraries:

  • os and dotenv help us load sensitive credentials from our .env file.

  • fastapi, Request, and Response are used to define API routes and handle incoming HTTP requests.

  • vonage and vonage_messages give us access to the Vonage Messages API, specifically WhatsApp.

load_dotenv()

Here we load your .env file so you can securely access your application ID, private key path, and WhatsApp number without hardcoding them.

logging.basicConfig(level=logging.INFO)

This enables basic logging to help you debug and monitor incoming messages and events in your terminal as they happen.

auth = Auth(
    application_id=os.getenv("VONAGE_APPLICATION_ID"),
    private_key=os.getenv("VONAGE_PRIVATE_KEY"),
)
vonage_client = Vonage(auth)

This is where we initialize the Vonage client using the new SDK. You pass in your application_id and the path to your private key file to authenticate your API requests. The Vonage() instance will allow you to send WhatsApp messages using the Messages API.

app = FastAPI()

This creates the FastAPI application instance. You'll use this to define your webhook endpoints and run your development server.

WHATSAPP_NUMBER = os.getenv("VONAGE_WHATSAPP_NUMBER")

Finally, we store your WhatsApp sender number in a variable so it’s easy to reuse when sending outbound messages later.

Step 3: Handle Incoming WhatsApp Messages and Send Replies

To build a working WhatsApp bot, you need two webhook endpoints:

  1. One to receive incoming messages from WhatsApp users

  2. One to track message status updates (e.g., delivered, read, failed)

You can see the working main.py file on GitHub.

Handle Incoming Messages via Webhook

Create an /inbound endpoint that listens for incoming WhatsApp messages. When someone sends a message to your Vonage WhatsApp number, Vonage makes a POST request to this URL with a JSON payload describing the message.

Here’s how to handle it:

@app.post("/inbound")
async def receive_whatsapp_message(request: Request):
    try:
        data = await request.json()
    except Exception:
        raw = await request.body()
        try:
            data = json.loads(raw)
        except:
            data = {}

This block tries to parse the incoming request as JSON. If it fails (sometimes the body is just raw bytes), it falls back to decoding and loading it manually.

 logging.info(f"🔍 Full inbound payload: {json.dumps(data, indent=2)}")

 For debugging and transparency, we log the entire payload to the console. This is helpful during development to understand what fields are available and how the data is structured.

    sender = data.get("from")
    message = data.get("text")

Here we extract two key fields:

  • from: the user's phone number who sent the WhatsApp message

  • text: the actual message content

Send a WhatsApp Reply

Now that you’ve received the message, let’s send a response. In this example, the bot just reverses the user's message and sends it back; a fun and simple way to demonstrate two-way messaging.

  if sender and message:
        reversed_text = message[::-1]
        reply = WhatsappText(
            from_=WHATSAPP_NUMBER,
            to=sender,
            text=f"Here's your message in reverse: {reversed_text}",
        )
        response = vonage_client.messages.send(reply)
        logging.info(f"📤 Sent reply: {response}")

Here’s what’s happening:

  • We check that both the sender number and message are present.

  • We reverse the message string using Python slice syntax [::-1].

  • We construct a WhatsappText message using the Vonage SDK. This creates the proper JSON payload under the hood.

  • Finally, we send the message with vonage_client.messages.send(reply), and log the response.

return Response(status_code=200)

This tells Vonage that the webhook request was successfully received. Always return a 200 OK response to acknowledge webhook delivery.

Track Delivery and Read Receipts (Optional)

You can also listen for message status events by implementing a /status endpoint. This receives delivery confirmations and read receipts, which can help you debug or analyze message flow.

@app.post("/status")
async def message_status_update(request: Request):
    data = await request.json()
    logging.info(f"📬 Status update: {data}")
    return Response(status_code=204)

When you send a WhatsApp message, Vonage will call this endpoint later with status updates such as:

  • delivered: the user’s device received the message

  • read: the user opened the message

  • failed: delivery failed (e.g., invalid number)

Step 4: Run and Test Your FastAPI App

In your terminal, start your server:

uvicorn main:app --reload --port 3000

Now:

  1. Send a WhatsApp message to your Vonage WABA number

  2. Your FastAPI app will:

    • Log the incoming message

    • Send a reversed reply using the Vonage Messages API

  3. You’ll see the reply in your WhatsApp chat

>> You can see the status of your message updated in the FastAPI server (your terminal). 

Bonus: How to Send a WhatsApp Message

Sometimes, you want to send a message programmatically, not just in response to a webhook. Here’s a simple script you can run. First, create a new send_message.py file:

touch send_message.py

This script looks largely the same as before. But instead of sending a hardcoded message, we’ll prompt the user via the command line to enter a phone number and a message to send.

# send_message.py
import os
from dotenv import load_dotenv
from vonage import Auth, Vonage
from vonage_messages import WhatsappText

load_dotenv()

auth = Auth(
    application_id=os.getenv("VONAGE_APPLICATION_ID"),
    private_key=os.getenv("VONAGE_PRIVATE_KEY"),
)

vonage_client = Vonage(auth)

# Ask the user for phone number and message text
recipient = input("Enter recipient phone number (e.g., 14155551234): ").strip()
message = input("Enter a message to send: ").strip()

msg = WhatsappText(
    from_=os.getenv("VONAGE_WHATSAPP_NUMBER"),
    to=recipient,
    text=message,
)

response = vonage_client.messages.send(msg)
print(response)

To run it:

source venv/bin/activate && python3 send_message.py

And then you will see:

Terminal screenshot showing a Python script prompting for a phone number and message text, then returning a WhatsApp message UUID after successful delivery.Sending a WhatsApp message using the Python CLI with FastAPI and the Vonage SDK.

Conclusion

You've now built a working WhatsApp bot in Python using FastAPI and the Vonage Messages API. This is a great starting point for real-time support, automation, or chatbots!

If you’re eager to keep building and learning, check out these related tutorials:

  1. Connect WhatsApp to ChatGPT in Python: use OpenAI to build smart, conversational bots

  2. Try RCS Messaging in Python: RCS is like WhatsApp, but natively in your phone's messaging app

Have a question or something to share? Join the conversation on the Vonage Community Slack, stay up to date with the Developer Newsletter, follow us on X (formerly Twitter), subscribe to our YouTube channel for video tutorials, and follow the Vonage Developer page on LinkedIn, a space for developers to learn and connect with the community. Stay connected, share your progress, and keep up with the latest developer news, tips, and events!

シェア:

https://a.storyblok.com/f/270183/384x384/e4e7d1452e/benjamin-aronov.png
Benjamin AronovDeveloper Advocate

Benjamin Aronov is a developer advocate at Vonage. He is a proven community builder with a background in Ruby on Rails. Benjamin enjoys the beaches of Tel Aviv which he calls home. His Tel Aviv base allows him to meet and learn from some of the world's best startup founders. Outside of tech, Benjamin loves traveling the world in search of the perfect pain au chocolat.