Skip to content
WbizTool

Send WhatsApp messages with Python

Send WhatsApp texts, images and files from a Python script, from your own number linked to WbizTool like WhatsApp Web. Use the official wbiztool-client package or a plain requests call to the same endpoint.

Free trial: 50 messages in any 30 days, no card.

How it works

  1. Get your API key and link your number

    Sign up, then link your WhatsApp number on the WhatsApp numbers page with a QR code or a pairing code, like WhatsApp Web. On Settings → API keys, create a key and copy your Client ID (the API keys guide below shows where). The ID on the number's card (such as ID 678) is your whatsapp_client.

  2. Install the client, or use requests

    Run pip install wbiztool-client for the official client. If you'd rather not add a package, the requests library works just as well – the examples below show both.

  3. Send the message

    POST your credentials, the phone number and the text to https://wbiztool.com/api/v1/send_msg/. A reply with "status": 1 and a msg_id means the message is queued on your number.

  4. Check that it went out

    Pass a webhook URL to be told when the message is sent or fails, or ask the Message status endpoint with the msg_id.

Python code examples

Install the official client
pip install wbiztool-client
Send a text with the official client
from wbiztool_client import WbizToolClient

client = WbizToolClient(api_key="YOUR_API_KEY", client_id="12345")

result = client.send_message(
    phone="9876543210",
    country_code="91",
    msg="Hi Aman, your order #4821 has shipped.",
    whatsapp_client=678,
)
print(result)
Send a text with requests
import requests

response = requests.post(
    "https://wbiztool.com/api/v1/send_msg/",
    json={
        "client_id": 12345,
        "api_key": "YOUR_API_KEY",
        "whatsapp_client": 678,
        "msg_type": 0,
        "country_code": "91",
        "phone": "9876543210",
        "msg": "Hi Aman, your order #4821 has shipped and will arrive on Thursday.",
    },
    timeout=60,
)
result = response.json()  # read the body even when the HTTP code is 400

if result.get("status") == 1:
    print("Queued with msg_id", result["msg_id"])
else:
    print("Failed:", result.get("message"))
Reply
{"status": 1, "message": "Created", "msg_id": 9817263}
Send a PDF (file upload)
import requests

with open("invoice-4821.pdf", "rb") as f:
    response = requests.post(
        "https://wbiztool.com/api/v1/send_msg/",
        data={
            "client_id": 12345,
            "api_key": "YOUR_API_KEY",
            "whatsapp_client": 678,
            "msg_type": 2,
            "country_code": "91",
            "phone": "9876543210",
            "msg": "Your invoice for order #4821 is attached.",
            "file_name": "invoice-4821.pdf",
        },
        files={"file": f},
        timeout=120,
    )
print(response.json())
Check the message status
import requests

msg_id = 9817263
response = requests.post(
    f"https://wbiztool.com/api/v1/message/status/{msg_id}/",
    json={
        "client_id": 12345,
        "api_key": "YOUR_API_KEY",
    },
    timeout=60,
)
result = response.json()  # read the body even when the HTTP code is 400

if result.get("message") == "Unknown message id":
    print("No message with this ID in your workspace")
elif "status_text" not in result:
    print("Request failed:", result.get("message", "no message in response"))
elif result["status"] == 1:
    print("Sent")
elif result["status"] == 2:
    print("Failed:", result["error"])
else:
    print("Status:", result["status_text"])
Schedule a message for later
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo

import requests

send_at = datetime.now(ZoneInfo("Asia/Kolkata")) + timedelta(hours=2)

response = requests.post(
    "https://wbiztool.com/api/v1/schedule_msg/",
    json={
        "client_id": 12345,
        "api_key": "YOUR_API_KEY",
        "whatsapp_client": 678,
        "msg_type": 0,
        "country_code": "91",
        "phone": "9876543210",
        "msg": "Hi Aman, a reminder that your appointment starts in 30 minutes.",
        "date": send_at.strftime("%d/%m/%Y"),
        "time": send_at.strftime("%H:%M"),
        "timezone": "Asia/Kolkata",
    },
    timeout=60,
)
result = response.json()  # schedule errors come back with HTTP 200 and "status": 0

if result.get("status") == 1:
    print("Scheduled with msg_id", result["msg_id"])
else:
    print("Failed:", result.get("message", "no message in response"))
Receive the status webhook (Flask)
from flask import Flask, request

app = Flask(__name__)

@app.post("/wbiztool-webhook")
def wbiztool_webhook():
    # WbizTool posts form fields, not JSON.
    msg_id = request.form["msg_id"]
    status = request.form["status"]  # SENT, FAILED, CANCELLED or EXPIRED
    print(msg_id, status)
    return "", 200

What you can do

  • Texts, images and files

    Set msg_type to 0 for text, 1 for an image or 2 for a file. Give a public img_url or file_url, or upload the file itself with files= in requests.

  • Personal messages from your data

    Build msg from your own records – a name, an order number, a due date. WhatsApp formatting such as *bold* and _italic_ works, up to 3,000 characters.

  • Status by webhook or by asking

    A webhook gets a POST with the msg_id and SENT, FAILED, CANCELLED or EXPIRED. Or call Message status: a failed message comes with its error, such as Phone number invalid.

  • Schedule for later

    POST to /api/v1/schedule_msg/ with date (dd/mm/yyyy), time (HH:MM) and a timezone such as Asia/Kolkata. strftime("%d/%m/%Y") and strftime("%H:%M") build them for you.

  • Drop messages that come too late

    expire_after_seconds marks a message as expired if it hasn't gone out in time, which suits time-sensitive messages such as delivery ETAs.

  • Recurring reminders

    The Reminders API repeats a message on a cron schedule, such as 10:00 on the 1st of every month. Reminders need a paid plan.

Good to know

  • "status": 1 means the message is queued, not delivered. Sent is the final success state; the API doesn't report whether the message was delivered or read.
  • Send message errors come back with HTTP 400 (429 at the daily limit); Schedule message errors usually come back with HTTP 200 and "status": 0, so read response.json() and check status rather than the HTTP code. The official client raises requests.HTTPError: read the reason with e.response.json()["message"].
  • The official client doesn't cover every endpoint correctly yet: its schedule_message and check_credentials() don't work with the current API. Call /api/v1/schedule_msg/ with requests as shown above, and /api/v1/me/ the same way.
  • Keep the API key on your server, for example in an environment variable. Anyone who has it can send from your numbers, so never put it in browser JavaScript, a mobile app or code you publish.
  • The free trial has 50 messages in any 30 days and 1 number, no card. Paid plans start at $25 a month in the US (your price is on Pricing) and send unlimited messages under fair use: up to 1,000 a day per number.
  • Messages go out from your own WhatsApp number, so WhatsApp's own rules apply: message people who expect to hear from you.

Questions

Is there an official Python library for the WbizTool API?
Yes: wbiztool-client on PyPI (pip install wbiztool-client). Use its send_message and get_message_status. For scheduling and checking credentials, call the endpoints with requests.
How do I send a PDF or an image from Python?
Use msg_type 1 with img_url for an image, or msg_type 2 with file_url for a file. To send a file from disk, post it as multipart form data in a field named file, and set file_name with its extension, such as invoice-4821.pdf.
How do I know the message was sent?
A reply with "status": 1 and a msg_id means it's queued. Pass a webhook URL to get a POST with SENT, FAILED, CANCELLED or EXPIRED, or call the Message status endpoint with the msg_id. Sent is the final state: the API doesn't report delivered or read.
Which phone number format should I send?
Send the number with its country code (919876543210), or without it (9876543210) together with country_code (91). Spaces, +, dashes and brackets are removed for you, so +91 98765-43210 works too.
Do I need the WhatsApp Business API or Meta approval?
No. WbizTool sends from your own WhatsApp or WhatsApp Business number, linked like WhatsApp Web. There's no Meta approval and no message templates to get approved.
Does it cost per message?
No. The free trial includes 50 messages in any 30 days. Paid plans send unlimited messages under fair use, up to 1,000 a day per number: Lite $25, Standard $59 and Advanced $149 a month in the US; Pricing shows your country's price.

Read the guides

Related

Send your first automated WhatsApp message today

Create an account, scan the QR code and send a message in under five minutes.

Start free

Paid plans start at $25 a month in the US. Pricing