Apartment Building Management Software

The complete user & admin guide. Everything the software does, explained in plain language.

What it does

This is a self-hosted property-management system for apartment buildings. One install runs your whole rental operation: properties and units, tenants and leases, rent collection, maintenance, finances, and day-to-day office tasks. There are no subscription fees and no external services required — you host it and you own the data.

There are three kinds of login: Admin (full control), Manager (runs the building day-to-day, with optional per-area access limits set by an admin), and Tenant (a simple resident portal to pay rent and file requests). Vendors/contractors are kept as a directory you manage — they do not log in.

🏢 Properties & Units

Unlimited buildings and units, occupancy and vacancy tracking

📄 Leases & Renewals

Full lease lifecycle, one-click renewal with rent change

💳 Rent & Payments

Stripe card payments or manual entry, auto late fees, receipts

🔧 Maintenance

Work orders with photos, vendor directory, SLA alerts, analytics

📊 Finance & Reports

Budgets, petty cash, disbursements, P&L, vacancy, year-end

🛎️ Office tools

Packages, parking, keys, utilities, compliance, announcements

✉️ Automated reminders

Late-rent reminders, renewal alerts, monthly statements

🔗 API & Webhooks

Zapier/Make ready, REST API, real-time event webhooks

Requirements

ComponentMinimumRecommended
PHP8.08.2+
MySQL / MariaDB5.7 / 10.38.0+ / 10.6+
Web serverApache or NginxApache with mod_rewrite
PHP extensionsPDO, PDO_MySQL, mbstring, curl, openssl, fileinfo, json, session
SSL certificateRequired for Stripe card payments. Free from Let's Encrypt.
Disk space100 MB5 GB+ (for uploaded files)

Installation

Option A — Web installer (recommended)

1

Upload all files to your server. The project root folder is the web document root — point your domain at it.

2

Create an empty MySQL database (e.g. apartment_db) in cPanel → MySQL Databases.

3

Open https://yourdomain.com/install/ in a browser.

4

Follow the wizard: Requirements check → Database → Site settings → Admin account.

5

The installer loads the schema, creates your admin account, writes _app/config/config.php, and removes itself.

Option B — Manual install

1

Upload files and point your domain at the project root folder.

2

Create a MySQL database and import install_complete.sql (phpMyAdmin → Import). This single file builds the entire up-to-date schema — you do not need to run any install_patch_* files on a fresh database.

3

Copy _app/config/config.sample.php to _app/config/config.php and fill in your values.

4

Visit /register.php and create your account. The first account ever registered automatically becomes the Admin.

5

After the admin exists, public registration closes automatically (unless you re-enable it in settings). You can also remove register.php for extra safety.

🔐 The sign-in screen. The login page does not show a "Create an account" link — accounts are created by an admin (Settings → Users & Roles) or via an emailed invite, and the very first admin via register.php as above. The login form includes a "Remember me" checkbox that keeps that browser signed in for 21 days; left unticked, the session ends when the browser is closed.
💡 Document root matters. Point the domain at the project root. The _app/ folder (config, includes, cron) is blocked from the browser by the included .htaccess so secrets stay private.

Roles & who sees what

The whole system runs on three roles. Pick the right one when you add a user.

RoleCan do
AdminEverything, always. Admins are never page-restricted. Only an admin can change roles, restrict managers, delete users, and edit other admins.
ManagerRuns the building: properties, tenants, leases, payments, maintenance, office tools, reports. An admin can limit an individual manager to only the areas they need — it's an allow-list (see Manager access control).
TenantTheir own resident portal only — pay rent, file maintenance, request renewal/move-out, see documents and announcements.

Vendors/contractors are not a login role. They live in the Vendors directory so you can assign them to work orders and keep their rates and contact details — but they never sign in.

Configuration file

Settings live in _app/config/config.php. The installer writes this for you. For a manual setup, copy config.sample.php to config.php and fill in:

