4ce4204b6c
CI / Lint (push) Failing after 2s
CI / Build (push) Has been skipped
SDK CI / PHP SDK (push) Failing after 1s
Split PHP SDK / PHP SDK tests (push) Failing after 1s
CI / Test (push) Failing after 1s
CI / Dashboard (push) Failing after 0s
SDK CI / JavaScript SDK (push) Failing after 0s
SDK CI / Python SDK (push) Failing after 2s
SDK CI / Java SDK (push) Failing after 1s
Split PHP SDK / Mirror sdk/php -> rmyndharis/openwa-php (push) Has been skipped
CI / Test (PostgreSQL migrations) (push) Failing after 7m47s
CI / Docker Build (push) Has been skipped
94 lines
2.8 KiB
Markdown
94 lines
2.8 KiB
Markdown
# rmyndharis-openwa
|
|
|
|
Official Python SDK for the [OpenWA](https://github.com/rmyndharis/OpenWA) WhatsApp API Gateway.
|
|
|
|
A synchronous client built on [httpx](https://www.python-httpx.org/), with bundled type hints (PEP 561).
|
|
|
|
## Install
|
|
|
|
```bash
|
|
pip install rmyndharis-openwa
|
|
```
|
|
|
|
Requires Python 3.9+. The importable module is `openwa`.
|
|
|
|
## Usage
|
|
|
|
```python
|
|
from openwa import OpenWAClient
|
|
|
|
client = OpenWAClient(
|
|
base_url="https://your-gateway.example.com",
|
|
api_key="owa_k1_…",
|
|
)
|
|
|
|
client.sessions.start("my-session")
|
|
|
|
result = client.messages.send_text("my-session", {
|
|
"chatId": "628123456789@c.us",
|
|
"text": "Hello from the OpenWA Python SDK!",
|
|
})
|
|
print(result["messageId"])
|
|
```
|
|
|
|
The client is also a context manager (it closes the underlying connection pool on exit):
|
|
|
|
```python
|
|
with OpenWAClient(base_url="…", api_key="…") as client:
|
|
client.messages.send_text("my-session", {"chatId": "…@c.us", "text": "hi"})
|
|
```
|
|
|
|
For tests, pass an httpx transport — no global monkey-patching required:
|
|
|
|
```python
|
|
import httpx
|
|
client = OpenWAClient(base_url="…", api_key="…", transport=httpx.MockTransport(handler))
|
|
```
|
|
|
|
## Search
|
|
|
|
`GET /search` is wrapped as `client.search.search(params)`. Only `q` is required;
|
|
the rest (`sessionId`, `chatId`, `direction`, `type`, `from`, `dateFrom`,
|
|
`dateTo`, `limit`, `offset`) are optional. `dateFrom` / `dateTo` are epoch-ms.
|
|
The active search provider (built-in DB full-text, or a plugin) answers; if none
|
|
is configured the server returns 501.
|
|
|
|
```python
|
|
res = client.search.search({"q": "invoice", "sessionId": "my-session", "limit": 20})
|
|
for hit in res["hits"]:
|
|
print(hit["snippet"], hit["score"])
|
|
```
|
|
|
|
## Messaging
|
|
|
|
> Voice notes: pass `ptt=True` inside the body dict to `send_audio` to send a real WhatsApp voice note (PTT). Supply `audio/ogg; codecs=opus` audio for reliable playback; the server defaults the mimetype to that when `ptt` is set without one.
|
|
|
|
## Errors
|
|
|
|
A non-2xx response raises a typed `OpenWAApiError` subclass — `OpenWAAuthError` (401),
|
|
`OpenWAForbiddenError` (403), `OpenWANotFoundError` (404), `OpenWAConflictError` (409),
|
|
`OpenWARateLimitError` (429), `OpenWANotImplementedError` (501) — each carrying `.status`
|
|
and the parsed `.body`. A timeout raises `OpenWATimeoutError`.
|
|
|
|
```python
|
|
from openwa import OpenWANotFoundError
|
|
|
|
try:
|
|
client.sessions.get("missing")
|
|
except OpenWANotFoundError as e:
|
|
print(e.status) # 404
|
|
```
|
|
|
|
## Notes
|
|
|
|
- **Use HTTPS in production** — the API key is sent as `X-API-Key` and is bearer-equivalent.
|
|
- The SDK does **not** retry, and **never follows redirects** (so the key is never re-sent to
|
|
a redirect target). Path segments are percent-encoded; a base-URL path prefix (e.g. behind a
|
|
reverse proxy) is preserved.
|
|
- Escape hatch for endpoints the SDK does not wrap:
|
|
`client.request(method, path, query=…, body=…)`.
|
|
|
|
## License
|
|
|
|
MIT
|