Keep 2.5% more of every sale. ExtPay takes 5% flat. crxpay is 2.5% — and your first $2,500 in tracked revenue is free.
Migrate from ExtPay in an afternoon.
A drop-in, API-compatible adapter keeps every extpay.getUser() call working — while you unlock entitlements, paywalls, analytics, and a 2.5% fee(half of ExtPay’s 5%).
-const extpay =- ExtPay('my-extension');-await extpay.startBackground();--const user = await extpay.getUser();-if (user.paid) unlock();
+import { crxpay } from '@crxpay/sdk';+const sub = crxpay({ apiKey: 'pk_live_…' });+await sub.ready();+if (sub.hasEntitlement('pro'))+ unlock();
Why switch
Everything ExtPay does — plus what it doesn’t.
crxpay covers the same subscription primitives you already rely on, then layers the pieces ExtPay asks you to build yourself.
No more ‘subscription disappeared’ tickets. HMAC-signed local cache keeps entitlements valid on flaky networks. ExtPay re-fetches on every check.
Built for MV3 service workers, not against them. Every SDK call is CORS-safe in Manifest V3. No background-page workarounds, no re-auth loops.
Ship a paywall update without a store re-review. No-code editor, remote deploy, targeting, and A/B out of the box. ExtPay stops at the payment link.
Migrate in an afternoon. One adapter package, one import swap, then run the CLI. Users stay signed in, subscriptions stay active.
See the migration guide →Feature-by-feature, side by side.
The honest version. Built for Chrome extension devs evaluating their next few years.
How it works
Three steps. One afternoon.
Install the compat layer
One package replaces ExtPay. Drop in the adapter and your existing extpay.* calls continue to resolve — now against crxpay.
pnpm add @crxpay/sdk @crxpay/compat-extpay
Swap one import
Change a single line in your background service worker. All your existing user-check branches keep working untouched.
// was:
import ExtPay from 'extpay';
// now:
import { ExtPay } from '@crxpay/compat-extpay';Mirror your users, then flip the switch
Run crxpay migrate once — it imports every ExtPay user and links Stripe customers. Publish, and the next paywall check reads from crxpay.
npx crxpay migrate \ --from extpay \ --api-key <your-extpay-key>
Drop-in compatible
Your old code doesn’t need to change.
extpay.getUser(), onPaid, and openPaymentPage all keep their signatures. The adapter forwards them to crxpay, returns the exact shape ExtPay returned, and unlocks entitlements behind the scenes.
- ✓Zero rewrite — 1 import change
- ✓Same user IDs, same install dates
- ✓Entitlements available when you want them
+import { ExtPay } from '@crxpay/compat-extpay';··const extpay = ExtPay('my-ext');·extpay.startBackground();··extpay.onPaid.addListener(async (user) => {· // works exactly as before· if (user.paid) state.set('pro', true);·});··// unlock the new stuff when you want it:+const sub = extpay.asCrxpay();+if (sub.hasEntitlement('team-seat'))+ showTeamUi();
The questions we always get.
Ready to grow?
Our entire suite of features comes standard — and your first $2,500 in tracked revenue is free.