> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zeplo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Python SDK

> Integrate Zeplo's WhatsApp Business API into your Python application using the official zeplo package.

# Python SDK

The official Zeplo Python SDK provides a clean, Pythonic interface for the WhatsApp Business API. It supports both synchronous and asynchronous usage.

> [!NOTE]
>
> The SDK requires Python 3.8 or later and ships with full type hints for IDE autocompletion and static analysis with mypy or pyright.

## Installation

**1. Install the package**

```bash theme={null}
pip install zeplo
```

For async support with extra performance:

```bash theme={null}
pip install zeplo[aio]
```

**2. Verify installation**

```python theme={null}
from zeplo import ZeploClient

print("Zeplo SDK loaded successfully")
```

## Initialization

Create a new `ZeploClient` instance with your configuration:

```python theme={null}
import os
from zeplo import ZeploClient

client = ZeploClient(
    api_key=os.environ["ZEPLO_API_KEY"],       # Required
    api_secret=os.environ["ZEPLO_API_SECRET"], # Required
    channel_id=os.environ["ZEPLO_CHANNEL_ID"],  # Required
    base_url="https://zeplo.ai/api/v1",        # Optional
)
```

> [!NOTE]
>
> Store your API key in an environment variable. Never hard-code secrets in your source files.

## Operations

### Messaging

**JavaScript/TypeScript**

```typescript theme={null}
// Send a template message
const templateMessage = await client.messaging.sendTemplate({
  to: "+1234567890",
  templateName: "welcome_message",
  language: "en",
  parameters: ["John", "Order #1234"],
});

// Send a reply to an existing conversation
const reply = await client.messaging.sendReply({
  conversationId: "conv_abc123",
  text: "Thank you for reaching out!",
  attachments: [
    {
      type: "image",
      url: "https://example.com/photo.jpg",
      caption: "Product photo",
    },
  ],
});
```

**Python**

```python theme={null}
# Send a template message
template_message = client.messaging.send_template(
    to="+1234567890",
    template_name="welcome_message",
    language="en",
    parameters=["John", "Order #1234"],
)

print(template_message.message_id)

# Send a reply to an existing conversation
reply = client.messaging.send_reply(
    conversation_id="conv_abc123",
    text="Thank you for reaching out! We will get back to you shortly.",
    attachments=[
        {
            "type": "image",
            "url": "https://example.com/photo.jpg",
            "caption": "Product photo",
        }
    ],
)
```

### Contacts

**JavaScript/TypeScript**

```typescript theme={null}
const contact = await client.contacts.create({
  phone: "+1234567890",
  name: "Jane Smith",
  tags: ["vip", "enterprise"],
  customFields: { company: "Acme Corp" },
});

const contacts = await client.contacts.list({
  limit: 50,
  tags: ["vip"],
  search: "Jane",
});
```

**Python**

```python theme={null}
# Create a new contact
contact = client.contacts.create(
    phone="+1234567890",
    name="Jane Smith",
    tags=["vip", "enterprise"],
    custom_fields={"company": "Acme Corp"},
)

# List contacts with filters
contacts = client.contacts.list(
    limit=50,
    tags=["vip"],
    search="Jane",
)

# Iterate through paginated results
for contact in contacts.data:
    print(f"{contact.name}: {contact.phone}")
```

### Campaigns

**JavaScript/TypeScript**

```typescript theme={null}
const campaign = await client.campaigns.create({
  name: "Summer Sale 2026",
  templateName: "summer_promo",
  segmentIds: ["seg_abc123"],
  scheduledAt: "2026-06-01T09:00:00Z",
});
```

**Python**

```python theme={null}
# Create a campaign
campaign = client.campaigns.create(
    name="Summer Sale 2026",
    template_name="summer_promo",
    segment_ids=["seg_abc123", "seg_def456"],
    scheduled_at="2026-06-01T09:00:00Z",
    language="en",
)

# Launch the campaign immediately
client.campaigns.launch(campaign.id)

# Get campaign analytics
stats = client.campaigns.get_stats(campaign.id)
print(f"Sent: {stats.sent}, Delivered: {stats.delivered}")
```

### Webhooks

**JavaScript/TypeScript**

```typescript theme={null}
const webhook = await client.webhooks.create({
  url: "https://yourapp.com/webhooks/zeplo",
  events: ["message.received", "message.delivered"],
  secret: "whsec_abc123...",
});
```

**Python**

