A multi-tenant SaaS platform for managing rental properties, tenants, leases, payments and operational communication across Kenya and East Africa — built by Webloom Tech Kenya and shipped at alphaone.africa.
Industry
PropTech / Real Estate
Project Type
Multi-tenant SaaS
Deployment
Live — alphaone.africa
Stack
FastAPI · React · PostgreSQL
The Challenge
Rent arrives by M-Pesa, tenants report maintenance over WhatsApp, lease documents live in email threads, and financial records are scattered across spreadsheets and SMS histories. For landlords and property managers this means there is no single source of truth for what is actually owed at any moment.
Payments, leases and tenant records live in different places, making it impossible to know what is owed at any given moment.
M-Pesa confirmations arrive as free-form text messages, not structured records that can feed a ledger.
A single provider must serve many landlords and property managers without their data colliding, while still scoping access per property and role.
The Approach
AlphaOne centralizes the full property-management lifecycle — organizations, properties and units; tenant records and lease agreements; rent and deposit charges; payment ingestion from multiple channels; and the reconciliation queue that turns messy, external payment evidence into clean, auditable ledger entries.
The system is built around the principle that money is never recorded directly from an external source. Every payment must first pass through a review queue, where it is matched to a tenant and a lease, then explicitly applied. This keeps the financial model honest whether a payment originates from a bank CSV upload or a forwarded WhatsApp message.
Key Capabilities
Nine focused modules cover the day-to-day operations of running a rental portfolio across multiple buildings, owners and roles.
Multi-property portfolios, unit tracking, vacancy management and occupancy reporting — all scoped per organization.
Tenant records, document storage, lease agreements, phone/OTP verification and occupancy history.
Lease creation, recurring rent charges, one-time deposit charges, and oldest-first settlement that never lets rent payments absorb deposits.
M-Pesa statement CSV ingestion with per-row tenant and lease matching, deposit-aware splitting, and duplicate detection.
A pending → applied/review flow that unifies CSV and WhatsApp evidence sources before any money hits the ledger.
Inbound webhooks become tickets; forwarded M-Pesa confirmations become structured payment evidence.
Full ticket lifecycle (open → assigned → in_progress → resolved → closed) with categories, priorities, attachments and conversation history.
Tailored dashboards for landlords, property managers, finance teams and tenants, each scoped to the data they are allowed to see.
Expense tracking with vendor and category management, plus rent-roll, collection and profit reports.
Design & Product Experience
The interface is role-aware — landlords see portfolio-wide metrics, finance teams see the reconciliation queue, tenants see their own records through a dedicated mobile portal.
Occupancy, collected vs. outstanding rent and open maintenance tickets on a single screen — with monthly collection trend at a glance.
Every payment — whether typed from a bank statement, forwarded as an M-Pesa SMS over WhatsApp, or recorded manually — becomes a candidate review item that is matched, reviewed and applied as a single, auditable transaction.
Tenants pay via M-Pesa, forward the confirmation to the AlphaOne WhatsApp number and receive an automatic receipt — without ever logging in to a portal.
For tenants who do log in, a mobile portal surfaces the next due date, payment history and ticket status with the same brand experience.
Payment Engineering
The design enforces a hard rule: a WhatsApp message never becomes a Payment
row directly. It can only become a PaymentReviewItem, which must then be
reviewed and applied. This removes an entire class of financial-integrity bugs.
Tenant → WhatsApp message → Meta webhook (inbound) → Message persistence (idempotent) → Ticket auto-created → Payment evidence parser → PaymentReviewItem (source = "whatsapp", status = pending_review) → Reconciliation queue → Apply → Payment → lease settlement recomputation → WhatsApp receipt
A conservative parser recognises several message formats — the structured
MPESA TO ACC ... TIMESTAMP ... statement rows, the forwarded customer
confirmation SMS (UDTQS2OHFR Confirmed. Ksh26,000.00 sent to ...),
PESA long-hex references and cash-deposit slips. Each match is tagged with a
confidence level (high / medium / low / none) so reviewers can triage the
uncertain ones, and amounts are extracted strictly to avoid fabricating figures
from phone numbers, timestamps or account tokens.
Because the WhatsApp evidence and the bank CSV arrive through different channels, the reconciliation service can match them against each other. A CSV row carrying the same M-Pesa reference, tenant and amount (within a small date tolerance) is surfaced to the reviewer with a confidence tag, so a forwarded SMS can reconcile a bank statement line and vice-versa.
Property teams onboard hundreds of units at once and reconcile weeks of payments in a single statement. The bulk-upload subsystem handles both.
Spreadsheet-based import of properties, units and tenants (CSV and Excel), with a read-only tenant preview, row-level validation and per-row skip handling so one bad row never rejects an entire import.
M-Pesa statement CSV ingestion that builds a preview — matching each row to a tenant via the WhatsApp payment-evidence record, or as a fallback via the payer phone — before any money is recorded.
The preview is read-only: it flags rows as matched, unmatched, multiple leases, insufficient first payment, duplicate or parse error, and only the rows the reviewer confirms are committed. At commit time the first-payment-must-cover-deposit rule is enforced: a row that cannot cover the remaining deposit balance in full is rejected, while qualifying rows are split into a deposit payment and a rent payment that share the same reference — so the deposit charge is never silently left unpaid and rent-collection figures never include deposit money.
Results & Impact
AlphaOne is not a demo. It is a multi-tenant SaaS with real rent moving through reconciliation, real tenant communication arriving over WhatsApp, and real financial controls that prevent a misrouted or malformed payment from corrupting a ledger.
The project is notable because it does not pretend the world is tidy. Payments arrive as text messages. People share phone numbers. Tenants have multiple leases. Banks export CSVs and tenants forward screenshots. The engineering value is in accepting that messiness and channeling it through one consistent, auditable flow: evidence → review → apply → settle.
Technology & Implementation
The platform is a modular monolith — deliberately kept cohesive enough to reason about end-to-end while separating concerns cleanly across domain APIs and service layers.
React 19 + Vite (feature-based) → HTTP / JWT → FastAPI → SQLAlchemy ORM → PostgreSQL (transactions, charges, payments, tenants, audit) ↑ ↓ Redis (refresh tokens, background tasks, rate-limit state) ↓ Caddy (HTTPS) → Nginx (frontend) | FastAPI (backend) → Postgres + Redis
Every query is scoped to an organization_id, so one landlord's properties, tenants, leases and payments are never visible to another. Access within an organization is governed by five roles — LANDLORD, PROPERTY MANAGER, FINANCE, TENANT and SYSTEM — resolved authoritatively from the membership table rather than a single user flag.
A property-manager or finance user is further scoped to the specific properties they are assigned to, so a finance team member only ever reconciles the statements for their own buildings. Tenants see only their own records through the tenant portal.
Sensitive personal data — tenant phone numbers, emails, ID numbers and emergency contacts — is stored encrypted (Fernet), never in plaintext. Lookups that need to match a phone back to a tenant use a precomputed blind index, so the system can resolve a WhatsApp sender to a tenant without ever comparing plaintext phone numbers in a query.
Short-lived JWT access tokens (15 min) with long-lived refresh tokens persisted in the database and revoked on password change or reset, so a stolen refresh token cannot survive a credential rotation.
Account lockout after repeated failed logins, a password policy that rejects dictionary and common passwords, password history, mandatory OTP phone verification for new landlords, and refresh-token invalidation on every password reset.
FastAPI with Pydantic schemas, role-based dependencies, async-capable background tasks (receipt sends, notifications) and automatic OpenAPI / Swagger documentation.
PostgreSQL 15 with SQLAlchemy ORM and Alembic migrations. Charge and payment tables carry a charge_type / payment_type discriminator so rent and deposit money never mix in aggregation queries.
React 19 + Vite with a feature-based layout, Context-API session handling (including silent JWT refresh), role-aware route guards, a shared Pagination hook and reusable Modal / Pagination / MobileCardList components.
Redis 7 powers refresh-token storage, slow-auth rate-limit state and the task queue backing outbound message confirmation.
Docker Compose with a Caddy HTTPS reverse proxy in front of an Nginx-served frontend and the FastAPI backend; automated daily Postgres dumps with 7-day retention and health-checked containers.
An audit-log table records who did what to which entity (with before / after new-values) for payments, review items, login events and message traffic.
Organization scoping is enforced at the query layer, while PII stays encrypted at rest using blind-index hashes for lookups — so tenant resolution works without exposing plaintext phone numbers.
M-Pesa confirmations arrive as free text. A conservative parser extracts reference, amount and confidence, then routes the candidate through the same review queue used by bank-CSV imports so the two sources reconcile against each other.
The billing engine settles rent and deposit charges from independent payment pools (oldest-first), and the batch importer splits a single M-Pesa line into deposit + rent payments — preventing deposits from inflating rent-collection metrics.
Meta retries webhooks frequently, so every stage — message persistence, ticket creation and review-item creation — is guarded on provider_message_id / source_message_id and deduplicates safely.
Account lockout after repeated failures, a password policy that rejects dictionary and common passwords, password history, mandatory OTP phone verification for new landlords, and refresh-token invalidation on every password reset.
HTTPS via Caddy with HSTS, security headers, request-size limits, file-upload validation (size, type, magic bytes), pgAdmin IP-restricted behind a firewall, and container health checks.
The interface evolved alongside the backend. Dashboard work delivered role-specific summaries, a finance dashboard with a rent / deposit split view and a tenant portal. Usability refinements included server-side pagination across lists, global search, an Excel / XLSX path for spreadsheet imports, and a responsive layout with a mobile bottom navigation so property managers can act from a phone on-site.
The reconciliation queue itself is a usability decision: by forcing a review step before money is recorded, ambiguous payments are surfaced to a human instead of being silently misallocated.
The system is deployed as a Docker Compose stack behind a Caddy HTTPS reverse proxy. The public application lives at alphaone.africa with the API served at api.alphaone.africa. Infrastructure concerns are handled for production: automated PostgreSQL backups with retention, a firewall allow-list that restricts pgAdmin (port 5050) to known IPs, secrets centralised into environment configuration and validated at startup, and container health checks that gate dependent services.
A public marketing layer (home, features, about and contact pages) makes the product discoverable. Structured data (Organization, WebSite, WebPage and BreadcrumbList JSON-LD), canonical URLs, Open Graph and Twitter metadata, a sitemap and robots directives are all wired in so the platform is represented correctly in search and social previews.
Core SaaS foundation (auth, JWT, roles, Docker) → Organization & property management → Units, tenants & leases → Billing, charges & payments → Role-based dashboards → Expense management → Tickets & inspections → Deposit & payment type modelling → Payment reconciliation queue → WhatsApp messaging & inbound ticketing → WhatsApp payment-evidence parsing & matching → Bulk financial operations & deposit-aware splits → Deployment & production hardening → Public presence & SEO → UX & UI refinement
Final Outcome
AlphaOne demonstrates the ability to take a genuine, operational business problem — running rental portfolios in an environment that lives on phone calls and M-Pesa — and design, build and ship a system that handles it. It bridges informal, tenant-channelled payment evidence with structured financial records, while keeping strict organization and role boundaries between landlords, property managers, finance teams and tenants.
See the live platform and review the implementation behind it.