Fictura
Entitlements

Client-side gating

One boolean for the UI: Growth.isSubscribed(). Honest about what it is — a rendering hint that fails closed — and what it is not.

TypeScript
import { Growth } from "@fictura/sdk";

if (Growth.isSubscribed()) {
  // render the premium experience
}

The verdict rides in the SDK config payload, derived server-side from Stripe's and the stores' own webhooks. It refreshes with the config — launch, foreground, five-minute TTL — is cached offline with the config, and fails closed: before the first successful fetch on a fresh install the answer is false, never a guess.

Division of authority

  • Web-checkout purchasesisSubscribed() is the authoritative client answer; the store SDK has never heard of them.
  • Store purchases — your store SDK (for most apps, RevenueCat) remains the source of truth it already is. Fictura's copy of the verdict is a shadow that is continuously scored against the store SDK's answer.
  • Anything that costs you money — gate it server-side. A modified client can lie to itself; it can't lie to your backend.

For more than the boolean, getShadowEntitlement() returns the full verdict — status, product_id, will_renew, expires_at — marked shadow: true for exactly this reason: read it, display it, but don't build access control on the client from it.

On this page