Drift — migrate in
Fictura is designed to be adopted piece by piece, next to everything you already run — and to break nothing if you leave.
The migration story is additive. Nothing asks you to replace your billing spine, your crash reporter, or your subscriptions table on day one — each connection sits beside what exists.
Keep RevenueCat
Fictura consumes RevenueCat's webhook; it doesn't replace RevenueCat. Your purchase code, your entitlement checks, your RevenueCat dashboard all keep working — one pasted URL adds Fictura as a second consumer.
Bring your history with you
The webhook starts telling us about sales from the day you connect it. Everything you sold before that day is still in RevenueCat, and you can bring it over in one step.
Go to Import data in the dashboard. There are two ways in, and you can use both:
- Paste a RevenueCat secret key. Make one in RevenueCat under Project settings, API keys, Secret keys. We read your customers and their purchases. Nothing is written back.
- Upload their export file. In RevenueCat, export your Transactions file and drop it in. This file has every renewal, which the key on its own cannot list.
The import keeps going if you close the tab. If it stops early, it picks back up where it stopped instead of starting over.
Three things stay true while it runs:
- Your live webhook keeps working. New sales land the whole time.
- A sale that arrives both ways is counted once, so your revenue never doubles.
- Old sales keep their real dates, so your charts start where your business does.
And bring AppsFlyer's
RevenueCat has the money. AppsFlyer has where the people came from: the install, the channel that brought it, the campaign behind it, plus uninstalls, reinstalls and ad revenue. If you ran both, import both — otherwise your old revenue arrives with no channel attached to it.
AppsFlyer is the one connection that is genuinely a replacement rather than an addition, so it has its own page: Leave AppsFlyer.
Keep your subscriptions table
Point the billing webhook at the handler you already run. The only real difference from the RevenueCat payload is nesting — theirs under event, ours under data — so the shim is a few lines:
const payload = await req.json();
// Works for both senders: RevenueCat nests under `event`, Fictura under `data`.
const e = payload.event ?? payload.data;
const userId = e.app_user_id;
const productId = e.product_id;
const expiresAt =
e.expires_at ??
(e.expiration_at_ms ? new Date(Number(e.expiration_at_ms)).toISOString() : null);Everything after those lines — your upsert, your status function, your gating — runs unchanged. Or retire the table and ask the entitlements endpoint instead; both derive from the same events.
Keep your error reporter
Fictura's error handlers chain to whatever was installed first, so anything you already run keeps catching exactly what it catches today. Nothing to remove on the way in.
And the exit
The same properties in reverse. Because your spine was never replaced — RevenueCat still fires, your table still fills, your store products still sell — turning Fictura off tomorrow breaks nothing. Web checkout's off switch returns every device to the App Store sheet within one config refresh. That's the drift argument: tools that connect without fusing.