Meta has launched an API accessible for businesses or developers to extend their services or allow better communication.
In this series of articles, we will build a simple web service using Flask and the Cloud API. At the end of the series, we'll have a Flask server deployed that can be used to send messages to a phone number but also received notifications via webhooks.
Great, right? Let's start with configuring the project and sending a template message.
Requirements
You need to configure a business account with Meta developers. Here is some documentation but I'll give steps below:
- Create a Meta business account.
- Create a WhatsApp business account.
- Link the WhatsApp business account to the Meta business account.
- Create a new application under the name of the Meta business account.
- Configure Whatsapp.
Configuring the project
Create the directory that will contain the flask project.
mkdir flask-whatsapp-api
cd flask-whatsapp-api
After that, create a virtual environment.
python3.10 -m venv venv
And activate the environment.
source venv/bin/activate
Next, install the dependencies.
pip install Flask requests python-dotenv gunicorn
Creating the Flask App
At the root of the project, create a config.py file. This file will be helpful to load env variables.
from dotenv import load_dotenv
load_dotenv()
Adding the Whatsapp Client
Next, create a new directory called app
with a __init__.py
file inside it. This will tell Python that this is a package and it will help with imports.
Inside the app
directory, create a file named whatsapp_client.py
. This file will contain a wrapper to interact with the Whatsapp Cloud API.
It's always an interesting habit to write wrappers (classes or functions) when you will be interacting with external services.
In this case, we'll write a class called WhatsAppWrapper
. Let's start with basic initialization.
# app/whatsapp_client.py
import os
import requests
import json
class WhatsAppWrapper:
API_URL = "https://graph.facebook.com/v13.0/"
API_TOKEN = os.environ.get("WHATSAPP_API_TOKEN")
NUMBER_ID = os.environ.get("WHATSAPP_NUMBER_ID")
def __init__(self):
self.headers = {
"Authorization": f"Bearer {self.API_TOKEN}",
"Content-Type": "application/json",
}
self.API_URL = self.API_URL + self.NUMBER_ID
def send_template_message(self, template_name, language_code, phone_number):
pass
Let's write the send_template_message
method. We'll just use the requests
package to make a request to the Cloud API and return a response if possible.
...
def send_template_message(self, template_name, language_code, phone_number):
payload = json.dumps({
"messaging_product": "whatsapp",
"to": phone_number,
"type": "template",
"template": {
"name": template_name,
"language": {
"code": language_code
}
}
})
response = requests.request("POST", f"{self.API_URL}/messages", headers=self.headers, data=payload)
assert response.status_code == 200, "Error sending message"
return response.status_code
Good, with the wrapper ready, we now move to write the Flask web application and add the POST
endpoint.
Adding the Flask Web App
Inside the app
directory, create a new file called main.py
. It will contain our API routes.
import os
from flask import Flask, jsonify, request
from app.whatsapp_client import WhatsAppWrapper
app = Flask(__name__)
VERIFY_TOKEN = os.environ.get('WHATSAPP_HOOK_TOKEN')
@app.route("/")
def hello_world():
return "Hello World!"
@app.route("/send_template_message/", methods=["POST"])
def send_template_message():
pass
Let's write the send_template_message
controller. Basically, we need to check for the fields and just initialize a WhatsApp client and then send the message.
@app.route("/send_template_message/", methods=["POST"])
def send_template_message():
"""_summary_: Send a message with a template to a phone number"""
if "language_code" not in request.json:
return jsonify({"error": "Missing language_code"}), 400
if "phone_number" not in request.json:
return jsonify({"error": "Missing phone_number"}), 400
if "template_name" not in request.json:
return jsonify({"error": "Missing template_name"}), 400
client = WhatsAppWrapper()
response = client.send_template_message(
template_name=request.json["template_name"],
language_code=request.json["language_code"],
phone_number=request.json["phone_number"],
)
return jsonify(
{
"data": response,
"status": "success",
},
), 200
The route for this article is ready. Let's create and run the server with gunicorn
and configure env variables.
Running the project
As we are working with tokens and ids provided by WhatsApp API, it's important to have them as environment variables.
Create a .env
file at the root of the project and proved the following values.
WHATSAPP_API_TOKEN=
WHATSAPP_NUMBER_ID=
And add the values provided on your Dashboard.
At the root of the project, add a new file called wsgi.py
. This will be used by gunicorn
to run the Flask application.
from app.main import app
if __name__ == "__main__":
app.run()
And then launch the project with the following command.
gunicorn -w 4 wsgi:app
Your application will be running at http://127.0.0.1:8000.
Make a POST
request to http://127.0.0.1:8000/send_message
with the following payload.
{
"template_name": "hello_world",
"language_code": "en_US",
"phone_number": "RECIPIENT_PHONE_NUMBER"
}
And you'll receive a WhatsApp message on the number.
And we have the first version of a web service using WhatsApp Cloud API and Flask. In the next part, we'll deploy the Flask application on Heroku and configure a webhook. Stay tuned.🤟
Want to add something or have some comments? Let's discuss this in the comments section.
Article posted using bloggu.io. Try it for free.
Top comments (4)
Great ...
Thank you 🚀
Good Python article.
thank you Andrew