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
| Component | Minimum | Recommended |
|---|---|---|
| PHP | 8.0 | 8.2+ |
| MySQL / MariaDB | 5.7 / 10.3 | 8.0+ / 10.6+ |
| Web server | Apache or Nginx | Apache with mod_rewrite |
| PHP extensions | PDO, PDO_MySQL, mbstring, curl, openssl, fileinfo, json, session | |
| SSL certificate | Required for Stripe card payments. Free from Let's Encrypt. | |
| Disk space | 100 MB | 5 GB+ (for uploaded files) |
Installation
Option A — Web installer (recommended)
Upload all files to your server. The project root folder is the web document root — point your domain at it.
Create an empty MySQL database (e.g. apartment_db) in cPanel → MySQL Databases.
Open https://yourdomain.com/install/ in a browser.
Follow the wizard: Requirements check → Database → Site settings → Admin account.
The installer loads the schema, creates your admin account, writes _app/config/config.php, and removes itself.
Option B — Manual install
Upload files and point your domain at the project root folder.
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.
Copy _app/config/config.sample.php to _app/config/config.php and fill in your values.
Visit /register.php and create your account. The first account ever registered automatically becomes the Admin.
After the admin exists, public registration closes automatically (unless you re-enable it in settings). You can also remove register.php for extra safety.
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._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.
| Role | Can do |
|---|---|
| Admin | Everything, always. Admins are never page-restricted. Only an admin can change roles, restrict managers, delete users, and edit other admins. |
| Manager | Runs 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). |
| Tenant | Their 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:
| Key | Example | Required? |
|---|---|---|
DB_HOST | localhost | Required |
DB_NAME | apartment_db | Required |
DB_USER / DB_PASS | your DB user & password | Required |
APP_URL | https://yourdomain.com | Required |
APP_KEY | long random string | Required |
UPLOAD_DIR | /home/yoursite/uploads | Required |
MAIL_FROM / MAIL_FROM_NAME | noreply@yourdomain.com | Optional |
STRIPE_SECRET_KEY | sk_live_… | Optional |
STRIPE_PUBLIC_KEY | pk_live_… | Optional |
STRIPE_WEBHOOK_SECRET | whsec_… | Optional |
APP_ENV | production | Optional |
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
- Turn on 2-Step Verification on the Google account.
- Create an App Password at myaccount.google.com/apppasswords.
- Host
smtp.gmail.com, port587, 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.
- Sign up at twilio.com and get a phone number.
- Copy your Account SID and Auth Token from the Twilio console.
- Enter them plus your Twilio From number (in international format, e.g.
+15551234567).
+. 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.
- Sign up at stripe.com.
- Copy your API keys from Developers → API keys into
_app/config/config.php(STRIPE_SECRET_KEY,STRIPE_PUBLIC_KEY). - Add a Stripe webhook pointing to
https://yourdomain.com/webhooks/stripe.phpand copy its signing secret intoSTRIPE_WEBHOOK_SECRET. - Tune behaviour in Settings → Payment Settings.
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
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
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
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
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
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
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
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
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
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
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
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)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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.
Editing a user & changing passwords Improved
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
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
- 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
.php extension — e.g. /api/action_create_tenant.php. There is no extension-less routing; the short form returns 404.Endpoints
| Endpoint | Method | Action |
|---|---|---|
/api/action_create_tenant.php | POST | Invite a new tenant |
/api/action_create_work_order.php | POST | Open a maintenance request |
/api/action_record_payment.php | POST | Record a payment |
/api/action_send_message.php | POST | Send a broadcast |
/api/action_create_charge.php | POST | Add a charge to a tenant |
/api/trigger_poll.php | GET | Polling trigger (Zapier) |
/api/triggers.php | GET | List webhook events |
/api/subscribe.php | POST | Subscribe a URL to an event |
/api/unsubscribe.php | POST | Remove 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
| Symptom | Likely fix |
|---|---|
| Emails not arriving | Use Settings → General → Email → Test connection. For Gmail you must use a 16-char App Password, not your normal password. |
| SMS not arriving | Test connection on the SMS tab. Numbers must be in international format (+ and country code). |
| API call returns 404 | Add the .php extension to the endpoint URL. |
| Deactivate didn't stick | Resolved in the current build — re-upload the latest settings/users.php. |
| Manager sees a page they shouldn't | Open 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 fail | Check Stripe keys in config.php, that the webhook is set, and that the site has a valid SSL certificate. |
| Scheduled emails never send | Confirm the relevant cron job in _app/cron/ is registered on the server. |
_app/ files load in browser | Make sure the domain points at the project root and .htaccess/mod_rewrite is active. |
Apartment Building Management Software · User & Admin Guide · v1.5