Metadata-Version: 2.4
Name: windback
Version: 0.2.0
Summary: Official Python SDK for Windback — AI-powered churn recovery for SaaS
Project-URL: Homepage, https://windback.com
Project-URL: Repository, https://github.com/windback/windback-python
Project-URL: Documentation, https://docs.windback.com
Author-email: Windback <hello@windback.com>
License-Expression: MIT
Keywords: churn,recovery,saas,subscription,winback,windback
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
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 :: Software Development :: Libraries
Requires-Python: >=3.8
Requires-Dist: httpx>=0.24.0
Description-Content-Type: text/markdown

# windback

Official Python SDK for [Windback](https://windback.com) — AI-powered churn recovery for SaaS.

## Install

```bash
pip install windback
```

## Quick Start

```python
from windback import Windback

pb = Windback("sk_live_your_api_key")

event = pb.track_churn(
    email="jane@company.com",
    name="Jane Doe",
    provider="stripe",
    plan_name="Pro",
    mrr=4900,          # $49.00 in cents
    currency="USD",
    tenure_days=120,
    cancel_reason="too_expensive",
    cancel_reason_text="Costs more than our budget allows",
)
```

## Usage

### Initialize

```python
# Simple
pb = Windback("sk_live_your_api_key")

# With options
pb = Windback(
    "sk_live_your_api_key",
    base_url="https://api.windbackai.com",  # default
    timeout=10.0,  # seconds
    retries=2,
)
```

---

### Track Churn

Call this wherever your cancellation logic runs. Windback stores the event; use
`generate_variants` + `send_variant` to trigger the winback email manually, or pass
`cancel_reason` and call `report_cancel_reason` to trigger it automatically.

```python
event = pb.track_churn(
    email="jane@company.com",    # required
    provider="stripe",            # required — see providers below
    mrr=4900,                     # required, in cents

    name="Jane Doe",              # optional
    plan_name="Pro",              # optional
    currency="USD",               # optional, default "USD"
    tenure_days=120,              # optional
    last_active_at="2026-02-10T12:30:00Z",  # optional, ISO 8601
    cancel_reason="too_expensive",           # optional — see cancel reasons below
    cancel_reason_text="Too costly for our stage",  # optional, free text
    notes="Requested downgrade first",              # optional, internal notes
)
```

---

### Cancel Reason — Two Integration Patterns

#### Pattern A — All-in-one (cancel happens in real time)

Use this when the customer fills in the cancel reason on YOUR platform at the moment
they cancel. Windback creates the event, picks the best winback strategy for the reason,
and sends the email automatically.

```python
resp = pb.submit_cancel_flow(
    email="jane@company.com",    # required
    provider="stripe",            # required
    mrr=4900,                     # required, in cents
    currency="USD",               # required
    cancel_reason="too_expensive",               # required
    cancel_reason_text="It's more than our budget",  # optional

    name="Jane Doe",
    plan_name="Pro",
    tenure_days=120,
)
# Email is sent automatically.
# resp = { "churn_event_id": "...", "status": "new", "message": "..." }
```

#### Pattern B — Webhook first, survey later

Use this when your payment provider (Stripe, Dodo, Razorpay) fires a webhook that
Windback picks up automatically to create the churn event — and your cancel survey
collects the reason separately (e.g. shown after the customer confirms cancellation).

```python
# Step 1 — Windback creates the event from the payment webhook automatically.
# Your webhook handler just needs to be set up in the Windback dashboard.

# Step 2 — Once your cancel survey captures the reason, call:
pb.report_cancel_reason(
    event_id=event.id,
    cancel_reason="missing_features",
    cancel_reason_text="We need Salesforce integration",
)
# Windback updates the event and sends the targeted winback email automatically.
```

---

### Cancel Reason Values

| Value | When to use | Email strategy |
|---|---|---|
| `too_expensive` | Price is the blocker | Discount offer |
| `missing_features` | They need something you don't have | Highlight unused / upcoming features |
| `not_using_enough` | Low engagement / forgot about it | Value recap |
| `switching_competitor` | Moving to a competing product | Social proof |
| `technical_issues` | Bugs, downtime, or integration problems | Pain point fix + apology |
| `poor_support` | Unhappy with support experience | Founder personal email |
| `dont_need_anymore` | Use case is gone (company pivot, etc.) | Pause option |
| `other` | None of the above — use `cancel_reason_text` | Feedback request |

Windback maps each reason to the best winback email strategy automatically.

---

### Supported Providers

`stripe` | `razorpay` | `paypal` | `wise` | `paddle` | `polar` | `dodo` | `chargebee` | `lemonsqueezy` | `custom`

---

### Other Methods

```python
# Get a churn event
event = pb.get_event("event_id")

# Generate AI recovery email variants manually
result = pb.generate_variants("event_id")

# Send a specific variant manually
pb.send_variant("event_id", "variant_id")
```

---

### Context Manager

```python
with Windback("sk_live_your_api_key") as pb:
    pb.track_churn(email="jane@co.com", provider="stripe", mrr=4900)
# HTTP client is automatically closed
```

---

### Error Handling

```python
from windback import Windback, WindbackError

try:
    pb.track_churn(email="jane@co.com", provider="stripe", mrr=4900)
except WindbackError as e:
    print(e)          # "Windback: invalid API key"
    print(e.status)   # 401
```

## License

MIT
