Settings & billing
Scheme settings control identity, structure, and configuration. Billing settings control the subscription plan, payment method, and access to paid features. Both are managed from the Settings page in the dashboard.
Scheme configuration
| Field | Notes |
|---|---|
strata_plan_number | The registered strata plan number (e.g., SP12345). Immutable after creation. |
name | Optional display name. Falls back to strata plan number if not set. |
slug | URL-safe identifier used in the dashboard path (e.g., /sp12345/tickets). Auto-generated from strata plan number. |
jurisdiction | Australian state or territory. Affects notice day calculations. Default: NSW. |
total_lots | Total number of lots in the scheme. Used for quorum and onboarding progress. |
address_line1 / suburb / state / postcode | Scheme postal address. Displayed in sidebar and notices. |
Buildings and lots
A scheme can have one or more buildings. Each building has an address, and belongs to exactly one scheme. Buildings contain lots.
Lots have:
lot_number— unique within the schemelot_type—residential,commercial,car_park,storage,utilityunit_entitlement— UE value. Used for weighted voting and levy calculations.building_id— which building the lot is in
Lot ownership is tracked separately in lot_ownerships, allowing historical ownership records when lots change hands. An owner can own multiple lots; a lot can only have one active owner at a time (owned_to = null).
Subscription plans
| Feature | Free | Paid |
|---|---|---|
| Matters | Up to 50 per scheme | Unlimited |
| Members | Up to 5 active | Unlimited |
| Meeting history | Last 12 months | Full history |
| Document history | Last 12 months | Full history |
| Meetings | Unlimited | Unlimited |
| Documents | Unlimited uploads | Unlimited uploads |
| AI minutes | Included | Included |
| Email notices | Included | Included |
| Support | Community | Priority |
Plans are managed via Stripe. The subscriptions table mirrors the Stripe subscription status (active, trialing, past_due, canceled). A scheme is considered paid if its subscription status is active or trialing.
No free plan — paywall after trial
There is no free tier. Every scheme starts a 30-day trial (status trialing) with the full product unlocked. When the trial lapses without a payment method, the subscription is promoted toexpired — server-side, by both the /api/cron/expire-trials job and theSubscriptionEnforcementFilter on first access.
An expired (or cancelled / past_due) scheme is read-only: GET requests still work so the committee can view their data and pay, but any write returns HTTP 402 (error: trial_expired, subscription_expired, or payment_past_due). Pricing is per-scheme by lot count, so each scheme carries its own subscription.
Billing and Stripe
Billing is handled by Stripe Checkout and the Stripe Customer Portal:
- Upgrade: redirects to a Stripe Checkout session. On success, the webhook handler creates/updates the
subscriptionsrecord. - Manage subscription: redirects to the Stripe Customer Portal for plan changes, payment method updates, and cancellation.
- Webhooks:
POST /api/stripe/webhookhandlescheckout.session.completed,customer.subscription.updated,customer.subscription.deleted, andinvoice.payment_failed.
The subscriptions table stores: stripe_customer_id, stripe_subscription_id,status, plan_id, current_period_end, and cancel_at_period_end.
Billing admin: the is_billing_admin flag on a membership record controls who can initiate checkout and access the Stripe portal. Typically the committee treasurer or chair.
Free trial
New schemes start a free trial on sign-up. During the trial, the subscription status is trialingand the full product is accessible. When the trial expires without a payment method, status transitions toexpired and the scheme becomes read-only until billing is set up (see “No free plan” above). The trial length is 30 days.
Scheme identity in the URL
The dashboard uses the scheme's slug in the URL path (e.g., /sp12345/tickets). The API also accepts the scheme's UUID directly. The SchemeHelper.ResolveAsync backend helper accepts both slug and UUID, so all API routes work with either form.
If a scheme has no slug (legacy or onboarding edge case), the UUID is used as the path segment.