KeyExampleRequired?
DB_HOSTlocalhostRequired
DB_NAMEapartment_dbRequired
DB_USER / DB_PASSyour DB user & passwordRequired
APP_URLhttps://yourdomain.comRequired
APP_KEYlong random stringRequired
UPLOAD_DIR/home/yoursite/uploadsRequired
MAIL_FROM / MAIL_FROM_NAMEnoreply@yourdomain.comOptional
STRIPE_SECRET_KEYsk_live_…Optional
STRIPE_PUBLIC_KEYpk_live_…Optional
STRIPE_WEBHOOK_SECRETwhsec_…Optional
APP_ENVproductionOptional

Email (SMTP) and SMS (Twilio) are not set here — they're entered in the app under Settings → General so you can change them without touching files.

Email setup (SMTP)

Go to Settings → General → Email (SMTP). Every email the system sends (tenant invites, receipts, reminders, alerts) uses this one configuration. If you leave SMTP blank it falls back to the server's basic mail, which often lands in spam — configuring SMTP is strongly recommended.

Gmail

  1. Turn on 2-Step Verification on the Google account.
  2. Create an App Password at myaccount.google.com/apppasswords.
  3. Host smtp.gmail.com, port 587, TLS, your Gmail address, and the 16-character App Password (not your normal password).

Outlook / Microsoft 365

Host smtp.office365.com · port 587 · TLS · your normal email and password.

Brevo / Postmark / others

Use the host, port and SMTP key from your provider. The Email tab has a built-in quick-reference card for the popular ones.

SMS setup (Twilio)

Go to Settings → General → SMS. SMS is fully optional — every SMS feature silently falls back to email if it isn't configured.

  1. Sign up at twilio.com and get a phone number.
  2. Copy your Account SID and Auth Token from the Twilio console.
  3. Enter them plus your Twilio From number (in international format, e.g. +15551234567).
📱 Phone numbers used for SMS must include the country code with a leading +. Every phone field in the app shows this hint, because a number saved as a plain local number can't receive texts.

Stripe online payments

Stripe lets tenants pay rent by card from their portal. It's optional — you can also just record manual payments.

  1. Sign up at stripe.com.
  2. Copy your API keys from Developers → API keys into _app/config/config.php (STRIPE_SECRET_KEY, STRIPE_PUBLIC_KEY).
  3. Add a Stripe webhook pointing to https://yourdomain.com/webhooks/stripe.php and copy its signing secret into STRIPE_WEBHOOK_SECRET.
  4. Tune behaviour in Settings → Payment Settings.
⚠️ Use test keys (sk_test_…) until you're ready to take real money.

Testing connections Built in

You don't have to send a real invoice to find out if email or SMS works. Both the Email and SMS tabs in Settings → General have a Test connection button.

  • Email: it actually connects to your SMTP server, logs in, and (if you enter a recipient) sends a short test message. If something is wrong it tells you exactly where — wrong port, bad password, TLS failure, etc.
  • SMS: Test connection checks your Twilio credentials with no message sent and nothing charged. A separate Send test SMS button sends a real message to a number you type in.

Tests use whatever is currently typed in the form, so you can verify settings before saving. Secret fields can be left blank to reuse the saved value.

Cron jobs

Scheduled features (late-payment reminders, late fees, renewal & SLA alerts, recurring tasks, monthly statements, webhook retries) are driven by a single dispatcher. You no longer add a dozen cron lines — just one. The dispatcher decides which jobs are actually due each time it runs, based on each job's own schedule.

The installer offers a "Try to install it automatically" button on its final screen. On most VPS/dedicated servers that's all you need. On shared hosting that's often blocked, so add this one line via your control panel's Cron Jobs tool (set "Once per 5 minutes") — adjust the path to your install:

*/5 * * * * php /path/to/app/_app/cron/run_all.php >/dev/null 2>&1

