Inspiration

Every SaaS or subscription business loses revenue the same quiet way: a card expires, a payment fails, and the automated dunning email goes unread. The customer didn't intend to cancel — they just never saw the message.

I face this personally running community programs where missed payments mean lost participants. Email open rates for billing issues hover around 20%. A phone call gets answered. That gap is what Recover is built to close.

What it does

Recover is an AI-powered payment recovery agent that uses CALL-E to place outbound phone calls to subscribers with failed payments — having a real, structured conversation to understand their situation and capture their intent.

After a call, the agent surfaces one of three advisory outcomes to a human operator dashboard:

  • Retry now — customer confirmed they want the charge re-attempted
  • Update card — customer wants to switch payment methods
  • Pause subscription — customer requested a grace period

A human operator reviews and confirms before any financial action is executed. Nothing is done autonomously.

How we built it

The stack is intentionally minimal and focused on reliability:

  • Next.js 16 (App Router) — API routes handle call orchestration, webhook ingestion, and the operator dashboard
  • CALL-E TypeScript SDK — call creation with a structured resultSchema that extracts a typed PaymentRecoveryDecision directly from the conversation
  • Stripe Webhooks — trigger recovery flows on invoice.payment_failed events
  • SQLite (in-memory) — lightweight state machine tracking call lifecycle: initiating → active → pending_confirmation → completed

The most interesting architectural decision was the webhook re-fetch pattern: since CALL-E doesn't currently sign webhook payloads, the app never trusts incoming webhook bodies. Every webhook triggers an authoritative re-fetch of the call via GET /v1/calls/{id}, binding the result to the exact local call record and stored subscriber destination before anything is recorded.

Challenges we ran into

Webhook security without signing — No signing secret means you can't verify the webhook sender client-side. The solution — re-fetching from the authenticated API — is the right mitigation but isn't documented as a recommended pattern. We had to arrive at it independently and implement it as a security requirement.

Idempotency key lifecycle — After a call is rejected pre-dial (e.g. missing sender disclosure), reusing the same idempotency key throws an error. The distinction between "safe to issue a new key" vs "must reconcile first" isn't walked through in the docs with a concrete example.

Region support discoverability — Ghana isn't currently a supported calling region, and this only surfaces as a rejection at call-creation time — there's no pre-flight way to check supported regions from code. CALL-E's Discord support team pointed us to the US test hotline as a workaround, which allowed us to complete the integration.

Accomplishments that we're proud of

Getting a structured, validated payment decision — retry_now, update_card, or pause_subscription — out of a natural phone conversation with zero custom NLP is genuinely remarkable. CALL-E's resultSchema handled all of that.

We're also proud of the safety architecture: a bounded retry chain, destination binding verification, idempotency throughout, and a strict human-confirmation gate before any financial action. It's a reference implementation that takes the "just a demo" shortcuts seriously.

What we learned

The AI part of an AI calling agent is the easy part. The hard part is the surrounding reliability infrastructure: idempotency, deduplication, bounded retry logic, and making sure you never act on an ambiguous or unverified outcome.

We also learned that the most impactful documentation gap for early CALL-E adopters isn't the happy path — it's the edge cases: rejected calls, failed verifications, and what to do with a webhook you can't cryptographically verify.

What's next for Recover – AI Payment Recovery Agent

  • Real Stripe integration — execute confirmed retries and card-update sessions automatically after human approval
  • Webhook signing — once CALL-E ships signed webhooks, remove the re-fetch overhead for verified deliveries
  • Multi-region support — expand beyond US as CALL-E adds more supported regions
  • Analytics — track recovery rates, call outcomes, and churn reduction over time

Built With

Share this project:

Updates

Submission history