Official Python SDK for Windback — AI-powered churn recovery for SaaS
Project description
windback
Official Python SDK for Windback — AI-powered churn recovery for SaaS.
Install
pip install windback
Quick Start
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
# 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.
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.
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).
# 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
# 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
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
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file windback-0.2.0.tar.gz.
File metadata
- Download URL: windback-0.2.0.tar.gz
- Upload date:
- Size: 7.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be389a12e82693b38080f5df486ab5366fce86e47170eda2613045a85fa187ef
|
|
| MD5 |
d52eb88acc1e64990d9f6fa0644436a6
|
|
| BLAKE2b-256 |
0106f6136d3e7928ab8e3658f380351fc9924a43eab84543ccd32950d9a80f4c
|
File details
Details for the file windback-0.2.0-py3-none-any.whl.
File metadata
- Download URL: windback-0.2.0-py3-none-any.whl
- Upload date:
- Size: 9.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bb2c30260d990fa8662591d5b9c078a5cf49c9be7724585551ccb0e481ccaf28
|
|
| MD5 |
b755ff67f9070eec379f0995f1763a9e
|
|
| BLAKE2b-256 |
cab4ef0dace459edc6110e85ab1c0a60f9c3bf0a8981c1be81151549c0292684
|