Metadata-Version: 2.5
Name: usenadia
Version: 0.1.0
Summary: Python SDK for the UseNadia public API — schedule posts, manage channels, run the Instagram comment/story → DM machinery
Project-URL: Homepage, https://usenadia.com
License: MIT
License-File: LICENSE
Requires-Python: >=3.11
Requires-Dist: attrs>=22.2
Requires-Dist: httpx<1,>=0.23
Requires-Dist: python-dateutil>=2.8
Description-Content-Type: text/markdown

# usenadia

Python SDK for the **UseNadia** public API (`/public/v1`) — schedule posts,
manage channels, and drive the Instagram comment/story → DM machinery.

```bash
pip install usenadia
```

```python
from usenadia import Nadia, NadiaError

nadia = Nadia(api_key=os.environ["USENADIA_API_KEY"])

channels = nadia.integrations()

try:
    nadia.post({
        "type": "schedule",
        "date": "2026-10-01T09:00:00.000Z",
        "shortLink": False,
        "tags": [],
        "posts": [{
            "integration": {"id": channels[0]["id"]},
            "value": [{"content": "Hello from the SDK", "image": []}],
            "settings": {},
        }],
    })
except NadiaError as err:
    print(err.status, err)      # 402 You have reached your limit
```

## The content board

Every card of the board in the app is reachable: create one from anywhere
(a voice note, a Notion page, a DM), move it along, read its numbers once
it is published.

```python
card = nadia.create_content(
    "Three mistakes when moving to Malta",
    hook="Nobody told me about the third one.",
)

nadia.move_content(card["id"], "SCRIPT")
nadia.update_content(card["id"], script="…")

# Scheduled with nadia.post({..., "posts": [{"group": "g-42", ...}]}):
nadia.link_content_post(card["id"], "g-42")  # → PUBLISHED when it goes live

numbers = nadia.contents_performance()  # keyed by card id
```

Columns, in order: `IDEA`, `SCRIPT`, `VALIDATED`, `TO_SHOOT`, `TO_EDIT`,
`TO_SCHEDULE`, `PUBLISHED`.

## How it is built

Two layers, and the split is deliberate.

- **`usenadia/generated/`** — the transport. Generated from
  `openapi.public.json` by
  [`openapi-python-client`](https://github.com/openapi-generators/openapi-python-client)
  (httpx + attrs), covers every operation, never edited by hand, not
  committed.
- **`usenadia/__init__.py`** — this SDK's own surface: the `Nadia` class,
  sane defaults, typed errors, retries. Small, hand-written, reviewed.

Anything the facade does not wrap is reachable through `nadia.raw`, the
configured generated client.

## Errors

Every response with a status ≥ 400 raises a `NadiaError` carrying `status`,
`body` and the API's `msg`. `err.is_transient` is true for 429 and 5xx — those
are retried automatically (twice by default, `Nadia(key, retries=0)` to turn
it off).

## Regenerating

```bash
pnpm run sdk:generate   # from the repo root — regenerates both SDKs
```

Plan: `docs/roadmap/19-sdk-public-api.md`.
