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.

L
Leaseora
Oct 09, 2026 40 min read 63 views

LEASEORA

KNOWLEDGE CENTER

WHITE-LABEL APP
Complete Technical, Integration, Security & Automation Documentation

 

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
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.

 

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
The source implementation uses terms such as tenant, landlord, company, corporate landlord and white-label client in model names, route names and code. This documentation preserves those technical terms because changing them would make the guide harder to map to the codebase.

 

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
One platform, many brands: the same maintainable backend and mobile codebase can serve multiple company-branded applications while the server enforces tenant/company isolation.

 

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
The source design treats this resolution chain as the most important white-label identity concept. Filtering against the wrong identifier can return no data or, more seriously, weaken isolation.

 

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
Where the required landlord relationship cannot be resolved, the source implementation applies a false predicate (1 = 0). That is a defensive design: misconfiguration should return an empty result set rather than unrelated company data.

 

Critical design decision
The supplied technical specification prefers landlord_id where possible because corporate_landlord_id was introduced later and may be NULL on historical records. A nullable relationship must never be treated as a permissive bypass.

 

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
Queued verification and password-reset emails do not have the original HTTP request container. Persisting the originating slug on the user gives the branding layer a durable identity source.

 

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
Build-time variables identify and theme the app, while backend request scoping remains the authoritative security boundary. A custom colour or app name is not a data-isolation mechanism.

 

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
Authenticated mobile routes use Laravel Sanctum bearer tokens. The Flutter Dio interceptor adds X-Company-Slug to white-label requests so authentication and company context travel together.

 

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
A white-label request must never widen a query because the company relationship is missing. The expected defensive outcome is an empty result or 403 guard, depending on the operation.

 

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
Never publish real API secrets, signing keys, app-store credentials or Codemagic tokens in the Knowledge Center. Use secret managers and deployment environment variables.

 

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
KYC provider availability, permitted BVN use, data-retention rules, consent wording, encryption, document handling and regulatory obligations must be validated for the production country and current provider agreement. This guide documents the supplied technical flow; it is not legal or regulatory advice.

 

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
Using a company address in the application does not by itself authorize email delivery. Production domains must be configured with the required mail-provider verification and DNS authentication (for example SPF/DKIM/DMARC as applicable) before a sender is represented as production-ready.

 

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
AI-Powered PropTech + FinTech Real Estate Operating System
www.leaseora.com  |  support@leaseora.com

Your app. Your brand. Your customers. Powered by Leaseora.

 

Was this article helpful?

Your feedback helps us improve our documentation.

Article Info

Category WHITE-LABEL APP
Reading Time 40 min
Views 63
Published Oct 09, 2026

Share

🤝

Need more help?

Our support team is available to assist you.

Contact Support