Metadata-Version: 2.4
Name: fluidtalk
Version: 2.0.0
Summary: Official Python SDK for the FluidTalk Characters API — drive an AI persona across DMs, comments, triggers, and follow-ups.
Project-URL: Homepage, https://talk.fluidvip.com
Project-URL: Documentation, https://api-talk.fluidvip.com/api/v1/characters/openapi.json
Project-URL: Source, https://github.com/Trebuu/FluidTalk-Selfhost
Author: Fluidvip
License-Expression: MIT
Keywords: ai-persona,automation,characters,chatbot,dm,fluidtalk
Requires-Python: >=3.8
Requires-Dist: httpx>=0.24
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == 'dev'
Description-Content-Type: text/markdown

# FluidTalk Characters — Python SDK

Official Python SDK for the [FluidTalk Characters API](https://api-talk.fluidvip.com/api/v1/characters/openapi.json) — drive an AI persona across DMs, comments, triggers, and follow-ups from your own bot or connector.

## Install

```bash
pip install fluidtalk
```

## Quickstart

```python
from fluidtalk import FluidTalk

ft = FluidTalk(token="ftc_live_...")          # base_url defaults to production

# A lead DM'd the character — get the reply and send the bubbles yourself.
reply = ft.chat(platform="instagram", handle="mark", message="hey ava")
for bubble in reply.bubbles:
    send_dm("mark", bubble.text)              # your platform I/O
print("session:", reply.session_id)
```

Your **per-character connector token** (`ftc_live_…`) is sent as `X-Connector-Token`; get it from the character's platform settings in the [dashboard](https://talk.fluidvip.com). The token *is* the character — you name the `platform` in each call.

## API

| Method | Endpoint |
|---|---|
| `ft.chat(platform, handle, message="", image_url=None, session_id=None, own_username=None)` | `POST /chat` |
| `ft.event(platform, handle, external_event_id, event_type="purchase", amount=None, currency=None)` | `POST /events` |
| `ft.trigger(platform, handle, event_id, external_event_id, context=None, own_username=None)` | `POST /triggers` |
| `ft.followups.list(platform, own_username=None, limit=100)` | `GET /followups` |
| `ft.followups.ack(followup_id)` | `POST /followups/{id}/ack` |
| `ft.comment(platform, post_ref, caption=None, image_urls=None, author_handle=None)` | `POST /comments` |
| `ft.comment_reply(platform, post_ref, replier_handle, reply_text="", parent_comment_ref=None)` | `POST /comments/reply` |

Responses are returned as attribute-access objects unwrapped from the `{data, request_id}` envelope (`reply.bubbles[0].text`, `res.decision`); a missing field reads as `None`. Use `.to_dict()` for the raw dict.

## Errors

Every non-2xx response raises a typed exception (all subclass `FluidTalkError` / `ApiError`):

```python
from fluidtalk import FluidTalk, PaymentRequiredError, RateLimitError, ApiError

ft = FluidTalk(token="ftc_live_...")
try:
    reply = ft.chat(platform="instagram", handle="mark", message="hi")
except PaymentRequiredError:
    top_up_wallet()        # 402 — the wallet can't cover the turn
except RateLimitError:
    backoff_and_retry()    # 429
except ApiError as e:
    print(e.status, e.code, e.request_id, e.message)
```

`AuthError` (401), `PaymentRequiredError` (402), `PermissionError` (403), `NotFoundError` (404), `ConflictError` (409), `ValidationError` (422), `RateLimitError` (429), and `ApiError` (anything else).

## Configuration

```python
FluidTalk(
    token="ftc_live_...",
    base_url="https://api-talk.fluidvip.com",   # green: https://api-green-talk.fluidvip.com
    timeout=60.0,
)
```

## Development

```bash
pip install -e ".[dev]"
pytest
```