Running it every 5 minutes is recommended (and safe even every minute) — the dispatcher itself enforces each job's real cadence: webhook retries every ~5 min, SLA alerts hourly, reminders/fees/renewals once a day, balance summaries once a month. Skipping the cron line entirely just means those automated emails won't fire; everything else still works manually.

💡 To run everything once on demand (e.g. to test): php /path/to/app/_app/cron/run_all.php --force

Features — operations

These are the core pages an admin or manager uses to run the building. Each section below explains, in plain terms, what the page is for and how to use it.

Dashboard

Sidebar → Dashboard

Your morning overview. It shows the building's pulse at a glance: rent collected vs outstanding, open work orders, upcoming lease endings, and pending tenant requests. Red badges in the sidebar tell you when something needs attention (new move-out request, new maintenance request, etc.) so nothing slips through.

Properties & Units

Sidebar → Properties / Units

Properties are your buildings. Add one with its name and address; you can also nominate an admin as the property's "primary contact" (used for the monthly statement email and the by-contact financial report).

Units are the rentable apartments inside a property — number, bedrooms, and rent. The Units list shows occupancy at a glance so you can see what's vacant. A unit moves through the lease lifecycle automatically as you sign and end leases on it.

Tenants

Sidebar → Tenants

Your residents. Add a tenant two ways: invite by email (they get a link to set their own password) or create manually (you set the password, useful for residents who can't easily check email).

Each tenant has a profile you can edit any time — name, email, phone, status. From the tenant's Edit page you can also change their password directly (handy when a resident is locked out and can't reach email) and upload files for that tenant (ID copy, signed forms, pet agreement). The tenant view shows their balance owed, open charges, and full lease history.

The phone field expects international format with a country code (e.g. +15551234567) — the same number is used to text the tenant, so the form reminds you.

Leases

Sidebar → Leases

The full lease lifecycle. Create a lease by linking a tenant to a unit with a start/end date and monthly rent. Leases move through clear states (draft → active → ending soon → expired/terminated). You can edit a lease, generate a lease document, capture a signature, and renew with one click — the renewal flow lets you adjust the rent and rolls the dates forward without re-keying everything.

Move-out & Renewal requests

Sidebar → Move-out requests / Renewal requests

When a tenant submits a renewal or move-out notice from their portal, it lands here and a red badge appears in the sidebar. For a move-out you get a checklist workflow — forwarding address, deposit math, and lease termination handled in one place. For a renewal you can approve and feed it straight into a new lease term.

Unit turns

Sidebar → Unit turns

The "between tenants" tracker. When one tenant moves out and before the next moves in, a unit usually needs cleaning, painting and small repairs. A unit turn tracks that checklist and its costs so you know how long and how much each turnover takes, and so a unit isn't accidentally re-let before it's ready.

Features — money

Payments

Sidebar → Payments

Every rent and fee payment, in one ledger. Tenants can pay by card (if Stripe is on) and it records automatically; otherwise you record a manual payment (cash, cheque, bank transfer) using a guided Property → Unit → Tenant picker so you can't attach money to the wrong account. Payments apply to the oldest open charge first, or to a specific charge you choose.

Finance

Sidebar → Finance

Everything that isn't rent income, in one place: budgets per category, petty cash in/out with receipts, owner disbursements (money paid out of the operating account to the building's owner/LLC), capital expenditure (big improvements tracked year over year), and expense approvals. This is where the building's outgoings are recorded and controlled.

Reports

Sidebar → Reports

Read-only financial views you can produce and share with whoever owns the building:

  • Income statement (P&L) — income vs expenses per property for any date range.
  • Statement by primary contact — combined P&L of every property a chosen admin is the contact for.
  • Vacancy — which units are empty and for how long.
  • Tenant statements — a clean account statement per tenant.
  • Year-end & CapEx — annual summary, yield calculator, capital-project history.

There's no separate "owner" login — buildings are usually owned by an LLC, so the owner's numbers live here for admins to export.

Late-payment reminders

Sidebar → Settings → Late-payment reminders

Automatic, escalating reminders for overdue rent (e.g. a friendly nudge on day 1, a firmer notice on day 5, a final notice on day 10). You fully control the wording with editable email and SMS templates, using placeholders like the tenant's name, amount and due date. Fired by the late-payment cron job.

Features — maintenance

Work orders

Sidebar → Work Orders

The maintenance backbone. A work order can come from a tenant (with up to several photos) or be created by staff. You set priority and category, assign a vendor from your directory, track it through clear statuses (open → assigned → in progress → completed), and add internal notes. New requests raise a sidebar badge, and the SLA cron flags anything sitting open too long.

Vendors (directory)

Sidebar → Vendors

Your contractor address book — plumbers, electricians, cleaners, etc. Store contact details, trade, pricing model (hourly/fixed/quote), rate, and notes, and mark your preferred vendors. Assign them to work orders from here. Vendors do not log in — this is purely a directory you control. (A dedicated vendor portal existed in older versions and has been removed; the directory replaces it.)

Inspections

Sidebar → Inspections

Schedule and record move-in, move-out and routine walk-through inspections. Mark them complete after you've done them, keeping a dated history of unit condition that's invaluable at deposit time.

Recurring tasks

Sidebar → Recurring Tasks

Set-and-forget routine jobs — gutter cleaning every spring, fire-alarm test monthly, boiler service annually. Define the task and its schedule once and the recurring-tasks cron creates a fresh to-do each time it's due, so seasonal work never gets forgotten.

Inventory

Sidebar → Inventory

Track property stock — filters, light bulbs, paint, spare parts, appliances. Adjust quantities as you use or restock them and see low-stock warnings so you're not caught short mid-repair.

Maintenance analytics

Sidebar → Analytics

The numbers behind your maintenance: volume of work orders over time, average time to close, breakdown by category and by property. Use it to spot a building that's costing too much in repairs or a vendor who's consistently slow.

Features — office

Documents

Sidebar → Documents

A central file store for the building — policies, templates, signed agreements, certificates. Files can be general or attached to a specific tenant. Tenant-scoped files are visible to that tenant in their portal; internal files stay staff-only.

Messages

Sidebar → Messages

A simple two-way inbox between staff and tenants — questions, follow-ups, a record of what was said. Staff can also send a broadcast to many tenants at once by email and/or SMS.

Announcements

Sidebar → Announcements

A building notice board — water shut-offs, policy changes, holiday reminders. Tenants see these in their portal, and urgent notices can be pinned to the top.

Emergency contacts

Sidebar → Emergency contacts

A directory of who to call after hours — plumber, electrician, gas, security. Tenants see big, tappable phone numbers on mobile so the right person is reached fast in a real emergency. Phone numbers use international format so they dial correctly anywhere.

Keys

Sidebar → Keys

A key register — which physical keys and fobs exist, which unit they open, and who currently holds each one. Stops the "who has the spare to 4B?" problem.

Parking

Sidebar → Parking

Manage parking spots and who they're assigned to. Tenants can self-register their vehicle plates and request guest parking passes from their portal; staff approve and track them here.

Packages

Sidebar → Packages

Front-desk parcel log. When a delivery arrives, log it against the unit; the tenant is notified by email and/or SMS automatically and the package is marked collected when they pick it up — a clear chain of custody for deliveries.

Utilities

Sidebar → Utilities

Record meter readings and split shared utility bills across tenants fairly, so sub-metered or shared water/electric costs can be passed through accurately.

Compliance

Sidebar → Compliance

Track recurring legal and safety obligations — smoke-detector checks, fire permits, HVAC inspections, insurance renewals — each with a next-due date. The compliance cron flags anything overdue so a lapsed certificate never catches you out.

Tenant experience

When a tenant signs in they get a clean, mobile-friendly portal — none of the admin tools, just what concerns them:

  • Dashboard — balance, next due date, anything outstanding at a glance.
  • Pay rent — pay by card (if Stripe is on) or see what's owed; full payment history with receipts.
  • Maintenance — file a request with photos and track its status in plain English.
  • My lease — view lease details and documents.
  • Renew / move-out — submit a renewal or move-out notice with a forwarding address; it routes straight to staff.
  • Vehicles & guest parking — register plates and request visitor passes.
  • Packages — see parcels logged for them and when collected.
  • Documents, Messages, Announcements, Emergency contacts — everything shared with them, in one place.

Admin & settings

Users & roles

Sidebar → Settings → Users & Roles

Add people to the system as Admin, Manager or Tenant. Add them two ways: create manually (you set the password, they can sign in immediately) or invite by email (they get a one-time link to set their own password). The table lists every user with their role, status and last login, and quick actions to edit, deactivate, reactivate or delete.

Manager access control Key feature

When adding/inviting a Manager, or via Settings → Users & Roles → Edit

Admins always have full access and are never restricted. When you add or invite a Manager, a grid of checkboxes appears. It is an allow-list: a ticked box = an area the manager IS allowed to use. Unticking a box removes that page — its menu link disappears and the page itself refuses direct access (both viewing and saving).

The pages are organised into five groups so you can grant access in bulk:

  • Operations — Properties, Units, Tenants, Leases, Move-out & Renewal requests, Unit turns, Users & Roles
  • Money — Payments, Finance & Expenses, Reports & Export, Late-payment reminders, Payment Settings
  • Maintenance — Work Orders, Vendors, Inspections, Recurring Tasks, Inventory, Maintenance Analytics
  • Office — Documents, Messages, Announcements, Emergency contacts, Keys, Parking, Packages, Utilities, Compliance
  • Settings — General, API keys, Integrations, Import, and the other settings pages

Select all / Clear all buttons let you flip an entire grid quickly. New managers default to everything except Payment Settings, which you can then tailor.

Safety rule: a manager who has no access list saved at all is treated as full-access (so a half-finished setup never accidentally locks someone out). To actually limit a manager you must open their Edit page and Save with at least one box ticked.
⚠️ Upgrading from an older version? The model changed from "tick to hide" to this allow-list. Open Settings → Users & Roles → Edit for each existing manager once and re-save so their access reflects the new model.

Editing a user & changing passwords Improved

Settings → Users & Roles → Edit (any user)

Every user row has an Edit button. From the user editor an admin can change any user's profile — first/last name, email, phone, role and status — for tenants, managers and other admins alike. The same page has a Change password box so an admin can set a new password for anyone immediately (useful when someone is locked out and can't use email to reset it). For managers, the page also shows the restriction checkboxes. Tenants can additionally have their password changed from the Tenants → Edit page.

Deactivate vs delete a user Fixed

Settings → Users & Roles

