Metadata-Version: 2.4
Name: genieos
Version: 0.1.0
Summary: Official Python SDK for GenieOS — sync + async clients, typed responses, idempotency-aware retries, webhook verification.
Project-URL: Homepage, https://docs.genieos.pro/sdks/python
Project-URL: Documentation, https://docs.genieos.pro/sdks/python
Project-URL: Repository, https://github.com/GenieOS-0/sdk-python
Project-URL: Issues, https://github.com/GenieOS-0/sdk-python/issues
Project-URL: Changelog, https://github.com/GenieOS-0/sdk-python/blob/main/CHANGELOG.md
Author-email: GenieOS <developers@genieos.pro>
License: MIT
License-File: LICENSE
Keywords: drip,email,genieos,mcp,sequences,transactional
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 :: Email
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.6
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: posthog>=3.0.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: python-dotenv>=1.0.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Provides-Extra: telemetry
Requires-Dist: posthog>=3.0.0; extra == 'telemetry'
Description-Content-Type: text/markdown

# genieos — Python SDK

[![PyPI version](https://img.shields.io/pypi/v/genieos.svg)](https://pypi.org/project/genieos)

The official Python SDK for [GenieOS](https://genieos.pro). Sync and
async clients, typed responses (Pydantic), automatic idempotency,
retry-on-429/5xx with exponential back-off, and webhook signature
verification.

## Install

```bash
pip install genieos
```

Requires Python 3.9+ and `httpx>=0.27`, `pydantic>=2.6`.

## Quickstart (sync)

```python
from genieos import GenieOS

with GenieOS(api_key="gos_live_...") as mg:
    ws = mg.workspace.get()
    print(ws.name, "on", ws.plan)

    send = mg.templates.send(
        "welcome",
        to="aki@example.com",
        variables={"firstName": "Aki"},
    )
    print("queued:", send.id)
```

The API key is also picked up from the `GENIEOS_API_KEY` env var,
matching the Node SDK and CLI.

## Quickstart (async)

```python
import asyncio
from genieos import AsyncGenieOS

async def main():
    async with AsyncGenieOS() as mg:  # MAILGENIUS_API_KEY env var
        await mg.events.emit(
            "subscription.cancelled",
            email="aki@example.com",
            traits={"tier": "pro", "reason": "moving to weekly"},
        )

asyncio.run(main())
```

## Webhook verification (Flask)

```python
from flask import Flask, request, abort
from genieos import verify_webhook, WebhookSignatureError

app = Flask(__name__)

@app.post("/genieos/webhook")
def webhook():
    try:
        delivery = verify_webhook(
            request.get_data(as_text=True),
            request.headers,
            secret=os.environ["MAILGENIUS_WEBHOOK_SECRET"],
        )
    except WebhookSignatureError as e:
        abort(400, str(e))

    if delivery.type == "send.delivered":
        ... # handle it
    return "", 204
```

`verify_webhook` rejects out-of-window timestamps (default ±5 min) and
performs constant-time signature comparison. The same module exposes
`sign_webhook` for local testing.

## Error handling

```python
from genieos import (
    GenieOSRateLimitError,
    GenieOSValidationError,
    GenieOSAuthError,
)

try:
    mg.events.emit("checkout.completed", email="aki@example.com")
except GenieOSRateLimitError as e:
    time.sleep(e.retry_after_seconds)
except GenieOSValidationError as e:
    log.warning("422: %s", e.body)
except GenieOSAuthError:
    rotate_my_key()
```

All SDK errors inherit from `GenieOSError` and expose `.code`,
`.status`, `.request_id`, `.body`.

## License

MIT
