How to Send WhatsApp Messages via API in Python Without Twilio
Twilio's WhatsApp API works, but it's expensive ($0.05+ per conversation), requires a complex account setup, and the sandbox is frustrating to use during development. For developers in Brazil and Latin America especially, there are better options.
This tutorial shows how to send WhatsApp messages โ both template messages and free-form replies โ using IteraTools' WhatsApp endpoint, with complete curl and Python examples.
What You'll Need
- An IteraTools API key (get one at api.iteratools.com)
- A WhatsApp number to send to (recipient must be on WhatsApp)
- 5 minutes
No WhatsApp Business account registration. No Meta app approval. No webhook setup for basic sending.
What to Consider When Choosing a WhatsApp API
| Tool | Price | Setup Time | Template Required | Limitations |
|---|---|---|---|---|
| IteraTools | ~$0.005/msg (credits) | Minutes | No (for replies) | Volume limits |
| Twilio | $0.05/conversation + msg fee | Hours/days | Yes (for outbound) | Expensive |
| 360dialog | $50/mo + per msg | Days (BSP approval) | Yes | Complex setup |
| Meta Cloud API | Free (infra costs) | Days (app review) | Yes | Self-managed |
| Zapi / WPPConnect | ~$30/mo | Hours | No | TOS gray area |
Sending a Message โ curl
Send a WhatsApp message via IteraTools:
curl -X POST https://api.iteratools.com/v1/whatsapp/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+5511999998888",
"message": "Hello! Your order #1234 has been shipped and will arrive by Friday."
}'
Response:
{
"message_id": "wamid.abc123xyz",
"status": "sent",
"to": "+5511999998888",
"credits_used": 1
}
Send a message with media:
curl -X POST https://api.iteratools.com/v1/whatsapp/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+5511999998888",
"message": "Here is your invoice:",
"media_url": "https://example.com/invoice_1234.pdf",
"media_type": "document"
}'
Receiving Replies โ Webhook Setup
To receive incoming WhatsApp messages, set up a webhook endpoint in your IteraTools dashboard. Incoming messages will be POSTed to your URL:
{
"from": "+5511999998888",
"message": "Yes, please confirm my order.",
"message_id": "wamid.inbound456",
"timestamp": "2025-03-15T14:32:00Z"
}
Reply to an incoming message:
curl -X POST https://api.iteratools.com/v1/whatsapp/reply \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"message_id": "wamid.inbound456",
"message": "Great! Your order has been confirmed. ๐"
}'
Complete Python Example
import requests
from flask import Flask, request, jsonify
API_KEY = "your_api_key_here"
BASE_URL = "https://api.iteratools.com/v1"
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Sending Messages
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def send_whatsapp(to: str, message: str, media_url: str = None) -> dict:
"""Send a WhatsApp message."""
payload = {
"to": to,
"message": message
}
if media_url:
payload["media_url"] = media_url
payload["media_type"] = "image"
response = requests.post(
f"{BASE_URL}/whatsapp/send",
headers={"Authorization": f"Bearer {API_KEY}"},
json=payload
)
response.raise_for_status()
return response.json()
def reply_whatsapp(message_id: str, reply_text: str) -> dict:
"""Reply to an incoming WhatsApp message."""
response = requests.post(
f"{BASE_URL}/whatsapp/reply",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"message_id": message_id,
"message": reply_text
}
)
response.raise_for_status()
return response.json()
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Webhook Server (to receive messages)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
app = Flask(__name__)
def handle_incoming_message(sender: str, text: str, message_id: str) -> str:
"""Simple keyword-based auto-reply bot."""
text_lower = text.lower().strip()
if any(word in text_lower for word in ["hi", "hello", "hey", "oi", "olรก"]):
return "Hello! ๐ How can I help you today?"
elif "order" in text_lower or "pedido" in text_lower:
return (
"To check your order status, please reply with your order number. "
"Example: ORDER 12345"
)
elif text_lower.startswith("order "):
order_num = text_lower.replace("order ", "").strip()
# In production, look up the order in your database
return f"Order #{order_num}: Shipped โ
Expected delivery: Friday, March 21"
else:
return (
"I didn't understand that. Try:\n"
"โข *ORDER [number]* โ check order status\n"
"โข *HELP* โ see all commands"
)
@app.route("/webhook/whatsapp", methods=["POST"])
def whatsapp_webhook():
data = request.json
sender = data.get("from")
text = data.get("message", "")
message_id = data.get("message_id")
print(f"Incoming from {sender}: {text}")
# Generate auto-reply
reply_text = handle_incoming_message(sender, text, message_id)
# Send reply
result = reply_whatsapp(message_id, reply_text)
print(f"Replied: {result['status']}")
return jsonify({"status": "ok"})
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Main: Bulk Send Example
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
if __name__ == "__main__":
# Example: Send order confirmations to a list of customers
orders = [
{"phone": "+5511999990001", "order": "1001", "item": "Wireless Headphones"},
{"phone": "+5511999990002", "order": "1002", "item": "Phone Case"},
{"phone": "+5521999990003", "order": "1003", "item": "USB-C Cable"},
]
for order in orders:
message = (
f"Hi! Your order #{order['order']} ({order['item']}) "
f"has been confirmed and will ship within 24 hours. "
f"Thank you for your purchase! ๐๏ธ"
)
result = send_whatsapp(order["phone"], message)
print(f"Sent to {order['phone']}: {result['status']}")
# Start webhook server (run in production with gunicorn)
# app.run(port=5000, debug=True)
Sending WhatsApp Without Code (one-liner)
For quick testing:
# Send a test message right now
curl -X POST https://api.iteratools.com/v1/whatsapp/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"to": "+YOUR_NUMBER", "message": "Test from IteraTools API โ
"}'
Conclusion
Sending WhatsApp messages via API doesn't have to mean navigating Twilio's pricing or Meta's Business Manager setup. IteraTools makes it straightforward: one API key, one endpoint, pay per message with no monthly fees.
For projects already using IteraTools for scraping, PDFs, or image processing, adding WhatsApp notifications is a 5-minute addition โ no new accounts needed.
Top comments (0)