Official Python SDK for the VZaps public API.
Project description
VZaps Python SDK
Official Python client for the VZaps public API. Send WhatsApp messages, manage instances, configure webhooks, and subscribe to realtime events with a resource-oriented, sync and async interface.
Works in Python 3.10+. HTTP uses httpx; WebSocket realtime uses websockets.
Table of contents
- Features
- Requirements
- Installation
- Quick start
- Authentication
- Client options
- Resources
- Instance tokens
- Webhooks
- Realtime events
- Error handling
- Python
- Documentation
Features
- Automatic JWT handling — exchanges
client_token+client_secretfor a bearer token and refreshes it before expiry. - Resource-oriented API —
instances,messages,webhooks,contacts,groups, andeventsmirror the public HTTP contract. - Sync and async clients —
VZapsClientandAsyncVZapsClientshare the same resource surface. - Realtime WebSocket client — subscribe to instance events with reconnect, resume (
last_event_id), and server-side ack. - Instance token support — pass
instance_tokenon each instance-scoped request. - Extensible transport — inject a custom
httpx.Clientorhttpx.AsyncClientfor tests or custom runtimes.
Requirements
| Runtime | Minimum version |
|---|---|
| Python | 3.10+ |
The SDK uses httpx for HTTP. No extra HTTP dependency is required beyond the package itself.
Installation
pip install vzaps
Quick start
Create credentials in the VZaps dashboard (client_token and client_secret), then send a text message:
from vzaps import VZapsClient
with VZapsClient(
client_token="your-client-token",
client_secret="your-client-secret",
) as client:
client.messages.send_text(
instance_id="VZKB8AU4S4CWY1SLXX4I5WJGRZQMDDFTV6",
instance_token="instance-token",
phone="5511999999999",
message="Hello from VZaps",
)
Async equivalent:
from vzaps import AsyncVZapsClient
async with AsyncVZapsClient(
client_token="your-client-token",
client_secret="your-client-secret",
) as client:
await client.messages.send_text(
instance_id="VZKB8AU4S4CWY1SLXX4I5WJGRZQMDDFTV6",
instance_token="instance-token",
phone="5511999999999",
message="Hello from VZaps",
)
Authentication
VZaps uses a two-step model:
- Account credentials —
client_tokenandclient_secretidentify your integration. The SDK callsPOST /tokenand caches the JWT. - Instance token — instance-scoped routes also require
X-Instance-Token. Pass it on each instance-scoped request (see Instance tokens).
Every authenticated HTTP request sends:
| Header | Value |
|---|---|
Authorization |
Bearer <jwt> |
X-Client-Token |
Your client token |
X-Instance-Token |
Instance token, on instance-scoped requests |
You rarely need to call auth.get_access_token() directly — resources attach the token for you. Use it when integrating with custom HTTP logic:
token = client.auth.get_access_token()
Client options
Pass options to VZapsClient(...) or AsyncVZapsClient(...):
| Option | Type | Default | Description |
|---|---|---|---|
client_token |
str |
— | Required. Public client token from the dashboard. |
client_secret |
str |
— | Required. Client secret used to obtain JWTs. |
timeout |
float | httpx.Timeout |
30.0 |
HTTP request timeout in seconds. |
token_skew_seconds |
float |
60.0 |
Refresh JWT this many seconds before expiry. |
limits |
httpx.Limits |
— | Optional httpx connection pool limits. |
user_agent |
str |
package default | Optional User-Agent header on HTTP requests. |
http_client |
httpx.Client | httpx.AsyncClient |
— | Custom httpx client (tests, proxies, tracing). |
Resources
The client exposes namespaced resources. Responses are decoded as Python objects (typically dict/list) so you can align with the OpenAPI schema.
client.instances
| Method | HTTP | Description |
|---|---|---|
create(request?) |
PUT /instances/create |
Create a WhatsApp instance. |
list(request?) |
POST /instances/list |
List instances (pagination, search, sort). |
get(instance_id) |
POST /instances/get |
Get instance details. |
update(instance_id, request?, *, instance_token?) |
PATCH /instances/:id |
Update instance settings. |
restart(instance_id, *, instance_token?) |
POST /instances/:id/restart |
Restart instance runtime. |
client.messages
client.messages wraps the public WhatsApp send and chat endpoints. The most common calls are shown below; the SDK also exposes the other public message operations documented in the API reference, including media, interactive messages, reactions, polls, downloads, edits, deletes, presence, and read receipts.
client.messages.send_text(
instance_id="VZ...",
instance_token="instance-token",
phone="5511999999999",
message="Hello",
)
client.messages.send_image(
instance_id="VZ...",
instance_token="instance-token",
phone="5511999999999",
image="https://example.com/photo.jpg",
caption="Check this out",
)
Available send helpers include send_text, send_image, send_audio, send_document, send_video, send_sticker, send_gif, send_location, send_contact, send_buttons, send_list, send_link, and send_poll. See the API documentation for complete payload examples.
client.webhooks
| Method | HTTP | Description |
|---|---|---|
get(instance_id, *, instance_token?) |
GET /instances/:id/webhook |
Read current webhook configuration. |
set(request) |
POST /instances/:id/webhook |
Configure webhook URL and subscribed events. |
client.contacts
| Method | HTTP | Description |
|---|---|---|
list(instance_id, *, instance_token?) |
GET /instances/:id/contact/list |
List contacts for the instance. |
add(request) |
POST /instances/:id/contact/add |
Add a contact. |
client.groups
| Method | HTTP | Description |
|---|---|---|
list(request) |
GET /instances/:id/group/list |
List groups (paginated). |
get(request) |
GET /instances/:id/group/info |
Get group metadata by group_id. |
client.sessions
| Method | HTTP | Description |
|---|---|---|
status(instance_id, *, instance_token=...) |
GET /instances/:id/session/status |
Check WhatsApp login state and, when connected, live profile fields. |
GET /instances/{id}/session/status returns SessionStatusResponse. When data.connected is true, data includes (in order) phone, whatsapp_jid, push_name, business_name, business_profile, profile_picture_id, profile_picture_url, profile_url, and optional verified_name, about, website. When disconnected, data only has connected=False.
Other public namespaces are available as first-class resources too: sessions, users, queues, typebots, chatwoot, and chats.
client.request(method, path, ...)
Escape hatch for advanced calls or newly released endpoints:
instance = client.request(
"POST",
"/instances/get",
body={"id": "VZ..."},
)
Instance tokens
Instance-scoped routes require the instance token in addition to account credentials. Pass it on each request that targets an instance:
client.messages.send_text(
instance_id="VZ...",
instance_token="instance-token",
phone="5511999999999",
message="Hello",
)
Webhooks
Configure HTTP callbacks for instance events (same payload shape as realtime data, delivered to your URL):
client.webhooks.set(
instance_id="VZ...",
instance_token="instance-token",
webhook_url="https://example.com/webhooks/vzaps",
events=["Message", "Connected", "Disconnected"],
)
Common event types: Message, ReadReceipt, Connected, Disconnected, Presence, ChatPresence, HistorySync, GroupParticipantsAdd, GroupParticipantsRemove, or All.
Event payloads (webhook and realtime) use snake_case, matching the platform. Incoming media events include media_url inside data when platform storage is available.
Realtime events
Subscribe to the same events over the VZaps realtime WebSocket. This is the recommended path for in-app notifications, bots, and dashboards that need low-latency delivery without exposing a public webhook URL.
Realtime subscriptions are async-first. Use AsyncVZapsClient and async with client.events.subscribe(...):
async with AsyncVZapsClient(
client_token="...",
client_secret="...",
) as client:
async with client.events.subscribe(
instance_id="VZ...",
instance_token="instance-token",
events=["Message", "Connected", "Disconnected"],
reconnect=True,
last_event_id="evt_previous_id", # optional resume after disconnect
) as sub:
@sub.on_open
async def on_open() -> None:
print("Connected to realtime")
@sub.on("Message")
async def on_message(event) -> None:
print(event.data)
@sub.on_error
async def on_error(error) -> None:
print(error)
await sub.wait_closed()
Event envelope
Each WebSocket message keeps the platform shape (snake_case):
{
"id": "evt_…",
"type": "Message",
"instance_id": "VZ…",
"created_at": "2026-06-23T22:57:17.000Z",
"data": {
"type": "Message",
"event": { },
"media_url": "https://…"
}
}
data— same payload as webhook delivery (snake_case).media_url— present on incoming media messages when platform storage is available.
Delivery and ack
Delivery is at-least-once. After your handler runs, the SDK sends an ack automatically on the WebSocket connection. Use last_event_id when reconnecting if you need to reduce gaps. Deduplicate on event.id in your application if you process events idempotently.
Subscribe options
| Option | Type | Default | Description |
|---|---|---|---|
instance_id |
str |
— | Required. Instance to watch. |
events |
list[str] |
all subscribed | Comma-filtered event types. |
instance_token |
str |
— | Required. Instance token for authorization. |
reconnect |
bool |
True |
Reconnect after socket close. |
max_retries |
int |
unlimited | Max reconnect attempts. |
retry_delay_seconds |
float |
1.0 |
Delay between reconnects. |
last_event_id |
str |
— | Resume cursor after disconnect. |
Handler registration
| Method | When it fires |
|---|---|
on_open(...) |
WebSocket connected. |
on_close(...) |
WebSocket closed. |
on_error(...) |
Handler or transport error. |
on("Message", ...) |
Matching realtime event type. |
on("All", ...) |
Every event type. |
Error handling
The SDK raises typed exceptions you can catch and branch on:
| Class | When |
|---|---|
VZapsError |
Base class; HTTP errors include status_code, code, and details. |
VZapsAuthenticationError |
Invalid client_token / client_secret (401). |
VZapsTimeoutError |
Request exceeded timeout. |
VZapsRateLimitError |
Rate limited (429). |
VZapsAPIError |
Other non-2xx API responses. |
VZapsRealtimeError |
Realtime handler or transport failures. |
from vzaps import (
VZapsAPIError,
VZapsAuthenticationError,
VZapsError,
VZapsRateLimitError,
VZapsTimeoutError,
)
try:
client.messages.send_text(
instance_id="VZ...",
instance_token="instance-token",
phone="5511999999999",
message="Hello",
)
except VZapsAuthenticationError:
print("Check client credentials")
except VZapsTimeoutError:
print("Request timed out")
except VZapsRateLimitError:
print("Rate limited")
except VZapsAPIError as exc:
print(exc.status_code, exc.message, exc.details)
except VZapsError:
raise
Python
The package uses snake_case for Python APIs and request keyword arguments. Realtime and webhook event payloads stay in snake_case so both delivery channels match the platform wire format.
Resources accept dict payloads and keyword arguments, which makes it easy to pass newly released API fields before typed helpers are added:
client.messages.send_image(
instance_id="VZ...",
instance_token="instance-token",
phone="5511999999999",
image="https://example.com/photo.jpg",
caption="Check this out",
)
page = client.instances.list(page=1, size=20, search="support")
Use client.request(...) when you need full control over method, path, and body.
Documentation
License
MIT © VZaps
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vzaps-0.1.1.tar.gz.
File metadata
- Download URL: vzaps-0.1.1.tar.gz
- Upload date:
- Size: 21.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d7ed1f231fdc7314297aa46c1ddba009d372b1d7ead8067dcfd131afaac06e68
|
|
| MD5 |
2750008efd435dfc24165a9aab1de7f5
|
|
| BLAKE2b-256 |
18aa3ff5894ea78524081bb34a62559c0e480787b442279fbac111e2317fd328
|
Provenance
The following attestation bundles were made for vzaps-0.1.1.tar.gz:
Publisher:
release.yml on VZaps/vzaps-sdk-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vzaps-0.1.1.tar.gz -
Subject digest:
d7ed1f231fdc7314297aa46c1ddba009d372b1d7ead8067dcfd131afaac06e68 - Sigstore transparency entry: 1995811945
- Sigstore integration time:
-
Permalink:
VZaps/vzaps-sdk-python@acde0d96db7ac48278543733548290eac4bf8f09 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/VZaps
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@acde0d96db7ac48278543733548290eac4bf8f09 -
Trigger Event:
push
-
Statement type:
File details
Details for the file vzaps-0.1.1-py3-none-any.whl.
File metadata
- Download URL: vzaps-0.1.1-py3-none-any.whl
- Upload date:
- Size: 24.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed35909cef49f262f932faeb8163e288014a5fd009acf88108773b73bcb78635
|
|
| MD5 |
08574a98533c9c0d6b0a5e61f91923c6
|
|
| BLAKE2b-256 |
37292296508d12a886ca2ead1ca56461678eb623d8c4a95f7cb734084026d37d
|
Provenance
The following attestation bundles were made for vzaps-0.1.1-py3-none-any.whl:
Publisher:
release.yml on VZaps/vzaps-sdk-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vzaps-0.1.1-py3-none-any.whl -
Subject digest:
ed35909cef49f262f932faeb8163e288014a5fd009acf88108773b73bcb78635 - Sigstore transparency entry: 1995812008
- Sigstore integration time:
-
Permalink:
VZaps/vzaps-sdk-python@acde0d96db7ac48278543733548290eac4bf8f09 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/VZaps
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@acde0d96db7ac48278543733548290eac4bf8f09 -
Trigger Event:
push
-
Statement type: