WHITE-LABEL APP
This document is based on the white-label technical specification supplied for the Leaseora project. File paths, controller behavior, route coverage, class counts and deployment behavior should be validated against the current deployed branch and live configuration before they are treated as contractual, security-assurance or production-certification statements.
LEASEORA
KNOWLEDGE CENTER
|
WHITE-LABEL APP |
Build your brand. Keep your customers. Run on Leaseora infrastructure.
For real estate companies, corporate landlords, enterprise clients, platform administrators, developers, QA and DevOps teams.
|
Document control |
Value |
|
Document |
Leaseora White-Label App - Complete Technical Documentation |
|
Version |
1.0 |
|
Updated |
9 October 2026 |
|
Owner |
Leaseora Platform / Knowledge Center |
|
Platform |
Laravel API + Flutter Mobile + MySQL + Codemagic CI/CD |
|
Primary audience |
Enterprise customers, product teams, engineering, support, implementation and operations |
|
Documentation scope |
www.leaseora.com | support@leaseora.com
How to Use This Documentation
This guide has two complementary layers. Part I documents the white-label platform architecture and implementation patterns. Part II explains how those technical controls translate into real-estate-company features, automation, onboarding, security and deployment outcomes.
|
Audience |
Recommended sections |
|
Real estate company decision-makers |
Overview, Feature Automation Guide, Security & Data Isolation, Benefits Summary, Quick Start |
|
Implementation / support |
Database schema, Super Admin Management, Build & Deployment, Deployment Checklist |
|
Backend engineers |
Middleware, HasWhiteLabelScope, Branding Helper, Controller Matrix, API Reference |
|
Mobile engineers |
Flutter White-Label Configuration, Theme, KYC routing, Notifications, Reels, Build variables |
|
QA / security |
Identity Resolution Chain, route scoping, cross-company guardrails, post-deploy verification, fail-closed behavior |
|
DevOps |
Codemagic pipeline, environment variables, build status, deployment verification |
|
Terminology |
Table of Contents
|
PART I - Technical Architecture |
||
|
1 |
System Overview |
4 |
|
2 |
Architecture Diagram |
5 |
|
3 |
Database Schema |
6 |
|
4 |
Backend: Middleware Chain |
7 |
|
5 |
Backend: Core Concern - HasWhiteLabelScope |
8 |
|
6 |
Backend: WhiteLabelBrandingHelper |
10 |
|
7 |
Backend: Controllers by Feature |
11 |
|
8 |
Backend: Notifications & Email Branding |
12 |
|
9 |
Flutter Mobile App |
14 |
|
10 |
Build System (Codemagic) |
15 |
|
11 |
Super Admin Management |
16 |
|
12 |
API Reference |
16 |
|
13 |
Data Flow - End to End |
18 |
|
14 |
Deployment Checklist |
19 |
|
PART II - Real Estate Company Integration & Automation Guide |
||
|
15 |
What the Leaseora White-Label App Is |
21 |
|
16 |
Feature Automation Guide |
21 |
|
17 |
Registration & KYC - Automated Onboarding |
24 |
|
18 |
Email & Notification Branding |
25 |
|
19 |
Security & Data Isolation |
26 |
|
20 |
Build, Release & Lifecycle Management |
26 |
|
21 |
Benefits for Real Estate Companies |
27 |
|
22 |
Quick Start for a New Real Estate Company |
27 |
|
23 |
Operations, Monitoring & Troubleshooting |
28 |
|
24 |
File Inventory |
29 |
|
25 |
Glossary |
30 |
|
26 |
Knowledge Center Publishing Notes |
30 |
|
27 |
Contact & Support |
31 |
Part I follows the supplied 14-section technical structure. Part II adds the operational and feature-automation guide required for real estate companies and Knowledge Center readers.
PART I | TECHNICAL ARCHITECTURE
1. System Overview
Leaseora is a full-stack PropTech SaaS platform that enables corporate real estate companies to launch branded Flutter mobile applications powered by the Leaseora backend. Each white-label deployment presents the real estate company as the customer-facing brand while sharing Leaseora infrastructure, APIs, payment orchestration, document services, AI capabilities, notifications and operational data services.
A white-label build is not merely a logo swap. The runtime request carries a company identity, the backend resolves that identity to the owning company and landlord records, feature controllers apply server-side query scoping, payments enforce company ownership checks, and notifications and emails resolve the correct brand dynamically.
|
Capability |
Implementation detail |
|
Custom branding |
App name, logo, primary colour, tagline, support email, support phone and website can be configured per deployment. |
|
Scoped data |
Users see properties, leases, mortgages, land, WeBuild projects, reels, documents and related records belonging to the linked real estate company. |
|
Scoped notifications |
In-app and email notifications resolve the company identity and are filtered so unrelated landlord messages do not appear in the white-label app. |
|
Scoped payments |
Rent, wallet and service-payment flows validate the landlord/company relationship and block cross-company transactions. |
|
Nigeria BVN KYC |
The supplied design routes Nigerian white-label users to a Flutterwave BVN + ID document flow instead of the main-app Veriff path. |
|
Independent CI/CD |
Each app is compiled by Codemagic with company-specific dart-defines and can be released independently. |
|
Core design principle |
2. Architecture Diagram
The white-label request lifecycle has three layers: the branded Flutter client, the Laravel API scoping and feature layer, and the shared MySQL data model. The X-Company-Slug header is the identity bridge between the compiled mobile app and the backend request context.
2.1 Reference Architecture - Text View
FLUTTER WHITE-LABEL APP
WhiteLabelConfig.companySlug = "bemztouch"
Every API request -> X-Company-Slug: bemztouch
|
| HTTPS
v
LARAVEL API (leaseora.com/api)
1. WhiteLabelScopeMiddleware
- reads X-Company-Slug or company_slug
- resolves active white_label_clients row
- binds wl.company_id, wl.slug, wl.active, wl.client
2. HasWhiteLabelScope
- resolves company -> corporate landlord -> landlord user
- applies server-side filters
3. Feature controllers
- properties, lease, mortgage, land, WeBuild, wallet, etc.
4. WhiteLabelBrandingHelper
- resolves name, email, logo, colour, tagline, website
|
v
MYSQL
white_label_clients -> companies -> corporate_landlords -> users
users.id is the common landlord_id on many feature records
3. Database Schema
3.1 white_label_clients
|
Column |
Type |
Purpose |
|
id |
bigint PK |
Primary key |
|
slug |
varchar(100) UNIQUE |
URL-safe deployment identifier, e.g. bemztouch or apdc |
|
app_name |
varchar(255) |
Display name for the branded app |
|
agency_id |
bigint FK |
References companies.id - owning company |
|
is_active |
tinyint |
1 active; 0 suspended |
|
logo_url |
varchar |
Public logo URL |
|
primary_color |
varchar(10) |
Hex brand colour |
|
support_email |
varchar |
Customer-facing support sender/address |
|
support_phone |
varchar |
Support phone |
|
website_url |
varchar |
Company website |
|
app_tagline |
varchar |
Short tagline |
|
codemagic_app_id |
varchar |
Codemagic application identifier |
|
codemagic_workflow_id |
varchar |
Codemagic workflow identifier |
|
build_status |
varchar |
pending / building / success / failed |
|
last_build_at |
timestamp |
Most recent build trigger time |
3.2 Related Tables
|
Table |
Relevant columns |
White-label purpose |
|
companies |
id, name, corporate_landlord_id, registration_number |
agency_id resolves to the company; corporate_landlord_id begins the landlord identity chain. |
|
corporate_landlords |
id, user_id, company_name |
Maps the company relationship to the actual landlord user account. |
|
users |
id, registered_via, kyc_verified, kyc_method, kyc_verified_at, bvn |
users.id is the landlord_id on many records; registered_via preserves the source white-label slug for queue-safe branding. |
|
notifications |
sender_id, data JSON |
Supports sender ID and sender_slug based white-label notification filtering. |
3.3 Critical ID Resolution Chain
white_label_clients.agency_id
-> companies.id
-> companies.corporate_landlord_id
-> corporate_landlords.id
-> corporate_landlords.user_id
-> users.id
users.id = landlord_id on many feature records
(properties, sales, mortgages, land, WeBuild, reels, maintenance and related flows)
|
Why this matters |
4. Backend: Middleware Chain
File: app/Http/Middleware/WhiteLabelScopeMiddleware.php
WhiteLabelScopeMiddleware is the entry point for routes that support white-label context. It resolves the request slug, finds an active WhiteLabelClient, and binds a per-request identity context into the Laravel service container.
$slug = $request->header('X-Company-Slug')
?? $request->query('company_slug');
$client = WhiteLabelClient::where('slug', $slug)
->where('is_active', true)
->first();
if ($client) {
app()->instance('wl.company_id', (int) $client->agency_id);
app()->instance('wl.slug', $client->slug);
app()->instance('wl.active', true);
app()->instance('wl.client', $client);
}
4.1 Route Application
Route::middleware([
\App\Http\Middleware\WhiteLabelScopeMiddleware::class
])->group(function () {
// white-label aware route groups
});
4.2 Route Coverage
|
Route group |
Representative prefix / endpoint |
Capability |
|
Public |
/api/public/tenant/listings |
Rental listings |
|
Public |
/api/public/tenant/listings/{slug} |
Listing detail |
|
Authenticated |
/api/tenant/listings, /apply, /book-inspection |
Rental applications and inspections |
|
Public + Auth |
/api/public/property-sales/listings; /api/property-sales/* |
Property sales |
|
Public / Auth |
/api/public/mortgage/products; /api/mobile/mortgage/* |
Mortgage |
|
Public / Auth |
/api/public/land/browse; /api/mobile/land/* |
Land |
|
Public / Auth |
/api/public/we-build/projects; /api/mobile/we-build/* |
WeBuild |
|
Authenticated |
/api/maintenance, /api/maintenance-requests |
Maintenance |
|
Authenticated |
/api/lease-angel/* |
Lease Angel |
|
Authenticated |
/api/tenant/inquiry/* |
Inquiries |
|
Authenticated |
/api/notifications/* |
Notifications |
|
Authenticated |
/api/wallet/* |
Wallet and transactions |
|
Authenticated |
/api/leases/* |
Lease management |
|
Authenticated |
/api/rent-payments/* |
Rent payment |
|
Authenticated |
/api/payments/* |
General payments |
|
Authenticated |
/api/documents/* |
Documents |
|
Public + Auth |
/api/reels/* |
Media reels |
5. Backend: Core Concern - HasWhiteLabelScope
File: app/Http/Controllers/Concerns/HasWhiteLabelScope.php
Feature controllers use this concern to read the request-scoped company binding, resolve the correct landlord identifiers and apply the appropriate query constraint.
5.1 wlCompanyId()
protected function wlCompanyId(): ?int
{
return app('wl.company_id') ?? null;
}
5.2 wlLandlordUserId()
protected function wlLandlordUserId(int $companyId): ?int
{
static $cache = [];
if (!array_key_exists($companyId, $cache)) {
$company = \App\Models\Company::select('corporate_landlord_id')
->find($companyId);
if ($company && $company->corporate_landlord_id) {
$corp = \App\Models\CorporateLandlord::select('user_id')
->find($company->corporate_landlord_id);
$cache[$companyId] = $corp ? (int) $corp->user_id : null;
} else {
$cache[$companyId] = null;
}
}
return $cache[$companyId];
}
5.3 wlCorporateLandlordId()
protected function wlCorporateLandlordId(int $companyId): ?int
{
static $cache = [];
if (!array_key_exists($companyId, $cache)) {
$company = \App\Models\Company::select('corporate_landlord_id')
->find($companyId);
$cache[$companyId] = $company
? (int) $company->corporate_landlord_id
: null;
}
return $cache[$companyId];
}
5.4 applyWlCompanyScope()
protected function applyWlCompanyScope($query, string $column): void
{
$companyId = $this->wlCompanyId();
if ($companyId === null) return;
if ($column === 'landlord_id') {
$userId = $this->wlLandlordUserId($companyId);
$userId !== null
? $query->where($column, $userId)
: $query->whereRaw('1 = 0');
} elseif (in_array($column, ['corporate_landlord_id', 'company_id'])) {
$corpId = $this->wlCorporateLandlordId($companyId);
$corpId !== null
? $query->where($column, $corpId)
: $query->whereRaw('1 = 0');
}
}
|
Fail-closed behavior |
|
Critical design decision |
6. Backend: WhiteLabelBrandingHelper
File: app/Http/Concerns/WhiteLabelBrandingHelper.php
This helper centralizes dynamic identity resolution for emails and notifications. It supports request-context lookup by company ID and queue-safe lookup by a user's registered_via slug.
6.1 Branding by Company ID
protected function wlBranding(?int $companyId = null): array
{
$id = $companyId ?? app('wl.company_id') ?? null;
if (!$id) return $this->defaultBranding();
return Cache::remember("wl_branding_{$id}", 600, function () use ($id) {
$client = WhiteLabelClient::where('agency_id', $id)
->where('is_active', true)
->first();
return $client ? [
'name' => $client->app_name,
'email' => $client->support_email,
'logo' => $client->logo_url,
'color' => $client->primary_color,
'tagline' => $client->app_tagline,
'website' => $client->website_url,
'slug' => $client->slug,
] : $this->defaultBranding();
});
}
6.2 Queue-Safe Branding by User
protected function wlBrandingForUser(User $user): array
{
$slug = $user->registered_via ?? null;
if (!$slug || $slug === 'leaseora') return $this->defaultBranding();
return Cache::remember("wl_branding_slug_{$slug}", 600, function () use ($slug) {
$client = WhiteLabelClient::where('slug', $slug)
->where('is_active', true)
->first();
return $client ? [ /* branded fields */ ] : $this->defaultBranding();
});
}
6.3 Default Leaseora Branding
private function defaultBranding(): array
{
return [
'name' => config('app.name', 'Leaseora'),
'email' => config('mail.from.address'),
'logo' => null,
'color' => '#1E3A8A',
'slug' => 'leaseora',
];
}
7. Backend: Controllers by Feature
The following matrix summarizes the controller-level white-label controls described in the supplied implementation specification. It is the quickest engineering reference for where isolation is applied and which identifier is used.
|
Feature |
Controller |
Scope / guard |
Key behavior |
|
Rental listings |
PropertyController.php |
landlord_id |
tenantListings() scopes properties in whereHas(property, ...). |
|
Property sales |
PropertySaleController.php |
landlord_id |
Sale listings, applications and purchases remain tied to WL company properties. |
|
Mortgage |
MortgageMobileController.php |
landlord_id |
Products and applications use landlord user resolution. |
|
Land |
LandController.php |
landlord_id |
Browse and applications scoped to company landlord. |
|
WeBuild |
WeBuildMobileController.php |
landlord_id |
Browse, detail, bookings, payment schedule and payment history scoped. |
|
Lease / My Lease |
LeaseController.php |
corporate_landlord_id |
Leases rely on populated corporate landlord relation. |
|
Rent payments |
RentPaymentController.php |
corporate_landlord_id |
Rent payment route group is WL middleware protected. |
|
Wallet |
WalletController.php |
landlord_id + ownership checks |
Transactions/statistics filtered; payService and payRent validate company ownership. |
|
Maintenance |
MaintenanceController.php |
landlord_id |
Listing plus pending/in-progress/completed stats use the same base scope. |
|
Lease Angel |
LeaseAngelController.php |
landlord_id |
Find tenant, create payment, history and property search prevent cross-company gifting. |
|
Inquiries |
PropertyInquiryController.php |
participant landlord ID |
Lists rooms containing company landlord; startInquiry() returns 403 for outside respondent. |
|
Documents |
DocumentController.php |
resolved landlord user ID |
sharedByLandlordQuery() backs list, stats, request, show and download. |
|
Notifications |
NotificationController.php |
sender_id OR data.sender_slug |
Two-arm filter supports legacy/custom-insert and Laravel notify() paths. |
|
Media reels |
ReelController.php |
landlord_id |
feed, publicShow, saved, search are WL scoped. |
|
BVN verification |
BvnVerificationController.php |
white-label + Nigerian user route |
Flutterwave BVN lookup, >=80% fuzzy name match and ID document upload. |
7.1 Feature Notes and Guardrails
Property listings
Public and authenticated rental journeys filter against the owning landlord. The tenant journey remains Browse -> Apply -> Inspection -> Offer / Lease.
Wallet
In addition to list filtering, payment operations validate the requested landlord or lease against the white-label company before executing a transaction.
Lease Angel
Tenant discovery and rent gifting are deliberately restricted to tenants/properties under the same company context.
Inquiries
The participant set is a security boundary: the app cannot start a property inquiry with a landlord outside the resolved company.
Notifications
The filter is applied not only to list results but also to unread counts, mark-all-read, mark-one-read and deletion operations.
Documents
Access is scoped through a reusable landlord-aware query so index, show and download behavior remain consistent.
8. Backend: Notifications & Email Branding
8.1 Notification Payload Pattern
The supplied specification states that notification classes use WhiteLabelBrandingHelper and persist company-facing sender metadata so the mobile app can render the correct identity and the backend can filter by sender slug.
public function toArray(object $notifiable): array
{
$brand = $notifiable instanceof User
? $this->wlBrandingForUser($notifiable)
: $this->wlBranding($this->wlCompanyId);
return [
// feature-specific data ...
'sender_name' => $brand['name'],
'sender_logo' => $brand['logo'],
'sender_color' => $brand['color'],
'sender_slug' => $brand['slug'],
];
}
8.2 Mail Sender and Subject
return (new MailMessage)
->from($brand['email'], $brand['name'])
->subject($brand['name'] . ' - Notification Subject');
8.3 Queue-Safe Dispatch
$wlCompanyId = app()->bound('wl.company_id')
? app('wl.company_id')
: null;
$tenant->notify(
new LeasePaymentReceivedNotification($lease, $payment, $wlCompanyId)
);
8.4 Mail Inventory
|
Feature |
Mail groups / examples |
|
Lease / Rent |
app/Mail/Lease/ - 11 supplied files |
|
Mortgage |
app/Mail/Mofi/ - 10 supplied files plus MortgageApprovalNotification.php |
|
WeBuild |
app/Mail/WeBuild/ - 4 supplied files |
|
Wallet |
WalletBalanceUpdated.php; WalletInvoiceMail.php |
|
Maintenance |
MaintenanceBankTransferAlertMail.php; MaintenanceCostSummaryMail.php; MaintenancePaymentReceivedMail.php |
|
Documents |
DocumentFulfilledMail.php; DocumentRequestedMail.php |
|
Registration |
AgencyRegistrationConfirmationMail.php; VerifyEmail.php |
|
Password reset |
PasswordResetNotification.php |
|
Generic |
GenericNotificationMail.php |
8.5 Branded Email Layout
File: resources/views/emails/layouts/branded.blade.php. The template accepts brand name, logo, primary colour, support email, tagline and website values for the email header, buttons and footer.
8.6 registered_via Capture
$slug = $request->header('X-Company-Slug');
if ($slug && $slug !== 'leaseora') {
$user->update(['registered_via' => $slug]);
}
|
Why registered_via exists |
9. Flutter Mobile App
9.1 WhiteLabelConfig
File: mobile/lib/core/constants/white_label_config.dart
class WhiteLabelConfig {
static const String companySlug = String.fromEnvironment(
'COMPANY_SLUG',
defaultValue: 'leaseora',
);
static const bool isWhiteLabel = companySlug != 'leaseora';
static const String appName = String.fromEnvironment(
'APP_NAME',
defaultValue: 'Leaseora',
);
static const String primaryColor = String.fromEnvironment(
'PRIMARY_COLOR',
defaultValue: '#1E3A8A',
);
}
9.2 API Header Injection
File: mobile/lib/core/network/api_client.dart. A Dio interceptor adds the company slug to white-label API calls.
if (cfg.isWhiteLabel &&
cfg.companySlug.isNotEmpty &&
cfg.companySlug != 'leaseora') {
options.headers['X-Company-Slug'] = cfg.companySlug;
}
9.3 AppConfigService
· Loaded at app startup as a singleton.
· Exposes isWhiteLabel, companySlug, appName and primaryColor.
· Provides a single runtime source for white-label-aware widgets and navigation decisions.
9.4 WLColors Theme Helper
static Color primary(BuildContext context) {
if (AppConfigService.instance.isWhiteLabel) {
return Color(int.parse(
AppConfigService.instance.primaryColor.replaceAll('#', '0xFF')
));
}
return AppTheme.primaryColor;
}
9.5 KYC Router Guard
final kycVerified = currentUser?['kyc_verified'] == true;
if (profileComplete && !kycVerified && !isAnyKycRoute) {
final country = (currentUser?['country'] ?? '').toString().toLowerCase();
final isNigerian = country == 'nigeria' || country == 'ng';
final isWhiteLabel = AppConfigService.instance.isWhiteLabel;
if (isNigerian && isWhiteLabel) {
return '/bvn-verification';
}
return '/kyc-verification';
}
9.6 BVN Verification Page
1. Tenant enters an 11-digit BVN.
2. App submits POST /profile/bvn-verify.
3. Backend requests Flutterwave BVN KYC lookup and compares the returned name to the registered name using the supplied fuzzy matching threshold.
4. Tenant selects and uploads an identity document.
5. App submits POST /profile/bvn-verify/id-document.
6. When both verification conditions are satisfied, the user is marked verified and routed to the tenant home experience.
9.7 Notification Hub Branding
The notification model reads sender_name, sender_logo and sender_color from the backend. When a logo URL exists the tile uses the company logo; otherwise it renders a colour avatar using the sender name initial.
9.8 Reels Branding
// App bar
AppConfigService.instance.isWhiteLabel
? 'Media Reels'
: 'Leaseora Reels';
// Main navigation tab
label: AppConfigService.instance.isWhiteLabel
? 'Media Reels'
: 'Reels';
10. Build System (Codemagic)
10.1 Compile-Time Variables
flutter build appbundle \
--dart-define=COMPANY_SLUG=bemztouch \
--dart-define=APP_NAME="BemzTouch" \
--dart-define=PRIMARY_COLOR=#FF6B00 \
--dart-define=SECONDARY_COLOR=#1E3A8A \
--dart-define=THEME_PRESET=modern
10.2 Laravel Build Trigger
File: app/Http/Controllers/WhiteLabelController.php - triggerBuild(). The supplied implementation sends company-specific build variables such as COMPANY_SLUG, APP_NAME and PRIMARY_COLOR to the configured Codemagic workflow.
10.3 codemagic.yaml
environment:
vars:
COMPANY_SLUG: ${COMPANY_SLUG}
APP_NAME: ${APP_NAME}
PRIMARY_COLOR: ${PRIMARY_COLOR}
|
Operational note |
11. Super Admin Management
The supplied white-label management design provides centralized control over client records, build configuration, activation status and user/company associations.
|
Capability |
Admin behavior |
|
White-label client CRUD |
Create and manage white_label_clients records at /superadmin/white-label-clients. |
|
Activation / suspension |
is_active controls whether the middleware resolves the deployment as active. |
|
Company association |
User profile can display linked company white-label slugs and status. |
|
Build trigger |
Admin can initiate a Codemagic build for a configured client. |
|
Build monitoring |
build_status and last_build_at provide operational state. |
|
Eager loading |
UserController loads companies.whiteLabelClients to avoid repeated per-company queries. |
11.1 Company Model Relationship
public function whiteLabelClients()
{
return $this->hasMany(
\App\Models\WhiteLabelClient::class,
'agency_id'
);
}
11.2 UserController Eager Loading
$user->load([
'companies',
'companies.whiteLabelClients',
// other relations ...
]);
12. API Reference
|
Authentication model |
Tenant - Property Listings
GET /api/public/tenant/listings
GET /api/public/tenant/listings/{slug}
GET /api/tenant/listings
POST /api/tenant/listings/{id}/apply
POST /api/tenant/listings/{id}/book-inspection
Tenant - Reels
GET /api/reels
GET /api/reels/search?q=...
GET /api/reels/{id}
POST /api/reels/{id}/view
POST /api/reels/{id}/guest-like
POST /api/reels/{id}/like
POST /api/reels/{id}/save
GET /api/reels/saved
Tenant - Notifications
GET /api/notifications
GET /api/notifications/unread-count
POST /api/notifications/mark-all-read
POST /api/notifications/{id}/mark-read
DELETE /api/notifications/{id}
Tenant - Wallet
GET /api/wallet
GET /api/wallet/transactions
POST /api/wallet/pay-service
POST /api/wallet/pay-rent
Tenant - KYC / BVN (Nigerian white-label flow)
POST /api/profile/bvn-verify
POST /api/profile/bvn-verify/id-document
Landlord - Reel Management
GET /api/landlord/reels
POST /api/landlord/reels
PUT /api/landlord/reels/{id}
DELETE /api/landlord/reels/{id}
12.1 Required Request Headers
|
Header |
When used |
Purpose |
|
Authorization: Bearer <token> |
Authenticated routes |
Laravel Sanctum authentication. |
|
X-Company-Slug: <slug> |
White-label app requests |
Selects the company context used by middleware and controller scoping. |
|
Content-Type |
As required by endpoint |
JSON for normal requests; multipart for document uploads. |
13. Data Flow - End to End
13.1 Rental Listing Request Lifecycle
1. Flutter BEMZTOUCH app calls:
GET /api/public/tenant/listings
X-Company-Slug: bemztouch
2. Route executes WhiteLabelScopeMiddleware.
3. Middleware resolves active white_label_clients row:
slug=bemztouch -> agency_id=20
binds wl.company_id=20, wl.slug=bemztouch
4. PropertyController::tenantListings() applies WL scope.
5. wlLandlordUserId(20):
Company 20 -> corporate_landlord_id 3
CorporateLandlord 3 -> user_id 7
6. Query adds landlord_id = 7.
7. JSON response contains only records owned by landlord user 7.
8. Flutter renders the company-scoped listing feed with the compiled WL theme.
13.2 Notification Dispatch Lifecycle
1. Landlord confirms a payment for tenant user 1234.
2. Controller captures wl.company_id before queue dispatch.
3. Notification is queued with wlCompanyId.
4. Queue resolves branding from the user registered_via slug or explicit company ID.
5. Email sender, subject, logo, colour and support identity use the WL brand.
6. Notification data stores sender_name/logo/color/slug.
7. GET /api/notifications with X-Company-Slug filters to the matching sender ID or sender_slug.
8. Flutter renders the company logo/avatar and branded notification content.
13.3 Data Isolation Invariant
|
Invariant |
14. Deployment Checklist
14.1 Database Setup
-- 1. Verify white-label registry
SELECT id, slug, agency_id, is_active, app_name,
support_email, logo_url, primary_color
FROM white_label_clients
WHERE slug = 'bemztouch';
-- 2. Verify company -> landlord chain
SELECT c.id, c.name, c.corporate_landlord_id,
cl.user_id AS landlord_user_id
FROM companies c
LEFT JOIN corporate_landlords cl
ON cl.id = c.corporate_landlord_id
WHERE c.id = (
SELECT agency_id
FROM white_label_clients
WHERE slug = 'bemztouch'
);
-- 3. Verify inventory ownership
SELECT COUNT(*)
FROM properties
WHERE landlord_id = <landlord_user_id>;
14.2 Environment Variables
# Flutterwave - BVN verification
FLUTTERWAVE_SECRET_KEY=<managed-secret>
# Default Leaseora sender (used when WL branding is not resolved)
MAIL_FROM_ADDRESS=noreply@leaseora.com
MAIL_FROM_NAME=Leaseora
|
Secret-management rule |
14.3 Codemagic Trigger Payload
{
"appId": "<codemagic-app-id>",
"workflowId": "<workflow-id>",
"environment": {
"variables": {
"COMPANY_SLUG": "bemztouch",
"APP_NAME": "BemzTouch",
"PRIMARY_COLOR": "#FF6B00"
}
}
}
14.4 Post-Deploy Verification
curl -H "X-Company-Slug: bemztouch" \
"https://leaseora.com/api/public/tenant/listings?test_debug=1"
# Expected diagnostic intent:
# - middleware resolved the correct slug/client
# - company ID is bound
# - applyWlCompanyScope resolved the intended landlord ID
# - no unrelated landlord records are returned
|
Check |
Pass condition |
|
Brand identity |
App name, icon, logo, colours, support identity and store metadata match approved client assets. |
|
Company scoping |
Public feeds contain only expected company records. |
|
Authenticated scoping |
Lease, wallet, maintenance, documents and inquiries remain company-bound. |
|
Payment guards |
Attempted cross-company landlord/lease payment is rejected. |
|
Notification isolation |
Only the company sender appears; unread/read/delete actions cannot touch unrelated notifications. |
|
KYC routing |
Nigerian WL test account follows the configured BVN path; other users follow the intended default KYC path. |
|
Email branding |
Verification, password reset and operational emails use resolved company identity. |
|
Build metadata |
build_status and last_build_at reflect the deployed artifact. |
|
Rollback readiness |
Previous production build, signing configuration and release notes are retained. |
PART II | REAL ESTATE COMPANY INTEGRATION & AUTOMATION GUIDE
15. What the Leaseora White-Label App Is
The Leaseora White-Label App lets a real estate company launch its own branded customer mobile experience without building the underlying property, payment, lease, document, maintenance and engagement infrastructure from scratch. The company remains the customer-facing brand; Leaseora provides the operating technology layer.
Customers can download an app carrying the real estate company name, logo, colours and support identity. Behind that experience, the application uses the same Leaseora backend and feature services, while the company slug and backend scope controls isolate the relevant company data.
15.1 One Platform, Many Brands
Real Estate Company
-> Leaseora company account
-> White-label client record + unique slug
-> Codemagic compiles company-branded Flutter app
-> Customer installs company app
-> Every request carries X-Company-Slug
-> Backend resolves company / landlord context
-> Only company-authorized data and operations are returned
15.2 What the Company Receives
|
Deliverable |
Business meaning |
|
Branded mobile app |
Company-facing iOS/Android experience with approved app identity and theme. |
|
Scoped customer experience |
Customers interact with the company portfolio and services rather than a mixed marketplace feed. |
|
Branded communications |
Operational emails and in-app notifications can resolve the company sender identity. |
|
Automated workflows |
Applications, payments, leases, documents, maintenance and notifications connect to backend workflows. |
|
Operational dashboard |
Company teams use Leaseora management tools and analytics to operate the portfolio. |
|
Build pipeline |
Codemagic can produce independent company-specific artifacts from the shared codebase. |
16. Feature Automation Guide
The feature descriptions below translate the technical scoping model into the customer and company experience. Availability depends on the enabled Leaseora modules, subscription/enterprise scope, country, gateway configuration and deployment readiness.
16.1 Find Properties - Rental Listings
Customers browse and apply for the company's rental inventory.
|
Automation / scoping |
Listing APIs filter to the company landlord; applications route to company workflows; inspection booking, status notifications and lease progression remain within the same company context. |
|
Typical journey |
Browse -> Shortlist -> Apply -> Schedule inspection -> Offer -> Lease. |
16.2 My Lease - Digital Lease Management
Customers view active leases, schedules and lease history.
|
Automation / scoping |
Lease queries are company-scoped; due-date reminders, renewal requests, documents and status changes can be automated and surfaced in the management dashboard. |
|
Typical journey |
Lease record -> schedule -> reminders -> payment -> renewal / closure. |
16.3 Pay Rent & Bills
Customers pay rent, service charges and enabled bills.
|
Automation / scoping |
Gateway processing records payments, issues receipts and notifications, and reconciles activity. Server-side ownership checks prevent payment to an unrelated company context. |
|
Typical journey |
Select obligation -> pay -> gateway response -> ledger/receipt -> notification. |
16.4 Wallet - Digital Property Wallet
Customers maintain a wallet used for approved property-related payments.
|
Automation / scoping |
Transaction lists and statistics are scoped; service/rent payment validates the owning landlord; invoices and balance updates can be branded. |
|
Typical journey |
Top up / balance -> choose service -> validate company -> pay -> history. |
16.5 Property for Sale
Customers browse and purchase sale inventory offered by the company.
|
Automation / scoping |
Sale listings are company-scoped; offer and application flows route to the sales team; payment and sale-state notifications remain tied to the listing owner. |
|
Typical journey |
Discover -> offer/apply -> due diligence -> deposit/installments -> completion. |
16.6 Mortgage
Customers view mortgage products and submit applications.
|
Automation / scoping |
Mortgage products and applications are filtered to the configured landlord context; approval/rejection communications and repayment schedules remain company-linked. |
|
Typical journey |
Product -> application -> review -> offer -> repayment / servicing. |
16.7 Land - Land Sales
Customers browse land parcels and progress through purchase/application workflows.
|
Automation / scoping |
Land inventory and applications are scoped; payment, approval, documentation and completion events remain linked to the owning company. |
|
Typical journey |
Browse parcel -> apply/reserve -> pay -> documents -> completion. |
16.8 We Build For You
Customers commission or participate in construction projects offered by the company.
|
Automation / scoping |
Projects, bookings, payment schedules, payment history and status updates are filtered to company-owned WeBuild records. |
|
Typical journey |
Select project -> book -> milestones -> payments -> progress -> handover. |
16.9 Maintenance Requests
Customers log maintenance issues for company-managed assets.
|
Automation / scoping |
Requests and summary counts are company-scoped; status updates, cost/payment requests and completion notifications can be automated. |
|
Typical journey |
Report -> triage -> assign -> in progress -> resolve -> close. |
16.10 Lease Angel - Rent Gifting
An approved user can pay rent on behalf of another customer.
|
Automation / scoping |
Tenant search, property validation, payment creation and history are restricted to the same company/landlord. Cross-landlord gifting is blocked. |
|
Typical journey |
Find eligible tenant -> verify lease/company -> pay -> receipt -> history. |
16.11 My Documents
Customers access permitted tenancy, KYC, receipt and operational documents.
|
Automation / scoping |
Document list, requests, statistics, show/download operations use landlord-aware filtering; sharing and fulfilment notifications can be branded. |
|
Typical journey |
Request/share -> upload/fulfil -> permission check -> view/download -> audit. |
16.12 Inquiries - In-App Messaging
Customers contact the company about a property or service.
|
Automation / scoping |
Conversation lists require the resolved landlord participant. A start-inquiry request outside the company returns 403. |
|
Typical journey |
Open property/service -> start inquiry -> company response -> tracked conversation. |
16.13 Notifications - Fully Branded
Customers receive in-app and email alerts under the deployment identity.
|
Automation / scoping |
Notification filtering uses sender_id and sender_slug; tile branding uses sender logo/name/colour; read/delete operations use the same scope. |
|
Typical journey |
Event -> notification payload -> company filter -> customer display. |
16.14 Media Reels
Customers view short property videos and media content.
|
Automation / scoping |
Feed, search, saved and public-show results are company-scoped; the white-label navigation label changes to Media Reels. |
|
Typical journey |
Publish -> discover -> view/like/save -> analytics. |
17. Registration & KYC - Automated Onboarding
17.1 Standard Registration
1. Customer registers through the branded app with the required account credentials.
2. The app includes X-Company-Slug in registration traffic and the backend stores registered_via for a non-Leaseora deployment.
3. Email verification is generated using the resolved company brand where configured.
4. Customer completes profile information.
5. KYC route is selected based on the supplied router logic and customer context.
6. On successful KYC, the user continues into the white-label customer home experience.
17.2 Nigerian White-Label BVN Flow
|
Stage |
System action |
Result |
|
1. BVN input |
Validate 11-digit input and POST /profile/bvn-verify. |
BVN lookup request submitted. |
|
2. Provider lookup |
Flutterwave BVN endpoint returns identity details. |
Provider identity data available for comparison. |
|
3. Name matching |
Supplied logic uses >=80% fuzzy similarity. |
Pass/fail identity match. |
|
4. ID document |
Customer uploads passport, national ID, driver licence or configured type. |
Identity document stored for review/verification flow. |
|
5. Completion |
When required BVN + document conditions are met, kyc_verified can be set. |
Customer exits KYC gate and enters app. |
|
Production verification requirement |
18. Email & Notification Branding
The white-label messaging layer is designed so operational communication resolves the customer-facing company identity rather than hard-coding Leaseora branding. The system uses the active WhiteLabelClient record and/or the user registered_via slug to determine the brand.
|
Trigger |
Illustrative sender identity |
Illustrative subject style |
|
Registration / verification |
Company support or no-reply identity |
Welcome to <Brand> - Verify Your Email |
|
Password reset |
Company support identity |
Reset Your <Brand> Password |
|
Lease created |
Company support identity |
<Brand> - Your Lease Agreement is Ready |
|
Rent payment confirmed |
Company support identity |
<Brand> - Payment Received |
|
Maintenance update |
Company support identity |
<Brand> - Maintenance Request Update |
|
Mortgage update |
Company support identity |
<Brand> - Mortgage Application Update |
|
Document shared |
Company support identity |
<Brand> - Document Available for Download |
|
Mail authentication |
19. Security & Data Isolation
White-label isolation is designed as a server-side control, not a visual filter. The mobile brand and navigation improve the customer experience, but the authoritative boundary is the backend request context plus controller/query validation.
|
Security objective |
Enforcement described in the supplied implementation |
|
Only company properties visible |
Middleware resolves the company, then controller query applies landlord/company filter. |
|
Rent paid only to company landlord |
Wallet/rent flow validates lease or landlord against resolved company. |
|
Lease Angel stays in company |
Tenant/lease/property ownership validated before gifting/payment. |
|
Notifications isolated |
sender_id match plus sender_slug JSON match; operations use same filter. |
|
Inquiries stay in company |
Participant landlord validation; outside respondent receives HTTP 403. |
|
Documents stay in company |
Landlord-aware shared document query used across list/show/download paths. |
|
Missing relationship fails closed |
Unresolved required IDs produce empty query predicate rather than widening results. |
19.1 Recommended Security Test Cases
· Call each public feed with Client A slug and confirm no Client B IDs appear.
· Repeat authenticated calls with a Client A user against known Client B object IDs; expect empty/404/403 according to endpoint semantics.
· Attempt wallet/service payment using a landlord ID outside the resolved company; expect rejection.
· Attempt pay-rent using a lease owned by another company; expect rejection.
· Attempt Lease Angel discovery/payment against another company tenant; expect no discovery or rejection.
· Attempt startInquiry() with an outside landlord respondent; expect HTTP 403.
· Verify notification unread count, mark-read and delete cannot affect unrelated sender_slug records.
· Disable a white_label_clients row and confirm the deployment no longer receives active WL context as designed.
20. Build, Release & Lifecycle Management
The build system separates brand configuration from the shared application codebase. A company-specific release is created by injecting compile-time identity and theme variables, while the backend remains centrally maintained.
1. Configure the white-label client record and approved brand assets.
2. Confirm the company-to-corporate-landlord-to-user identity chain.
3. Confirm the company inventory and enabled modules.
4. Trigger the configured Codemagic workflow.
5. Run QA on the generated Android/iOS artifact.
6. Complete app-store metadata, privacy disclosures, signing and account requirements.
7. Release through the approved store or controlled distribution channel.
8. Monitor build status and retain release notes / rollback artifact.
9. When branding or app configuration changes, trigger a new build and repeat release QA.
20.1 What Requires a New App Build?
|
Change |
Likely action |
|
Compile-time app name / slug / primary colour |
New mobile build. |
|
App icon / native store assets |
New build and/or store metadata update. |
|
Backend data, properties, leases, documents |
No app build; data changes appear through APIs. |
|
Backend scoping bug fix |
Backend deployment plus regression test; app build only if client code also changes. |
|
Email brand record |
Usually backend/config update; validate cache invalidation and sender domain. |
|
New mobile feature / UI |
New mobile build; may also require backend deployment. |
21. Benefits for Real Estate Companies
|
Benefit |
Practical value |
|
Avoid building from scratch |
Use an existing real-estate operating platform instead of funding a separate mobile/backend stack. |
|
Brand independence |
Customer-facing app, communications and portfolio experience can use the real estate company identity. |
|
Enterprise feature base |
White-label deployments can reuse Leaseora property, lease, payment, document, maintenance, mortgage, land, development, CRM and analytics capabilities as enabled. |
|
Faster implementation |
Configuration and build automation shorten the path from onboarding to a branded pilot compared with a ground-up app build. |
|
Operational automation |
Connected workflows reduce manual handoffs between sales, finance, support, leasing and maintenance. |
|
Scalability |
The shared platform can support portfolio growth without creating a separate codebase for each client. |
|
Management visibility |
Leaseora dashboards provide operational data and analytics for company teams. |
|
Continuous platform evolution |
Shared-code improvements can be made centrally, subject to testing and release management for each white-label deployment. |
22. Quick Start for a New Real Estate Company
|
Step |
Company / Leaseora action |
Acceptance criterion |
|
1 |
Register / verify the real estate company in Leaseora. |
Company account and authorized administrators exist. |
|
2 |
Provide approved app name, logo, colours, support contacts, website and store assets. |
Brand pack approved. |
|
3 |
Create white_label_clients record with unique slug and build identifiers. |
Active record resolves correctly. |
|
4 |
Validate company -> corporate landlord -> landlord user mapping. |
Expected landlord user ID resolved. |
|
5 |
Load / validate properties and enabled products under the correct landlord. |
Inventory queries return expected company records. |
|
6 |
Trigger first Codemagic build. |
Artifact builds successfully. |
|
7 |
Run scope, KYC, payments, email, notification and document QA. |
No cross-company leakage; flows behave as configured. |
|
8 |
Publish / distribute under the agreed developer-account model. |
Approved store listing or distribution channel live. |
|
9 |
Onboard customers and staff; monitor pilot metrics. |
Usage, support and operational metrics reviewed. |
|
10 |
Move from pilot to production operating cadence. |
Support ownership, release process and commercial scope confirmed. |
23. Operations, Monitoring & Troubleshooting
23.1 Symptoms and First Checks
|
Symptom |
First checks |
|
App shows no company listings |
Check slug, is_active, agency_id, corporate_landlord_id, corporate landlord user_id and record landlord_id. |
|
App shows wrong brand |
Check compile-time slug/app name, WhiteLabelClient branding fields, cache and registered_via. |
|
Notifications missing |
Check sender_id / data.sender_slug and NotificationController filter. |
|
Email falls back to Leaseora |
Check active WL client lookup, registered_via, explicit wlCompanyId on queued jobs and cache. |
|
Payment rejected |
Check requested landlord/lease ownership relative to resolved WL landlord IDs. |
|
Build failed |
Check Codemagic app/workflow IDs, build variables, signing credentials, Flutter build logs and environment setup. |
|
Nigerian user sent to wrong KYC |
Check country value, isWhiteLabel state, profileComplete/kycVerified state and router guard conditions. |
23.2 Logging Recommendations
· Log request correlation ID, resolved WL slug and company ID for white-label API requests.
· Log the resolved landlord user ID when applying feature scopes in debug/non-sensitive environments.
· Never log BVN, full identity document content, tokens, passwords or payment secrets.
· Capture build trigger ID, client slug, workflow ID, build status and completion timestamp.
· Maintain audit logs for administrative activation/suspension and branding changes.
24. File Inventory
24.1 Backend PHP
|
Category |
Files / locations |
|
Middleware |
app/Http/Middleware/WhiteLabelScopeMiddleware.php |
|
Traits / concerns |
app/Http/Controllers/Concerns/HasWhiteLabelScope.php; app/Http/Concerns/WhiteLabelBrandingHelper.php |
|
Models |
app/Models/WhiteLabelClient.php; app/Models/Company.php whiteLabelClients() relationship |
|
Controllers |
PropertyController, MortgageMobileController, WeBuildMobileController, LandController, LeaseController, RentPaymentController, WalletController, MaintenanceController, LeaseAngelController, PropertyInquiryController, DocumentController, NotificationController, ReelController, BvnVerificationController, PaymentController, PropertySaleController |
|
Mail |
app/Mail/Lease/, app/Mail/Mofi/, app/Mail/WeBuild/ plus root mail classes described in this guide |
|
Notifications |
app/Notifications/ - supplied specification states 44 classes |
|
Views |
resources/views/emails/layouts/branded.blade.php and associated email templates |
|
Routes |
routes/api.php - WhiteLabelScopeMiddleware applied to the relevant white-label route groups |
24.2 Flutter
|
Category |
File |
|
Config |
mobile/lib/core/constants/white_label_config.dart |
|
Services |
mobile/lib/core/services/app_config_service.dart |
|
Network |
mobile/lib/core/network/api_client.dart |
|
Theme |
mobile/lib/core/theme/wl_colors.dart |
|
KYC |
mobile/lib/features/tenant/presentation/kyc/bvn_verification_page.dart |
|
Notifications |
mobile/lib/features/tenant/presentation/notifications/notifications_hub_page.dart |
|
Reels |
mobile/lib/features/tenant/presentation/reels/reels_feed_screen.dart |
|
Navigation |
mobile/lib/features/tenant/shell/tenant_main_shell.dart |
|
Router |
mobile/lib/main.dart |
|
Profile |
mobile/lib/features/auth/presentation/pages/profile_setup_page.dart |
24.3 CI/CD
|
File |
Purpose |
|
mobile/codemagic.yaml |
Codemagic workflow configuration and build variables. |
|
app/Http/Controllers/WhiteLabelController.php |
Laravel-side build trigger and client build management. |
25. Glossary
|
Term |
Meaning in this documentation |
|
White-label client |
The registry/configuration record that represents a branded deployment. |
|
Company slug |
Unique, URL-safe deployment identifier transmitted in X-Company-Slug. |
|
agency_id |
white_label_clients foreign key to companies.id. |
|
Corporate landlord |
Company-linked landlord entity that maps to the actual landlord user account. |
|
landlord_id |
In many feature tables, the users.id of the owning landlord. |
|
registered_via |
User field preserving the white-label slug used at registration. |
|
WL scope |
Server-side request context and query restrictions tied to the resolved company. |
|
Fail closed |
Returning no data / rejecting the operation when identity cannot be safely resolved. |
|
Codemagic |
CI/CD service used by the supplied design to compile company-specific Flutter artifacts. |
|
Dart define |
Compile-time key/value passed to Flutter to select deployment identity and theme. |
26. Knowledge Center Publishing Notes
· Keep code snippets synchronized with the production branch when implementation changes.
· Replace example company names/slugs with neutral examples where the article is public-facing.
· Do not publish live secrets, private app IDs, signing credentials, API tokens or customer PII.
· Mark country-specific KYC and payment guidance with the relevant availability/compliance caveat.
· When a module is optional, state that availability depends on enabled subscription/enterprise scope and deployment configuration.
· For major white-label releases, update this document version and maintain a short change log.
26.1 Suggested Change Log
|
Version |
Date |
Change |
Owner |
|
1.0 |
9 Oct 2026 |
Initial consolidated white-label technical, integration and automation documentation. |
Leaseora Platform / Knowledge Center |
27. Contact & Support
For white-label onboarding, implementation, build support, custom integration requests or production incident coordination, use the Leaseora Landlord/Super Admin support workflow or contact the Leaseora platform team through the official channels below.
|
LEASEORA |
Your app. Your brand. Your customers. Powered by Leaseora.
Was this article helpful?
Your feedback helps us improve our documentation.