Metadata-Version: 2.4
Name: simplymsg
Version: 0.1.0
Summary: Official Python SDK for SimplyMsg — WhatsApp messaging API
Project-URL: Homepage, https://simplymsg.com
Project-URL: Documentation, https://simplymsg.com/docs
Project-URL: Repository, https://github.com/AymanTechGlobal/simplymsg
Project-URL: Issues, https://github.com/AymanTechGlobal/simplymsg/issues
Author-email: SimplyMsg <support@simplymsg.com>
License: MIT
License-File: LICENSE
Keywords: api,messaging,sdk,webhooks,whatsapp
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Communications :: Chat
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: httpx>=0.25.0
Provides-Extra: dev
Requires-Dist: mypy>=1.5; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
Requires-Dist: pytest>=7.4; extra == 'dev'
Requires-Dist: respx>=0.20; extra == 'dev'
Requires-Dist: ruff>=0.1; extra == 'dev'
Description-Content-Type: text/markdown

# simplymsg

Official Python SDK for [SimplyMsg](https://simplymsg.com) — the WhatsApp messaging API for developers.

```bash
pip install simplymsg
```

## Quickstart

```python
from simplymsg import SimplyMsg

client = SimplyMsg(api_key="wsk_...")

result = client.messages.send(
    session_id="sess_abc123",
    to="14155551234",
    type="text",
    message="Your code is 4821",
)

print(result["messageId"])  # "msg_a82f7c4e"
```

## Features

- **Sync + async** — `SimplyMsg` and `AsyncSimplyMsg`, same API surface.
- **Type-hinted** — full type coverage; works with `mypy --strict`.
- **One dependency** — `httpx` only.
- **Idempotency keys** — replay-safe sends.
- **Typed errors** — catch `RateLimitError`, `AuthenticationError`, etc.
- **Webhook verification** — built-in HMAC-SHA256 helper.

## Sending messages

### Text

```python
client.messages.send(
    session_id="sess_abc",
    to="14155551234",
    type="text",
    message="Hello!",
)
```

### Image / video / audio / document

```python
client.messages.send(
    session_id="sess_abc",
    to="14155551234",
    type="image",
    media_url="https://example.com/cat.jpg",
    caption="Look at this cat",
)
```

### Location

```python
client.messages.send(
    session_id="sess_abc",
    to="14155551234",
    type="location",
    latitude=37.7749,
    longitude=-122.4194,
    name="Coit Tower",
)
```

### Idempotent sends

```python
client.messages.send(
    session_id=session_id,
    to=phone,
    type="text",
    message="Hello",
    idempotency_key="order-#A82F",
)
```

## Async

```python
import asyncio
from simplymsg import AsyncSimplyMsg

async def main():
    async with AsyncSimplyMsg(api_key="wsk_...") as client:
        result = await client.messages.send(
            session_id="sess_abc",
            to="14155551234",
            type="text",
            message="Async hello",
        )
        print(result["messageId"])

asyncio.run(main())
```

## Bulk sends (Enterprise)

```python
batch = client.messages.send_bulk(
    session_id="sess_abc",
    messages=[
        {"to": "14155551111", "type": "text", "message": "Hi customer 1"},
        {"to": "14155552222", "type": "text", "message": "Hi customer 2"},
    ],
)

status = client.messages.batch(batch["batchId"])
print(status["processed"], "/", status["total"])
```

## Webhooks

### Configure

```python
webhook = client.webhooks.create(
    url="https://your-app.com/wa/status",
    events=["message.delivered", "message.failed", "session.disconnected"],
)
print(webhook["secret"])  # save this!
```

### Verify incoming webhooks (Flask example)

```python
import os
from flask import Flask, request, abort, jsonify
from simplymsg import SimplyMsg

app = Flask(__name__)
SECRET = os.environ["SIMPLY_WEBHOOK_SECRET"]

@app.post("/wa/status")
def status_webhook():
    raw = request.get_data()  # raw bytes — don't use request.json
    sig = request.headers.get("X-Webhook-Signature", "")

    if not SimplyMsg.verify_webhook(raw, sig, SECRET):
        abort(401)

    event = request.json
    print(event["event"], event["data"])
    return jsonify(ok=True)
```

### Event types

- `message.sent` — accepted by WhatsApp's servers
- `message.delivered` — landed on recipient device
- `message.read` — recipient opened it
- `message.failed` — permanent failure
- `session.connected` / `session.disconnected` / `session.qr_ready` / `session.logged_out`
- `batch.started` / `batch.progress` / `batch.completed` / `batch.failed`

## Error handling

```python
from simplymsg import (
    SimplyMsg,
    AuthenticationError,
    RateLimitError,
    NetworkError,
)

try:
    client.messages.send(...)
except AuthenticationError:
    print("Bad API key")
except RateLimitError as e:
    print(f"Rate limited; retry after {e.retry_after}s")
except NetworkError:
    print("Connection failed")
```

## Configuration

```python
client = SimplyMsg(
    api_key="wsk_...",
    base_url="https://simplymsg.com",   # default
    timeout=30.0,                        # default: 30s
    user_agent="my-app/1.0.0",          # optional
)
```

## Requirements

- Python ≥ 3.9
- `httpx` ≥ 0.25

## License

MIT
