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

/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:
- A plan needs a Stripe Price ID.
- The tenant Owner opens Settings → Billing, checks out via Stripe Checkout, and returns with an active subscription.
- Stripe webhooks (
POST /stripe/webhook) keepsubscription_statusin 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