The dashboard
/portal is a minimalist, mobile-responsive dashboard. On desktop it’s a sidebar layout; on mobile it collapses to a bottom-nav with a drawer. Five sections:
Overview
Balance, next charges, and active subscriptions at a glance.
Wallet
The global balance and its transaction history, with a top-up modal that opens the same inline checkout used everywhere. →
Subscriptions
Every subscription grouped by merchant, with cancel / pause / resume where the merchant allows.
Cards, transfer & direct debit
Saved cards (add / remove), an optional dedicated bank account for funding by transfer, and direct-debit mandates that let renewals pull straight from a bank account.
Listing across merchants
A customer’s subscriptions live in many tenants (one per merchant they’ve paid). The portal finds them all by the account’s email, then their plans and merchant names — in a fixed number of batched queries, never N+1: Four queries regardless of how many merchants or subscriptions —customers, subscriptions IN, plans IN, tenants IN — then grouped by tenant into per-merchant cards.
Live mode only. Real customers see
live. The portal reads exactly the live schema — it never merges test and live data.Ownership is enforced on every action
Reads are filtered by the account’s email. Actions (cancel, pause, resume, remove card) re-verify ownership before touching anything: A stranger with a valid session for a different email cannot read or mutate someone else’s subscription — the customer’s email is loaded from the subscription and compared against the session subject before any state change.What the customer can do
- See every subscription, grouped by merchant, with plan, next charge, and status.
- Top up the wallet — an arbitrary amount via the inline checkout, funding future renewals in advance. →
- Manage cards — add a card (a ₦100 top-up that saves it), or remove one (blocked if it’s the last card while a subscription is active). →
- Request a virtual account — a dedicated bank account, funded by transfer, crediting the wallet automatically. →
- Authorise a direct-debit mandate, bank-account permission that becomes a fallback rail once activated. →
- Set a transaction PIN and phone number: a self-service PIN (
GET/PUT/DELETE /portal/email/pin) and a Nigerian phone on the account, both authenticated by the portal session. - Pause / resume / cancel where the merchant allows.
x-portal-session header; every authenticated action re-issues a freshly-slid token in the response’s x-portal-session header, so an active session keeps extending as the customer uses it.
Sign-in captures location — for the merchant’s security alert
The dashboard login requests browser geolocation, but only to enrich a security alert — it is capture-only and never blocks. If the customer denies the prompt, the sign-in proceeds exactly the same; the coordinates are simply omitted. That capture feeds the merchant-side security alerts: a sign-in records the IP, the device, and (if granted) the coordinates onto theSession, and the business owner is emailed an alert with a Google-Maps link to the location. See the security model for the full alert set.
Next: the wallet that powers the top-up and renewal story.