Overview
The Expenses system allows property managers to record, categorize, and assign property-related costs to the appropriate party. Every expense includes a payableBy field that determines who is financially responsible.
| Payable By | Description |
|---|---|
| OWNER | Deducted from owner payout at end of month |
| TENANT | Invoiced to tenant as an outstanding charge |
| PM | Absorbed by the property management company |
| INSURANCE | Tracked for insurance claim reimbursement |
| SPLIT | Cost divided among multiple parties by percentage |
Creating Expenses
Expenses can be created from three entry points in the application: the dedicated expense form, the property detail page, or directly from a unit page. Each path pre-fills context such as property ID and unit ID.
{
"propertyId": "prop_abc123",
"unitId": "unt_456",
"category": "MAINTENANCE",
"description": "HVAC filter replacement",
"amount": 18500,
"payableBy": "OWNER",
"vendorName": "CoolAir Services",
"date": "2025-01-15",
"recurring": false,
"receiptUrl": null
}Tenant Invoicing Flow
When an expense is assigned to a tenant, the system automatically creates a Payment record, sends an invoice email, and surfaces the charge on the tenant dashboard alongside rent.
Flow: Expense created (payableBy: TENANT) → Payment record generated → Invoice email sent → Charge appears on tenant dashboard → Tenant pays via card or ACH → Ledger entry recorded.
{
"expenseId": "exp_789",
"tenantId": "tnt_012",
"amount": 25000,
"description": "Broken window repair - Unit 4B",
"dueDate": "2025-02-01",
"status": "PENDING",
"paymentId": "pay_inv001"
}Split Expenses
Split expenses distribute a single cost across multiple parties. Each split entry specifies a party type and a percentage. The sum of all percentages must equal 100.
{
"expenseId": "exp_split001",
"amount": 50000,
"payableBy": "SPLIT",
"splits": [
{ "party": "OWNER", "percentage": 60, "amount": 30000 },
{ "party": "TENANT", "percentage": 30, "amount": 15000 },
{ "party": "PM", "percentage": 10, "amount": 5000 }
]
}Approval Workflow
Expenses submitted by maintenance staff or vendors enter aPENDING state. The property manager reviews and either approves or rejects each expense. Approved expenses proceed to invoicing or payout deduction. Rejected expenses are marked with a reason and archived.
| Status | Description |
|---|---|
| PENDING | Awaiting PM review and approval |
| APPROVED | Approved and queued for invoicing or payout deduction |
| REJECTED | Rejected with reason, archived for records |
Recurring Expenses
Expenses marked as recurring are automatically duplicated on the 1st of each month by the recurring-expenses cron job. The new expense inherits all fields from the original, with the date set to the current month. If the expense is tenant-payable, a new invoice is also generated automatically.
{
"expenseId": "exp_rec001",
"recurring": true,
"frequency": "MONTHLY",
"category": "UTILITIES",
"description": "Common area electricity",
"amount": 12000,
"payableBy": "TENANT",
"nextDuplicateDate": "2025-03-01"
}Receipt Upload
Each expense supports one or more receipt attachments. Supported formats include JPEG, PNG, and PDF. Receipts are uploaded to cloud storage and linked to the expense record via a signed URL.
{
"expenseId": "exp_789",
"receipts": [
{
"id": "rcpt_001",
"fileName": "hvac-invoice.pdf",
"fileType": "application/pdf",
"fileSize": 245000,
"url": "https://storage.doorstax.com/receipts/rcpt_001.pdf",
"uploadedAt": "2025-01-15T10:30:00.000Z"
}
]
}API Reference
All expense endpoints require authentication and are scoped to the property manager's organization.
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/expenses | Create a new expense |
| GET | /api/expenses | List expenses with filters |
| GET | /api/expenses/:id | Get expense details |
| PUT | /api/expenses/:id | Update an expense |
| DELETE | /api/expenses/:id | Delete an expense |
| POST | /api/expenses/:id/approve | Approve a pending expense |
| POST | /api/expenses/:id/reject | Reject a pending expense |
| POST | /api/expenses/:id/receipts | Upload a receipt attachment |