Paywall  /  Customer portal

Customer portal

The portal is a hosted self-service page for your buyers — receipts, refunds, cancelling and resuming, switching plans, even deleting their account. You don't build any of it. This page covers all three sides: what the buyer sees, the dashboard switches that shape it, and how to open it from your app.

Availability follows your Onelo plan: the portal itself is a plan capability, and two of its actions — Change plan and Request refund — are off on the Free plan (paid Onelo plans include them). Cancelling and receipts are never plan-gated.

What the buyer sees inside

The portal greets them with “Manage your plan” (or “Welcome back” if their plan lapsed) and shows, per purchase: a status pill (Active / Canceled / Payment failed), the plan name and price, the key date (“renews 12 Jul 2026”, “free trial — first charge…”, “ends…” or “access until…”), when they started, and their last payment. Below sit the action buttons — each only appears when it actually applies:

ActionWhat happens
Change plan / Upgrade planShown when you have more than one plan (and your Onelo plan includes portal plan-changes). Opens your store with the buyer recognised — the unused part of what they already paid is shown as a credit and deducted at checkout, so they only pay the difference (“Pay €X today after applying credits”).
Switch to annual · save X% / Switch to monthlyShown when the product has both prices. Going up (monthly → annual, or a higher tier): a preview shows the exact prorated amount due today, line by line, before they confirm. Going down: no charge today — the cheaper plan simply takes over at the next renewal, so the time already paid for is never cut short.
Cancel subscriptionTwo gentle steps: a confirm (“You'll keep access until {date}, then won't be charged again”) and a why-are-you-leaving picker (8 reasons + optional note) — those reasons land in your dashboard as churn insight. Access runs to the period end; nothing stops immediately.
Resume subscriptionA cancelled-but-not-yet-ended buyer can undo with one click — “No charge today.”
Request refundOnly inside the refund window you set, with the product's self-serve refund opt-in enabled (off by default on every new product — buyers then cancel instead), and when your Onelo plan includes portal refunds. The modal states fees aren't refundable, warns access ends now, asks a reason (7 options) — then: “Your refund is on its way… 5–10 business days.” Outside the window the button is greyed with a plain explanation (“Refund window closed · purchase was N days ago”).
ReceiptsA list of every payment with date, amount (struck through if refunded), billing address, and a PDF / Receipt link straight from Stripe — if you allow it (see below).
Delete accountA quiet link, deliberately heavy to use: password re-entry + an “I understand” checkbox. It schedules deletion in 30 days, cancels subscriptions at period end (“no surprise charges”), signs them out everywhere, and emails them. Signing in before the date cancels it. (Buyers who signed up with Google/Apple — no password — can't use this path.)
Plan changes are always fair — by construction. The credit for unused time is simple day-math: paid amount × days remaining ÷ days in the period (20 unused days of a €100 month = €66.67 off the new plan). It's computed and locked on Onelo's side, so it can't be tampered with from the browser; upgrades charge only the prorated difference today, downgrades wait politely for the renewal. The one exception: time on a free trial isn't paid time, so it earns no credit.
A lapsed buyer isn't a dead end. With no active plan the portal says “Your subscription has ended. To use {your app} again, pick a plan below” and a View plans button takes them straight to your store as a recognised returning customer.

Your switches — what you control

In Paywall → Customer portal, five app-wide decisions shape every buyer's experience:

SettingWhat it doesDefault
Refund outcomeWhat a buyer's plan becomes when a full refund leaves them with no active plan. Mark as lapsed — the account stays but paid features lock. Enroll in free tier — they're auto-moved onto your free product (price 0) instead. “Enroll” is disabled until a free product exists in Products.Mark as lapsed
Default refund modeFull refunds 100% of what was paid within the window. Proportional refunds only the unused part — paid amount × time remaining ÷ period length. This is the default for products that don't set their own (each product can override it under Refunds & Legal).Full
Refund platform feeOn a refund, whether Onelo also returns its platform fee to your connected account. On — you're made whole on a cancelled sale. Off — Onelo keeps its processing fee (you absorb it).On
Session after refundOnly applies when the outcome is Mark as lapsed: after a refund the buyer is signed out everywhere and the next launch goes sign-in → store. Off = they stay signed in with paid features locked. Hidden when the outcome is free tier — there they keep an active plan, so signing them out would make no sense.On
Payment receiptsApp-wide default for the Receipt / PDF links. Per-product override under Products → Refunds & Legal → Receipt visibility.On
Receipt links point at Stripe-hosted documents. Each payment links to its Stripe invoice PDF when one exists (subscription renewals, or one-off charges you issue as Stripe invoices), otherwise the Stripe receipt page. If Stripe produced neither for a payment, no link shows for it. Turn the setting off when a connected provider (Fakturownia, inFakt, wFirma) already emails a proper VAT invoice — otherwise the buyer gets two documents for one purchase.

Three more levers live per product (Products → Refunds & Legal): the refund window in days (it drives the Request-refund button's availability — leave it empty to inherit the app-wide window; set 0 to disable self-service refunds for that product), allow self-serve refunds (off by default on every new product, subscriptions and one-time alike — buyers then cancel instead of refunding), and a per-product refund mode and receipt visibility that override the app-wide defaults above.

Open it from your app

The portal opens with one SDK call — Onelo signs the buyer in behind the scenes (a short-lived secure link tied to the signed-in user; no extra password). It ships in every SDK: Swift (macOS, iOS), JS / Web, Electron, React Native, Flutter and Android. The snippet below assumes the Onelo SDK is already initialised and the buyer is signed in — see the Auth guide if you haven't set that up yet.

Replace onelo_pk_live_YOUR_KEY with your app's publishable key from your app's SDK page in the dashboard. The API URL is already the correct Onelo endpoint — use it as-is.

Install

npm install github:onelo-tools/onelo-js

Initialize

import { Onelo } from '@onelo/js'

const onelo = new Onelo({
  apiUrl: 'https://api.onelo.tools',
  publishableKey: 'onelo_pk_live_YOUR_KEY',
})

Usage

// Open the hosted customer portal (manage subscription, cancel, receipts…).
// The user must be signed in. Resolves when they close the portal.
await onelo.customerPortal.open()

That embedded-window call covers most apps. Two more entry points exist for other UI patterns:

CallUse it when
openCustomerPortal(from:)The default — opens the portal in an embedded ASWebAuthenticationSession inside your app and returns when the buyer is done.
openCustomerPortalInBrowser()Hands off to the system browser instead — no presentation anchor needed.
initiateCustomerPortal()Returns the signed URL so you can present it yourself in custom UI.
PlatformStatus
Swift (macOS / iOS)Available — the calls above
JS / WebAvailable — onelo.customerPortal.open()
ElectronAvailable — await onelo.customerPortal.open()
React NativeAvailable — mount <CustomerPortalModal>, then call await onelo.customerPortal.open()
FlutterAvailable — push OneloCustomerPortalView
AndroidAvailable — registerLauncher + openCustomerPortal(...)
The link is personal and short-lived (about 10 minutes, single user) — so always open the portal via the SDK call, never copy a portal URL into an email or a website button. On native apps the portal returns the buyer to your app automatically when they're done.

Typical placement: a “Manage subscription” item in your app's account or settings menu. The portal inherits your Branding (logo, colors), so it feels like part of your product.

Next

Customer portal — Paywall — Onelo Docs