Send WhatsApp messages with Python
Use the popular requests library to send WhatsApp messages from any Python app β Django, Flask, FastAPI, a cron job or a Jupyter notebook.
Before you start
- Create a free account and copy your API key from Settings.
- Add a WhatsApp number and scan the QR code; copy its instance id.
- Replace
YOUR_API_KEYandYOUR_INSTANCE_IDin the examples below.
1. Setup
pip install requests
2. Send a WhatsApp text message with Python
The recipient goes in to with the country code (for India, 91 followed by the 10-digit number). The response contains the message id and status.
import requests
API_KEY = "YOUR_API_KEY"
INSTANCE_ID = "YOUR_INSTANCE_ID"
BASE = "https://powerapiwa.com/api/v1"
resp = requests.post(
f"{BASE}/instances/{INSTANCE_ID}/send",
headers={"x-api-key": API_KEY},
json={"to": "919876543210", "type": "text", "message": "Hello from Python π"},
timeout=30,
)
resp.raise_for_status()
print(resp.json()["message"]["status"]) # "sent"
3. Send an image, PDF or location
Change the type: media_url for files from a URL, media for base64 uploads, location, poll or contact.
resp = requests.post(
f"{BASE}/instances/{INSTANCE_ID}/send",
headers={"x-api-key": API_KEY},
json={
"to": "919876543210",
"type": "media_url",
"url": "https://example.com/invoice.pdf",
"caption": "Your invoice #1042",
},
timeout=60,
)
4. Receive messages with a webhook
Set your endpoint URL on the WhatsApp number in the dashboard. Always verify the X-PowerAPI-Signature header before trusting the payload.
import hashlib, hmac
from flask import Flask, request, abort
app = Flask(__name__)
WEBHOOK_SECRET = "YOUR_WEBHOOK_SECRET"
@app.post("/whatsapp/webhook")
def whatsapp_webhook():
expected = hmac.new(WEBHOOK_SECRET.encode(), request.get_data(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, request.headers.get("X-PowerAPI-Signature", "")):
abort(401)
event = request.get_json()
if event["event"] == "message":
msg = event["data"]["message"]
print(msg["from"], msg.get("body"))
return {"ok": True}
Response and errors
Successful calls return {"success": true, ...}. Errors return {"success": false, "error": "..."} with a status code: 401 invalid key, 402 plan expired, 422 invalid payload, 429 daily limit reached. See the full API documentation.