Skip to content

Administration

The landlord panel

Only reachable in SaaS mode — a Standalone install 404s every URL under /landlord, as if it doesn't exist.

Last updated Aug 19, 2026 · 4 min read

Only reachable in SaaS mode — a Standalone install 404s every URL under /landlord, as if it doesn't exist.

Logging in

/landlord/login — a completely separate login from every tenant's own users. A landlord account (LandlordUser) has no role/permission system of its own and no relationship to any tenant's data; it exists purely to manage the platform itself.

The first landlord account is created for you automatically: whoever runs the install wizard in SaaS mode becomes both their tenant's Owner and the platform's first landlord, using the same email/password for both. There's no separate landlord sign-up page — additional landlord accounts (if you want more than one person managing the platform) currently have to be created directly:

php artisan tinker --execute '\App\Domain\Tenancy\Models\LandlordUser::create(["name" => "Name", "email" => "email@example.com", "password" => "a-strong-password"]);'

Tenants

The landlord panel's tenant list, showing every tenant's plan, user count, and status

/landlord/tenants lists every tenant on the platform — name, plan, user count, status, when they signed up. From here you can:

  • Create a tenant — same form as the install wizard's last step (business details + an Owner account), bootstrapped identically (same seeded currencies/roles/pipeline/tax rate/chart of accounts).
  • Suspend / Activate — toggles Tenant.status. While suspended, the tenant cannot use product modules (CRM, Sales, Inventory, Accounting, HR, AI), search, attachments, or the REST API. Owners/Admins with billing permission are redirected to Settings → Billing so they can reactivate; everyone else gets a 403. Profile, security, appearance, language, and billing itself stay reachable.
  • Assign a plan — attach one of your plans to a tenant. With platform Stripe configured (below), tenants can check out against that plan's Stripe Price; without Stripe, the assignment is record-keeping + plan limits (e.g. max users, HR) only.

Plans

/landlord/plans — define subscription plans (name, a Max Users cap, optional Stripe Price ID, price/currency display, HR enabled, AI token limit, active/inactive). The Max Users cap is enforced: once a tenant's team hits its plan's limit, adding another teammate (Settings → Team) is blocked until the plan is upgraded or someone's removed.

Stripe subscription billing

Platform Stripe keys live under Landlord → Settings. When configured:

  1. A plan needs a Stripe Price ID.
  2. The tenant Owner opens Settings → Billing, checks out via Stripe Checkout, and returns with an active subscription.
  3. Stripe webhooks (POST /stripe/webhook) keep subscription_status in sync (active, past_due, canceled, …).

Access policy:

State Product access
Tenant.status = active, subscription active or null Full access
subscription_status = past_due Grace by default — full access while Stripe retries payment. Set BILLING_BLOCK_PAST_DUE=true to hard-block like suspension.
Tenant.status = suspended (landlord suspend, or subscription deleted/canceled webhook) Hard lock — modules + API blocked; billing/profile still open for Owners

Public self-registration

If registration is open, /register-business lets anyone create their own tenant without you doing anything — it shows up in your tenant list the moment they finish the form. That path uses the same CreateTenantWithOwner bootstrap as the landlord create form and the installer.

In SaaS mode, Fortify's /register page redirects to /register-business (or 404s when registration is closed). Do not use /register for SaaS workspace signup.

Impersonation

From /landlord/tenants, Log in as on any tenant starts a session as that tenant's Owner (or its first user, if there's no Owner) — useful for support without asking the customer for their password. Your landlord session stays open in the background; Stop impersonating (visible anywhere in the tenant UI while impersonating) ends the borrowed session and returns you to the landlord panel. Every action taken while impersonating is attributed to the impersonated user in that tenant's own audit log, exactly as if they'd done it themselves — there's no separate impersonation trail beyond the application log.

Custom domains

From /landlord/tenants/{id}/domains, attach hostnames that should resolve to a tenant when platform_settings.allow_domain_resolution is enabled. Domains can be stored even when resolution is off, for later activation.

What the landlord panel is not

It's not a way to see into a tenant's data directly (no CRM records, invoices, stock, etc. browsable from the landlord side) — impersonation is the only way to see what a tenant sees, and it does so as that tenant's own user, not through a landlord-only data viewer.

← All Coravo – AI CRM & ERP Software for Growing Businesses documentation

We use cookies to understand how visitors use this site. Cookie Policy