```python theme={null}
# Register a webhook endpoint
webhook = client.webhooks.create(
    url="https://yourapp.com/webhooks/zeplo",
    events=["message.received", "message.delivered", "conversation.opened"],
    secret="whsec_abc123...",
)

# List existing webhooks
webhooks = client.webhooks.list()

# Verify a webhook signature (Flask example)
from zeplo import verify_webhook_signature

is_valid = verify_webhook_signature(
    request.data,
    request.headers.get("X-Zeplo-Signature"),
    "whsec_abc123...",
)
```

## Error Handling

All SDK errors inherit from `ZeploError`. Use specific exception classes to handle different failure modes:

```python theme={null}
from zeplo import (
    ZeploError,
    ZeploAuthenticationError,
    ZeploRateLimitError,
    ZeploValidationError,
    ZeploNotFoundError,
)

try:
    message = client.messaging.send_template(
        to="+1234567890",
        template_name="welcome_message",
        language="en",
    )
except ZeploAuthenticationError as e:
    print(f"Invalid API key: {e.message}")
except ZeploRateLimitError as e:
    print(f"Rate limited. Retry after: {e.retry_after} seconds")
except ZeploValidationError as e:
    print(f"Validation failed: {e.details}")
except ZeploNotFoundError as e:
    print(f"Resource not found: {e.resource_id}")
except ZeploError as e:
    print(f"Zeplo error [{e.code}]: {e.message}")
```

> [!WARNING]
>
> `ZeploRateLimitError` includes a `retry_after` property (in seconds). Implement exponential backoff rather than retrying immediately.

## Async Support

The SDK provides a fully asynchronous client for high-concurrency workloads. Async support uses `aiohttp` under the hood.

```python theme={null}
import asyncio
import os
from zeplo import AsyncZeploClient

async def main():
    async with AsyncZeploClient(
        api_key=os.environ["ZEPLO_API_KEY"],
        api_secret=os.environ["ZEPLO_API_SECRET"],
        channel_id=os.environ["ZEPLO_CHANNEL_ID"],
    ) as client:
        # Send multiple messages concurrently
        tasks = [
            client.messaging.send_template(
                to=phone,
                template_name="welcome_message",
                language="en",
                parameters=[name],
            )
            for phone, name in [
                ("+1234567890", "Alice"),
                ("+1987654321", "Bob"),
                ("+1555000000", "Charlie"),
            ]
        ]

        results = await asyncio.gather(*tasks)
        for result in results:
            print(f"Sent message: {result.message_id}")

asyncio.run(main())
```

> [!NOTE]
>
> The `AsyncZeploClient` implements the async context manager protocol. Always use `async with` to ensure connections are properly cleaned up.

### Async Error Handling

```python theme={null}
from zeplo import AsyncZeploClient, ZeploRateLimitError

async def safe_send(client: AsyncZeploClient, **kwargs):
    try:
        return await client.messaging.send_template(**kwargs)
    except ZeploRateLimitError as e:
        await asyncio.sleep(e.retry_after)
        return await client.messaging.send_template(**kwargs)
```

## FAQ

> **What Python versions are supported?**
>
> The SDK supports Python 3.8, 3.9, 3.10, 3.11, 3.12, and 3.13. We test against all supported versions in CI. If you are on an earlier version, we recommend upgrading to receive security patches.

> **How do I use async mode?**
>
> Install the SDK with the `aio` extra (`pip install zeplo[aio]`), then import `AsyncZeploClient` instead of `ZeploClient`. All methods on the async client return coroutines that you can `await`. Use `asyncio.run()` as the entry point for your async code.

> **Does the SDK provide type hints?**
>
> Yes. All public APIs are annotated with type hints compatible with mypy and pyright in strict mode. No additional stub packages are needed.

> **Are requests retried automatically?**
>
> By default, the SDK retries failed requests up to 3 times with exponential backoff. Customize this through the client configuration:
>
> ```python theme={null}
> client = ZeploClient(
>     api_key=os.environ["ZEPLO_API_KEY"],
>     api_secret=os.environ["ZEPLO_API_SECRET"],
>     channel_id=os.environ["ZEPLO_CHANNEL_ID"],
>     max_retries=5,
>     retry_delay=1.0,  # base delay in seconds
> )
> ```

> **How do I enable logging?**
>
> The SDK uses Python's standard `logging` module under the `zeplo` namespace. Enable debug logging to see request and response details:
>
> ```python theme={null}
> import logging
>
> logging.basicConfig(level=logging.DEBUG)
> logging.getLogger("zeplo").setLevel(logging.DEBUG)
> ```

## Next Steps

> **API Reference**
>
> Browse the full REST API endpoints, parameters, and response schemas.

> **JavaScript SDK**
>
> Use the official JavaScript/TypeScript SDK for frontend and Node.js projects.

> **Webhooks**
>
> Set up real-time event notifications for incoming messages and status updates.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.