Docs

Welcome to Backstop.

Practical guides for connecting Stripe, shipping a cancel flow, recovering failed payments, and wiring up our REST API. Indie-SaaS depth, no fluff. If something's wrong, hit reply on any Backstop email — a founder reads everything.

Getting started: set up your workspace

The fastest way through setup is the Get set upchecklist on your workspace Overview — it's the same five steps below, in the same order, and it ticks each one off automatically as you finish it (the one exception is step 4, which you mark done by hand — more on that there). This page is the long-form version: what each step does, where to click, how to confirm it worked, and the mistake that bites most people. Do them in order; each one builds on the last.

Before you start:a Stripe account with at least one subscription product, and access to your DNS provider if you want emails and portal pages on your own domain (steps 2 and beyond — both optional). That's it. You don't need your Stripe secret key, and you don't need to write any backend code until step 4.

1. Connect Stripe

From your workspace Overview, click Connect Stripe(it's the first item in the Get set up checklist, and the dashboard shows a banner until it's done). Stripe shows a consent screen for a read_writeConnect grant — read so we can mirror your customers, subscriptions, and invoices; write so we can act on the recovery and retention rules you configure later. Confirm it and you're back in Backstop. We never ask for your secret key, and you can revoke the grant from Stripe at any time.

  1. Verify: the connect banner clears and the checklist item turns green. The header under your workspace name shows whether you connected in testmode or livemode — Backstop mirrors whichever mode you connected with, so check it matches what you expect.
  2. Pitfall:connecting in test mode but expecting to see your live customers (or the reverse). There's no in-product mode toggle — you switch by reconnecting.

Full detail on the OAuth grant, exactly what we read and write, and how to disconnect: Connect Stripe.

2. Verify a send domain (optional, recommended)

Recovery turns on automatically once Stripe is connected, and dunning emails will send from our shared sender out of the box. For the best inbox placement, send them from your own subdomain instead. Go to Settings → Send domain, enter a dedicated subdomain like mail.yourcompany.com, and click Add domain. We generate three CNAME records (Amazon SES EasyDKIM tokens) — copy them into your DNS provider, then click Verify DNS.

  1. Verify: the settings page flips the domain to “verified” once SES confirms the records. CNAME propagation is usually a few minutes but can take a few hours — give it time and click Verify again.
  2. Pitfall: adding a custom domain and then leaving DNS unfinished blockssends (it won't silently fall back to the shared sender). Either finish verification or remove the domain. And don't reuse a subdomain you also blast marketing email from — a marketing spam complaint will drag your dunning deliverability down with it.

Full walkthrough, including how to brand the emails themselves: Custom send domain.

3. Build & publish your first cancel flow

From the Cancel flows nav, open New flow and pick the starter template closest to your business (about a dozen, from SaaS Standard to Pause Instead to Annual Upsell). Click Use template, tune the Offer node in the canvas builder, Simulate it to walk the flow as a customer would, then Publish — that snapshots your draft as version 1 at 100% traffic.

  1. Verify: publishing is what makes the embed snippet (step 4) render real content instead of 404ing. Most templates also publish a live v1 the moment you create them.
  2. Pitfall: the three templates with a schedule-a-call or save-stories step (Agency / Pro Service, Fitness / Wellness, B2B with Account Teams) land as drafts— fill in your booking URL and any story content, then Publish them before they'll go live.

Step-by-step on templates, offer variants, A/B testing, and discount-approval thresholds: Ship your first cancel flow.

4. Embed it (and close the Stripe bypass)

A published flow only saves customers who actually reach it, so now point your “Cancel subscription” button at it. Load embed.js and call Backstop.cancel(…) to open the flow as a modal on your own site, or use the hosted-redirect option (no SDK) for CSP-locked stacks. The copy-paste snippet, pre-filled with your workspace slug, lives under Cancel flows → Embed on your site. Both openers share one backend signer that HMAC-signs a short-lived token — your workspace embed secret never touches the browser.

  1. Critical second half — disable cancellation in Stripe.Wiring your button isn't enough on its own: in the Stripe Dashboard, turn off “Cancel subscriptions” under Settings → Billing → Customer portal. Otherwise customers who open Stripe's portal directly cancel without ever seeing your offer — the #1 reason a retention tool “doesn't seem to be doing anything.”
  2. Verify: clicking your button should land in the Backstop flow (survey first), and a test customer opening the Stripe portal should have nocancel option. This is also the one checklist step Backstop can't auto-detect — we can't read your Stripe portal setting through the API, so you mark it done by hand once it's flipped.

The handshake, signer code, callbacks, and a curl check that proves your HMAC is correct: Embed Backstop. The why-this-matters version and the full Stripe-portal walkthrough: Route cancellations through Backstop.

5. Watch recoveries roll in

You're live. Open the Recovery nav item: when Stripe fires invoice.payment_failed for any subscription, a campaign opens here automatically and runs decline-code-aware smart retries, a dunning email sequence, and the in-app Failed Payment Wall — then a one-click win-back if they still churn. Filter campaigns by In flight / Recovered / Lost / Abandoned, and watch the Recovered · 30d figure climb. Cancel-flow outcomes (the save side) live under Cancel flows → Analytics.

  1. Verify:the “See your first recovery campaign” checklist item turns green the moment your first campaign opens.
  2. Tune it: retry timing and email copy are configurable — Retry policy and the Email settings group in the sidebar — and you can globally pause sends from Settings → Pause recovery if you ever need to.

Sync outcomes into your own systems

  • Webhookssubscribe to recovery and cancel events (recovery.*, cancel.*) with HMAC-signed, Stripe-style payloads. Configure endpoints under Settings → Outbound webhooks.
  • REST APIpull campaigns, customers, cancel sessions, and aggregate stats. Bearer-token auth, minted under Settings → API tokens.

Custom domains (optional polish)

  • Custom portal domainserve your cancel flow, manage-subscription portal, and update-card pages from portal.yourcompany.cominstead of a Backstop URL. Also the fix when a customer's DNS filter blocks trybackstop.com.

Reference

  • REST APIauth, endpoints, rate limits.
  • Webhooksoutbound event types and HMAC signature verification.
  • Troubleshootingcustomers not syncing, dunning not sending, 404s, signature errors, and more — with the actual fix.