Maintenance Request Management
Maintenance Request Management
The myProp portal provides a full maintenance request lifecycle for tenants, landlords, and property managers — from submitting a new issue through to job completion, contractor tracking, and note history.
Overview
Maintenance requests are backed by the AgentOS (letmc.com) API. The portal surfaces real-time job data and enables two-way interactions: clients can report issues, track progress, communicate via notes, and monitor contractor assignments without contacting the agency directly.
Submitting a Request
Clients can report a maintenance issue by providing:
- Title — A short description of the problem.
- Description — Detailed account of the issue (may be skipped for emergency categories — see Step-Skip Logic).
- Category — Selected from the agency's configured category list.
- Priority — Urgency level for the job.
- Preferred date and time — Scheduling preferences (may be skipped for emergency categories).
- Access instructions — Entry notes for the contractor.
- Contact details — Phone and email for coordination.
Tracking Jobs
Once submitted, a maintenance job can be tracked in the portal. The following information is surfaced per job:
- Job status (open, in progress, awaiting contractor, completed, cancelled)
- Reported date and reported-by details
- Assigned contractor name, ID, and contact phone number
- Estimated and actual costs
- Preferred scheduling details
- Last updated timestamp
- Full note history
Job Statuses
| Status | Meaning |
|---|---|
| Open | Reported, not yet actioned |
| In Progress | Work has started |
| Awaiting Contractor | Pending contractor assignment or attendance |
| Completed | Work finished |
| Cancelled | Request withdrawn or closed |
Notes
Notes can be added to any active maintenance job by authorised users. Notes are listed in chronological order and distinguish between user-authored notes and system-generated notes.
Summary Statistics
A per-property maintenance summary provides aggregate KPIs:
- Total requests
- Open requests
- In-progress requests
- Completed requests
- Awaiting-contractor requests
- Average completion time (days)
Step-Skip Logic
Certain high-urgency categories automatically skip non-essential form steps to speed up emergency reporting.
Skipped Steps by Category
| Category | Skips Description | Skips Scheduling |
|---|---|---|
| Emergency | ✓ | ✓ |
| Urgent | ✓ | ✓ |
| Gas Leak | ✓ | ✓ |
| Flood | ✓ | ✓ |
| Fire | ✓ | ✓ |
| Break-in | ✓ | ✓ |
| No Heating | ✓ | — |
| No Hot Water | ✓ | — |
Step-skip behaviour is resolved in the following order:
- API flags — If the AgentOS category record includes
SkipDescription: trueorSkipScheduling: true, those steps are skipped unconditionally. - Emergency flag — If the record includes
IsEmergency: true(or equivalent), both steps are skipped. - Category name match — If the category name matches a known emergency name (case-insensitive), the appropriate steps are skipped.
FixFlo Integration
For agencies using FixFlo as their maintenance portal, the system resolves the correct maintenance URL using a priority chain:
- Company-level FixFlo URL
- Person-level FixFlo URL
- None — standard in-portal flow
The removeMaintenanceJobs flag is respected: if set, the standard job list is suppressed in favour of the FixFlo redirect.
API Endpoints
All endpoints are available under the maintenance tRPC namespace and require authentication.
maintenance.status
Check whether the maintenance service is available for the current agency.
maintenance.categories
Fetch the list of available maintenance categories, including step-skip flags for each.
Returns: Array of categories, each with:
categoryIdnamedescriptionparentCategoryIdskipDescriptionStep(boolean)skipSchedulingStep(boolean)displayOrder
maintenance.submit
Create a new maintenance request.
Input:
{
propertyId: string;
tenancyId?: string;
title: string;
description: string;
categoryId?: string;
priority?: string;
preferredDate?: string; // ISO date string
preferredTime?: string;
accessInstructions?: string;
contactPhone?: string;
contactEmail?: string;
}
Returns: { jobId, success, message }
maintenance.list
Paginated list of maintenance jobs for a property.
Input: { propertyId, status?, offset?, count? }
Returns: Array of MaintenanceRequest objects.
maintenance.details
Fetch a single maintenance job with its full note history (parallel fetch).
Input: { jobId, shortName }
Returns: { request: MaintenanceRequest, notes: MaintenanceNote[] }
maintenance.notes
List all notes for a maintenance job.
Input: { jobId, shortName }
Returns: Array of MaintenanceNote objects.
maintenance.addNote
Add a note to an existing maintenance job.
Input: { jobId, shortName, text }
Returns: Success indicator.
maintenance.updateStatus
Update the status of a maintenance job (complete, reopen, cancel).
Input: { jobId, shortName, status: 'completed' | 'reopened' | 'cancelled' }
Returns: Success indicator.
maintenance.summary
Fetch aggregate maintenance statistics for a property.
Input: { propertyId, shortName }
Returns: MaintenanceSummary object with open/in-progress/completed counts and average completion days.
maintenance.resolveFixflo
Resolve the FixFlo maintenance URL for the current user/agency context.
Input: { shortName, personId, companyId? }
Returns: { url: string | null, removeMaintenanceJobs: boolean }
Data Model
MaintenanceRequest
{
jobId: string;
propertyId: string;
propertyAddress: string | null;
tenancyId: string | null;
title: string;
description: string | null;
status: string;
priority: string | null;
category: string | null;
categoryId: string | null;
reportedDate: string | null;
reportedBy: string | null;
completedDate: string | null;
estimatedCost: number | null;
actualCost: number | null;
contractorName: string | null;
contractorId: string | null;
contractorPhone: string | null;
accessInstructions: string | null;
preferredDate: string | null;
preferredTime: string | null;
lastUpdated: string | null;
metadata: Record<string, unknown>;
}
MaintenanceNote
{
noteId: string;
jobId: string;
text: string;
createdAt: string | null;
createdBy: string | null;
type: string | null;
isSystemNote: boolean;
metadata: Record<string, unknown>;
}
MaintenanceSummary
{
totalRequests: number;
openRequests: number;
inProgressRequests: number;
completedRequests: number;
awaitingContractorRequests: number;
averageCompletionDays: number | null;
}
Error Handling
- 404 responses from AgentOS return
nullor empty arrays — no error is thrown. - Non-critical errors are captured via
captureErrorfor observability without surfacing to the client. - Critical errors (e.g. service misconfiguration) throw
LetmcNotConfiguredError.