Metadata-Version: 2.5
Name: cue-notify-client
Version: 0.3.1
Summary: Python client for Cue: send events and messages, and verify Cue's signed webhooks.
Project-URL: Homepage, https://github.com/murtazox04/Cue/tree/main/sdks/python
Project-URL: Documentation, https://murtazox04.github.io/Cue
Author: Murtazo Xurramov
License-Expression: MIT
Keywords: cue,notifications,sdk,webhooks
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Description-Content-Type: text/markdown

# cue-notify-client

Python client for [Cue](https://github.com/murtazox04/Cue), the attention layer between
software, AI agents and people. Its only dependency is `httpx`.

```bash
pip install cue-notify-client
```

The package is imported as `cue_client`.

```python
from cue_client import Cue

with Cue(api_key="ck_…", base_url="https://cue.example.com") as cue:
    cue.upsert_recipient(
        "user-42",
        timezone="Europe/Berlin",
        addresses=[{"channel": "email", "value": "ann@example.com"}],
    )
    cue.send_event(
        "order.shipped", "user-42", {"order_id": "1001"}, idempotency_key="order-1001-shipped"
    )
```

`AsyncCue` has the same methods for `asyncio`. Errors raise `CueError` with the problem
details Cue returns (`status`, `title`, `detail`, `errors`). Rate limits and gateway
errors are retried automatically for requests that are safe to repeat: reads, profile
updates, and sends with an idempotency key.

## Verifying webhooks

If Cue delivers to your service through its webhook connector, check every request
before trusting it:

```python
from cue_client import InvalidSignatureError, verify_webhook


def handle(request):
    try:
        verify_webhook(request.body, request.headers.get("Cue-Signature"), secret=WEBHOOK_SECRET)
    except InvalidSignatureError:
        return 401
    message = json.loads(request.body)
    ...
```

Verify the raw body bytes, before parsing them. Requests signed more than five minutes
ago are rejected (`tolerance=` changes this).

## Asking a person first

```python
asked = cue.request_approval("Refund order 9?", ["lead"], body="Never arrived.")
cue.get_approval(asked["id"])["status"]  # pending, approved, rejected or expired
```

CrewAI Flows: `cue_client.crewai.CueFeedbackProvider`. Dapr Agents:
`cue_client.dapr.approval_request` and `approval_response`. See
[approval requests](https://github.com/murtazox04/Cue/blob/main/docs/concepts/approvals.md).
