Skip to main content

izap

The Python SDK for the iZap API: WhatsApp messages, templates, chats, transmissions and webhooks for your business.

  • Typed request and response models, generated from iZap's public OpenAPI schema
  • Sync and asyncio calls through one client
  • Retries with backoff for idempotent requests, and one exception type for API errors
  • Webhook signature verification

Requires Python 3.11 or newer. Python 3.10 is not supported: it reaches end of life in October 2026, and 3.11 is the floor of the code generator the SDK is built with.

pip install izap

Authentication

The SDK authenticates with a personal access token. Create one in the iZap dashboard under User Settings → API Keys, which is available on plans that include the REST API. Tokens start with izap_pat_ and are shown once, so store yours as a secret.

Business-scoped endpoints act on the business selected by the business-id header rather than a path parameter. Pass it once on the client:

import os

import izap

client = izap.Client(os.environ["IZAP_TOKEN"], business_id=os.environ["IZAP_BUSINESS_ID"])

client.with_business(other_id) returns a copy scoped to another business, and passing business_id directly to an endpoint function overrides the client for that call.

Quickstart

Endpoint functions live in izap.api, one module per API area, and models in izap.models. Each endpoint has four functions: sync, sync_detailed (which also returns the status code and headers), asyncio and asyncio_detailed.

List WhatsApp templates

from izap.api.whatsapp_templates import list_whats_app_templates

with client:
    templates = list_whats_app_templates.sync(client=client, status="approved")
    for template in templates.templates:
        print(template.name, template.language)

Send a message

from izap.api.chats import list_current_business_chats
from izap.api.messages import send_chat_message
from izap.models import CreateMessageIn

with client:
    chats = list_current_business_chats.sync(client=client, kind="real", page_size=1)
    chat = chats.chats[0]
    sent = send_chat_message.sync(chat.id, client=client, body=CreateMessageIn(content="Your order is on its way"))
    print(sent.user_message.id)

send_chat_message sends as a human agent, and the assistant does not reply to it. examples/quickstart.py runs both steps from the command line.

Async

import asyncio

import izap
from izap.api.whatsapp_templates import list_whats_app_templates


async def main() -> None:
    async with izap.AsyncClient(token, business_id=business_id) as client:
        templates = await list_whats_app_templates.asyncio(client=client)


asyncio.run(main())

Errors

Every 4xx and 5xx response raises izap.IzapApiError:

try:
    send_chat_message.sync(chat_id, client=client, body=CreateMessageIn(content="Hi"))
except izap.IzapApiError as error:
    print(error.status, error.code, error.message)
Attribute Contents
status The HTTP status code
code The machine-readable code when the API sends one, e.g. plan_limit_event_webhooks
message A human-readable summary
detail The raw detail: a string, a {code, message} object, or a 422's validation errors
response The httpx.Response

A successful response whose status the schema does not document returns None.

Retries and timeouts

GET, HEAD, OPTIONS, PUT and DELETE requests answered with 429, 502, 503 or 504 are retried up to max_retries times (default 2). The client waits as long as Retry-After asks, up to 60 seconds, and otherwise backs off exponentially from 0.5 seconds. POST and PATCH are never retried. timeout (default 30 seconds) applies to each attempt.

import httpx

client = izap.Client(token, max_retries=4, timeout=10.0, transport=httpx.HTTPTransport(proxy="http://proxy:3128"))

Webhooks

iZap signs every webhook delivery. Verify it against the raw request body before you trust it:

import os

from flask import Flask, request

import izap

app = Flask(__name__)


@app.post("/hooks/izap")
def izap_webhook():
    try:
        event = izap.webhooks.verify(request.get_data(), request.headers, os.environ["IZAP_WEBHOOK_SECRET"])
    except izap.WebhookVerificationError:
        return "", 400
    if event.type == "message.received":
        handle_message(event.id, event.data["message"])
    return "", 204

Every delivery carries both izap-webhook-signature (v1) and the stronger izap-webhook-signature-v2, which also covers the delivery id and closes a replay gap in v1. verify requires v2 by default. Pass allow_v1=True only for senders from before v2 existed; when both headers are present, v2 alone decides. It also rejects a delivery whose timestamp is more than tolerance seconds (default 300) from now, and returns a WebhookEvent with id, type, timestamp and the parsed data. Retries and resends of a delivery keep the same event.id, so use it to process each one once. examples/webhook_receiver.py is a receiver built on the standard library, and the webhook guide covers registering endpoints and the event catalog.

API reference

The modules in izap.api follow the API reference: api_tokens, business_library, businesses, chats, menus, messages, transmissions, webhooks, whatsapp_cloud and whatsapp_templates. Each function's docstring describes its parameters and result.

Development

This package lives in the iZap monorepo under sdk/python, as a standalone uv project.

uv sync
uv run python scripts/generate.py --check   # regenerate from the schema snapshot, fail on drift
uv run ruff check && uv run ruff format --check && uv run ty check
uv run pytest
bash scripts/ci.sh                          # all of the above, plus the tests on Python 3.11

src/izap/_generated/ is generated by openapi-python-client, pinned in pyproject.toml, from openapi/izap-public.json, a vendored copy of iZap's public OpenAPI schema. Do not edit it by hand. uv run python scripts/sync_schema.py refreshes the snapshot from the monorepo's doc/external/devdocs/api-reference/openapi.json (or from IZAP_OPENAPI_INPUT), and uv run python scripts/generate.py regenerates from it; commit both. Before generating, the script declares path parameters the schema leaves undeclared, makes the business-id header an optional string and drops error responses; its docstrings explain why.

The webhook vectors in tests/fixtures/webhook_vectors.json are signed by the backend's own signer, so the tests pin the SDK to what the server sends. Regenerate them with scripts/webhook_vectors.py.

License

MIT

Metadata

Release files for izap 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for izap 0.3.0
File Size Uploaded Provenance
izap-0.3.0.tar.gz 79.2 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for izap 0.3.0
File Interpreter ABI Platform
izap-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 314.9 kB

Release files / izap-0.3.0.tar.gz

Download URL izap-0.3.0.tar.gz
Size 79.2 kB
Tags Source
SHA-256 checksum
How to use checksums
7097c1a39552c50ea98bfc30e87bc250b724543bbc6e9a62f9861b2c440c3b53
BLAKE2b-256 checksum
How to use checksums
9bfbf9dc1f6a37efac1f964c891370acda0cd75926a38eab02b7f7ced61653c4
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 Oct 15, 2026.

Transparency log

Release files / izap-0.3.0-py3-none-any.whl

Download URL izap-0.3.0-py3-none-any.whl
Size 235.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4a28684aaca24ea12447497f8e378cc69c88d5846a124d96f2c71dc81804f9dd
BLAKE2b-256 checksum
How to use checksums
a8eff696237fd58783251b848d0bfd746178b931e4103f473b7eaedd18e1355d
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 Oct 15, 2026.

Transparency log

Security for izap 0.3.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for izap-0.3.0.tar.gz

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 Oct 15, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page