WaAPI Python SDK
Official Python client for the WaAPI REST API — send and receive WhatsApp messages, manage chats, groups and channels from Python.
pip install waapi
Quick start
from waapi import WaAPI
client = WaAPI(token="YOUR_API_TOKEN", instance_id=123)
client.send_message(
chat_id="4915112345678@c.us",
message="Deployment finished.",
)
Get a token at waapi.app/user/api-tokens and create an instance connected to your number.
The chat ID is the one thing to get right
Its suffix decides where the message lands, and a wrong suffix is accepted and delivers nothing:
| Target | Format |
|---|---|
| One person | 4915112345678@c.us |
| Group | 123456789-123456789@g.us |
| Channel | 123456789@newsletter |
Async
Same method names, awaited:
from waapi import AsyncWaAPI
async with AsyncWaAPI(token="YOUR_API_TOKEN", instance_id=123) as client:
await client.send_message(chat_id="4915112345678@c.us", message="Hi")
Errors
A successful HTTP exchange is not proof the message was sent. The API carries two envelopes:
| Field | Answers |
|---|---|
status |
did the request reach the instance |
data.status |
did the instance carry the action out |
The inner one is authoritative. A malformed chat ID comes back as
{"status": "success", "data": {"status": "error", …}} — nothing was sent. The
SDK raises FailedActionError on either envelope, so neither case reaches you
looking like success.
from waapi import WaAPI, FailedActionError, AuthenticationError, RateLimitError
try:
client.send_message(chat_id="4915112345678@c.us", message="Hi")
except AuthenticationError:
... # token wrong, expired, or missing scopes
except RateLimitError as e:
time.sleep(e.retry_after or 5)
except FailedActionError as e:
... # accepted but not carried out — e.response has the detail
| Exception | Raised on |
|---|---|
AuthenticationError |
HTTP 401, 403 |
NotFoundError |
HTTP 404 |
ValidationError |
HTTP 422 — .errors holds the field errors |
RateLimitError |
HTTP 429 — .retry_after in seconds when the API sends it |
FailedActionError |
HTTP 400, and HTTP 200 with status: error |
ServerError |
HTTP 5xx |
All inherit from WaAPIError.
Coverage
All 122 client actions are wrapped, typed, and available on both clients:
client.create_group(group_name="Ops", group_participants=["4915112345678@c.us"])
client.send_media(chat_id="4915112345678@c.us", media_url="https://example.com/report.pdf")
client.get_contacts()
They are generated from the same OpenAPI specification the n8n node and the MCP tools come from, so they track the API instead of drifting behind it — see CONTRIBUTING.md.
An action added to the API since the last release is still reachable by name:
client.action("some-new-action", {"chatId": "4915112345678@c.us"})
Configuration
WaAPI(
token="...", # required
instance_id=123, # optional; per-call instance_id overrides it
base_url="https://waapi.app/api/v1",
timeout=30.0,
)
Passing instance_id to the client keeps single-instance code short. Any call
can still override it, and a call with neither raises before a request is sent.
Development
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest
The suite runs entirely against httpx.MockTransport — no network, no token,
no connected account.
License
MIT. Not affiliated with, endorsed or sponsored by WhatsApp LLC or Meta. WhatsApp is a trademark of WhatsApp LLC.
Metadata
Release files for waapi 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| waapi-0.1.2.tar.gz | 27.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| waapi-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 47.5 kB
Release files / waapi-0.1.2.tar.gz
| Download URL | waapi-0.1.2.tar.gz |
|---|---|
| Size | 27.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fda8d665ab5949a1eeedce03580e8454614731e01007784bb8da8138e118ed98
|
|
BLAKE2b-256 checksum How to use checksums |
964661a6ee685b13dcba0b1fc1f78eed23ae83ffa74c50a0c4f7524e79bb3a3e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.
Transparency logRelease files / waapi-0.1.2-py3-none-any.whl
| Download URL | waapi-0.1.2-py3-none-any.whl |
|---|---|
| Size | 20.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
801c415f867bfc3babbb84fb2a3bfecbe20bf2c3d7e2756c561ce887fa539f49
|
|
BLAKE2b-256 checksum How to use checksums |
fcab42691c980a850e9474cc6da6d3d7176f82ddbc6b9dc64eed9e280fa46ce5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.
Transparency log