Skip to content

Developers

Built for developers

The whole integration is one request from your server and one redirect. A CLI writes it for you, checks it, and hands your AI assistant the same contract this page describes.

One command

Install from the terminal

Run it in the project that owns the cancel button. It never writes a file without showing you what changes first.

npx revfence init
  • Detects your framework and finds where the server-side code lives.
  • Adds the server-side call and the environment variable that holds your API key.
  • Shows you the diff before writing a single file.
  • Verify

    npx revfence doctor

    Checks the key, the Stripe connection and the allowed return origins. Run it after init, and again whenever a session refuses to open.

  • Bring your AI assistant

    npx revfence skill

    Installs a Claude Code skill and a Cursor rule that carry the same contract as this page, so the assistant writes the request the way the server expects it.

    The same guides are public, in plain text:

The integration in one request

One request from your server, one redirect

Your server opens a session with the project key and sends the customer to the single-use address that comes back. The key never reaches the browser.

// On your server, when the customer presses "cancel subscription".
// One idempotency key per button press; send the SAME value on every retry.
const idempotencyKey = `cancel_${subscriptionId}_${crypto.randomUUID()}`;

const res = await fetch("https://api.revfence.com/public/sessions", {
  method: "POST",
  headers: {
    "Authorization": "Bearer rf_live_…", // the project key, never in the browser
    "Idempotency-Key": idempotencyKey,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ customerId, subscriptionId, returnUrl }),
});

if (!res.ok) {
  // 409, 429, 5xx: no session was opened. Continue your own cancel flow.
  return redirect("/account/cancel");
}

const { url } = await res.json();
return redirect(url); // single use, valid for 30 minutes
  1. 01

    Request

    A POST with the project key as a Bearer token, an Idempotency-Key that is unique per button press and reused on every retry, and the Stripe customer and subscription ids.

  2. 02

    Response

    A url field. Redirect the customer there; the address is single use and valid for 30 minutes. returnUrl is where they land afterwards and must be on the same origin as the cancel or keep URL set on the project.

  3. 03

    On error

    A 409, 429 or 5xx means no session was opened. Never block the customer: continue your own cancel flow as if RevFence were not there.

Guarantees

What RevFence never does

The boundaries are part of the contract. Your cancel flow stays yours, and the integration is one outbound request from your server.

  • Never cancels a subscription

    The customer keeps cancelling through your own flow. RevFence only applies the offer they accept, in your own Stripe account.

  • Never needs webhooks from you

    There is nothing to receive, verify or retry on your side. The result of a session is read from the dashboard, not pushed to your server.

  • Never runs in the browser

    The key stays on your server; the customer only ever sees the hosted page. There is no script to add to your product.

Turn the cancel button into a second chance

Connect Stripe, define one offer, redirect the button. Every cancellation you miss today is a question you'll never get to ask.