Inspiration

What it does

How we built it

Challenges we ran into

Accomplishments that we're proud of

What we learned

What's next for ChurnSave — PayPal churn-recovery agent

Inspiration

Subscription businesses lose 5–7% of MRR every month, and most cancellations get no response at all. PayPal tells the merchant the subscription is gone — but nothing brings it back. Writing a good retention offer for every churn event is manual work merchants never do, so that revenue is simply written off. We asked: what if an agent did that work?

What it does

ChurnSave is an autonomous churn-recovery agent built on PayPal APIs:

  1. A cancellation webhook fires. ChurnSave verifies its transmission signature and looks up the buyer.
  2. The agent runs a reasoning pipeline over the buyer's PayPal transaction history: it computes lifetime value, classifies the buyer into a segment, and decides the cheapest credible offer — a high-LTV "champion" gets 20% off for 3 months as a real discounted PayPal order; a light user gets a downgrade to a cheaper plan instead of being lost entirely.
  3. The buyer gets one personalized link — one click, and ChurnSave creates and captures a real PayPal order for the discounted amount.
  4. The merchant dashboard tracks the full funnel (cancellation events → offers → accepted → recovered MRR) with the agent's complete decision trace visible for every event.

A $588-LTV power user and a $49-LTV light user get different offers — that differentiation is the point: the agent spends a discount only where it pays off.

How we built it

  • Next.js 15 (App Router) + TypeScript for the merchant dashboard, buyer offer pages and webhook receiver.
  • @paypal/agent-toolkit (official PayPal SDK for agents) drives order creation and capture; the webhook endpoint verifies PayPal transmission signatures before any processing.
  • Agent core as an explicit state machine (src/lib/agent/run.ts): every step emits a trace event, so the dashboard shows exactly why an offer was made — findSubscription → fetchBuyerHistory → ltv:588 → segment:champion → decision:discount −20% → llm reasoning (confidence 0.86).
  • LLM provider abstraction: an OpenAI-compatible chat-completions client generates the buyer-facing insight copy and reasoning narrative; a deterministic MockProvider keeps the whole loop runnable offline with an honest "AI (offline mock)" badge on screen — no fake claims about what generated the text. Dropping in a live Nebius-hosted model is a .env change.
  • SQLite (better-sqlite3) for subscriptions, events, offers and orders.
  • Vitest covers the money paths: webhook signature verification, LTV math, anti-replay guards (409/410 on duplicate/used offers), and order idempotency.

Challenges we ran into

Making offers safe by construction: an offer link must be unguessable, single-use, and idempotent under double-clicks and webhook replays. We enforce it with opaque offer tokens, a one-use transactional guard, and explicit 409/410 responses tested in CI.

Accomplishments that we're proud of

  • A complete, honest closed loop on camera: cancel → agent decides → buyer accepts → PayPal order captured → recovered MRR on the dashboard, with the agent's own trace shown at every step.
  • Fully reproducible offline (npm run seed && npm run dev), with the mock gateway labeled MOCK everywhere.
  • Zero-cost, zero-fake AI: the reasoning layer is a pluggable provider with graceful degradation.

What we learned

PayPal's webhook + Orders API pair is enough to build reactive commerce agents: the webhook tells you when, the Orders API lets you act, and a trace-first state machine makes an agent auditable enough for merchants to trust it with real money decisions.

What's next for ChurnSave

Live PayPal sandbox end-to-end run, multi-currency offer policies, and a pause-instead-of-cancel option for temporary hardship churn.

Built with: Next.js 15, TypeScript, @paypal/agent-toolkit, PayPal Orders API, SQLite (better-sqlite3), Vitest, Tailwind CSS, OpenAI-compatible LLM client.

Demo repo: https://github.com/skye-cqu/churnsave (public, MIT). Run it yourself: npm install && npm run seed && npm run dev.

Built With

Share this project:

Updates

Submission history