Deactivate suspends an account — the person can no longer sign in, but their records stay intact. The button correctly flips to Reactivate afterwards so you can restore access later. (An earlier build had a bug where deactivate appeared not to "stick"; that's resolved.)

Delete permanently removes the user and, for a tenant, their related records (leases, charges, payments, requests). It asks for a strong confirmation first and cannot be undone. You can't deactivate or delete your own account.

Other settings

Sidebar → Settings
  • General — company name, currency, notification preferences, and the Email/SMS configuration with the built-in Test connection tools.
  • Payment Settings — Stripe behaviour, late-fee rules, grace periods.
  • Late-payment reminders — the escalating reminder schedule and editable templates.
  • API Keys — generate Bearer keys for the REST API (shown once — copy immediately).
  • Integrations / Webhooks — subscribe external URLs (Zapier/Make/n8n) to events.
  • Import / Export — bulk-load data in, or export it out (CSV).
  • Audit log — a dated record of significant actions for accountability.

File structure

your-app-root/            ← point your domain HERE (web root)
├── _app/                 ← NOT web-accessible (blocked by .htaccess)
│   ├── config/
│   │   ├── config.php        ← your settings (created by installer)
│   │   └── config.sample.php ← template
│   ├── cron/                 ← scheduled scripts
│   └── includes/             ← engine: auth, db, functions, layout
├── api/                  ← REST API endpoints (.php)
├── assets/               ← css / js
├── documentation/        ← this guide
├── install/              ← web installer (self-deletes after use)
├── tenant/               ← tenant portal pages
├── settings/             ← admin settings pages
├── (properties, units, tenants, leases, payments,
│    maintenance, vendors, reports, … one folder per feature)
├── uploads/              ← uploaded files (keep writable, private)
├── install_complete.sql  ← full single-file schema (fresh installs)
├── login.php  register.php  dashboard.php  index.php
└── .htaccess             ← security rules

Older versions used a public/ web root and an includes/ folder. The current layout is a flat root with a protected _app/ — point the domain at the root, not a sub-folder.

Database

58 tables. A single file, install_complete.sql, builds the entire current schema on a fresh database — including all features through the latest version. It uses CREATE TABLE IF NOT EXISTS, so it's safe, and you do not need to run the older install_patch_* files on a new install. (Patches are only for upgrading a database that already has live data.)

Key tables: users, properties, units, leases, charges, payments, work_orders, vendor_profiles, documents, notifications, manager_restrictions, settings.

API & webhooks

External systems can act on the data via a small REST API, and the app can push real-time events out to Zapier/Make/n8n via webhooks. Generate keys in Settings → API Keys and send them as a Bearer token:

Authorization: Bearer pm_your_api_key_here
⚠️ API endpoints are PHP files and must be called with the .php extension — e.g. /api/action_create_tenant.php. There is no extension-less routing; the short form returns 404.

Endpoints

EndpointMethodAction
/api/action_create_tenant.phpPOSTInvite a new tenant
/api/action_create_work_order.phpPOSTOpen a maintenance request
/api/action_record_payment.phpPOSTRecord a payment
/api/action_send_message.phpPOSTSend a broadcast
/api/action_create_charge.phpPOSTAdd a charge to a tenant
/api/trigger_poll.phpGETPolling trigger (Zapier)
/api/triggers.phpGETList webhook events
/api/subscribe.phpPOSTSubscribe a URL to an event
/api/unsubscribe.phpPOSTRemove a subscription

Response format

On success each endpoint returns its result under a named key — there is no ok/data wrapper. The key varies by endpoint, e.g. { "tenant": { … } }, { "charge": { … } }, { "broadcast_id": 5 }. On failure you get an HTTP 4xx with { "error": "message" } (auth failures return HTTP 401 with { "error": "unauthorized", "message": "…" }).

Full request/response details for every endpoint, webhook payloads, signature verification and platform setup are in the dedicated Integrations & API guide.

Troubleshooting

SymptomLikely fix
Emails not arrivingUse Settings → General → Email → Test connection. For Gmail you must use a 16-char App Password, not your normal password.
SMS not arrivingTest connection on the SMS tab. Numbers must be in international format (+ and country code).
API call returns 404Add the .php extension to the endpoint URL.
Deactivate didn't stickResolved in the current build — re-upload the latest settings/users.php.
Manager sees a page they shouldn'tOpen Settings → Users & Roles → Edit on that manager and make sure only the allowed areas are ticked (ticked = allowed). Save with at least one box ticked — a manager with nothing saved keeps full access.
Card payments failCheck Stripe keys in config.php, that the webhook is set, and that the site has a valid SSL certificate.
Scheduled emails never sendConfirm the relevant cron job in _app/cron/ is registered on the server.
_app/ files load in browserMake sure the domain points at the project root and .htaccess/mod_rewrite is active.
Need the deep API reference, webhook payloads, or Zapier/Make/n8n walkthroughs? See the Integrations & API guide.

Apartment Building Management Software · User & Admin Guide · v1.5