Contractor Portal API
Contractor Portal API
The Contractor Portal API provides tRPC endpoints and a service layer for contractor-specific operations within myProp. It enables contractors to view their account details, manage assigned maintenance jobs, track financial statements, and submit invoices — all connected in real time to the AgentOS (letmc.com) API.
Authentication
All contractor endpoints are protected and require an authenticated session. Unauthenticated requests are rejected before reaching the handler.
Endpoints
All endpoints are available under the contractor tRPC namespace (e.g. contractor.account, contractor.maintenanceJobs).
contractor.status
Returns a simple alive signal for the contractor router. Useful for connectivity checks.
contractor.insights
Returns aggregated dashboard KPIs for the contractor.
Response fields:
| Field | Type | Description |
|---|---|---|
totalAssignedJobs | number | Total jobs ever assigned to this contractor |
activeJobs | number | Jobs currently in progress |
completedJobs | number | Jobs marked as completed |
pendingPaymentAmount | number | Total value of unpaid statement entries |
totalEarnedAmount | number | Cumulative earned amount from statements |
Data is aggregated across multiple AgentOS API calls using Promise.allSettled so partial failures do not block the dashboard.
contractor.account
Fetches the contractor's profile from AgentOS.
Input:
shortName— Agency short name (AgentOS identifier)contractorId— Contractor's AgentOS ID
Response fields:
| Field | Type | Description |
|---|---|---|
contractorId | string | AgentOS contractor ID |
companyName | string | Registered company name |
displayName | string | Display name |
email | string | null | Primary email address |
phone | string | null | Phone number |
mobile | string | null | Mobile number |
address | string | null | Full address (combined) |
addressLine1–3 | string | null | Individual address lines |
postcode | string | null | Postcode |
vatNumber | string | null | VAT registration number |
companyRegNumber | string | null | Companies House number |
isActive | boolean | Whether the contractor account is active |
branchId | string | null | Associated agency branch |
trades | string[] | List of trade types |
metadata | Record<string, unknown> | Raw AgentOS fields |
Returns null if the contractor is not found (404 from AgentOS).
contractor.contacts
Lists contact persons associated with the contractor account.
Response: Array of ContractorContact objects.
| Field | Type | Description |
|---|---|---|
contactId | string | Contact ID |
name | string | Full name |
email | string | null | Email address |
phone | string | null | Phone number |
mobile | string | null | Mobile number |
role | string | null | Job title or role |
isPrimary | boolean | Whether this is the primary contact |
metadata | Record<string, unknown> | Raw AgentOS fields |
Errors from this endpoint are swallowed; an empty array is returned on failure.
contractor.maintenanceJobs
Returns a paginated list of maintenance jobs assigned to the contractor.
Input:
shortName— Agency short namecontractorId— Contractor IDoffset(optional) — Pagination offset (default: 0)count(optional) — Page size (default: agency-level default)
Response: Array of ContractorMaintenanceJob objects.
| Field | Type | Description |
|---|---|---|
jobId | string | Job ID |
propertyId | string | Associated property ID |
propertyAddress | string | null | Human-readable property address |
title | string | Job title/summary |
description | string | null | Detailed job description |
status | string | Current status (e.g. Open, Completed) |
priority | string | null | Priority level |
reportedDate | string | null | ISO date when reported |
completedDate | string | null | ISO date when completed |
estimatedCost | number | null | Estimated job cost |
actualCost | number | null | Final cost on completion |
category | string | null | Job category (e.g. Plumbing, Electrical) |
tenantName | string | null | Tenant at the property |
landlordName | string | null | Landlord name |
accessDetails | string | null | Access/entry instructions |
metadata | Record<string, unknown> | Raw AgentOS fields |
contractor.maintenanceJobDetails
Fetches full details for a single maintenance job.
Input:
shortName,contractorId,jobId
Response: Single ContractorMaintenanceJob object, or null if not found.
contractor.maintenanceJobNotes
Returns notes attached to a specific maintenance job.
Input:
shortName,contractorId,jobId
Response: Array of ContractorJobNote objects.
| Field | Type | Description |
|---|---|---|
noteId | string | Note ID |
jobId | string | Parent job ID |
text | string | Note content |
createdAt | string | null | ISO timestamp |
createdBy | string | null | Author name |
type | string | null | Note type/category |
metadata | Record<string, unknown> | Raw AgentOS fields |
Errors are swallowed; returns an empty array on failure.
contractor.toggleJobCompletion
Toggles the completion status of a maintenance job (PATCH).
Input:
shortName,contractorId,jobIdcompleted—boolean—trueto mark complete,falseto reopen
contractor.addJobNote
Adds a note to a maintenance job (POST).
Input:
shortName,contractorId,jobIdtext—string— Note content
contractor.statements
Returns historical financial statements for the contractor.
Input:
shortName,contractorIddateFrom(optional) — Start of date range (ISO string)dateTo(optional) — End of date range (ISO string)
Response: ContractorStatement object.
| Field | Type | Description |
|---|---|---|
entries | ContractorStatementEntry[] | Line items |
openingBalance | number | null | Period opening balance |
closingBalance | number | null | Period closing balance |
totalDebits | number | null | Sum of debits |
totalCredits | number | null | Sum of credits |
periodStart | string | null | ISO start date |
periodEnd | string | null | ISO end date |
Each ContractorStatementEntry includes: entryId, date, description, debit, credit, balance, jobId, propertyAddress, category, invoiceNumber, metadata.
contractor.pendingStatements
Returns unpaid/pending statement entries.
Response: Array of PendingStatementEntry objects.
| Field | Type | Description |
|---|---|---|
entryId | string | Entry ID |
date | string | null | Transaction date |
description | string | Description/narrative |
amount | number | Pending amount |
jobId | string | null | Related job ID |
propertyAddress | string | null | Related property |
invoiceNumber | string | null | Invoice reference |
status | string | null | Payment status |
metadata | Record<string, unknown> | Raw AgentOS fields |
contractor.submitInvoice
Submits an invoice for a completed maintenance job (POST).
Input:
shortName,contractorId,jobId- Invoice details (amount, reference, etc.) — validated by Zod schema
Response: InvoiceSubmissionResult
| Field | Type | Description |
|---|---|---|
invoiceId | string | null | ID assigned by AgentOS |
success | boolean | Whether the submission was accepted |
message | string | null | Confirmation or error message from AgentOS |
metadata | Record<string, unknown> | Raw AgentOS response fields |
Error Handling
| Scenario | Behaviour |
|---|---|
| 404 from AgentOS | Returns null or [] — does not throw |
| Non-configured AgentOS API | Throws LetmcNotConfiguredError |
| Server-side AgentOS error | Throws; captured via captureError |
| Non-critical endpoints (contacts, notes) | Errors swallowed, returns empty array |
Field Mapping
All AgentOS PascalCase response fields are mapped to camelCase typed interfaces. The service layer handles both primary and alternative field names returned by different AgentOS API versions (e.g. CompanyName / Company, EmailAddress / Email, Phone / PhoneNumber).
Architecture
Follows the same patterns as the Landlord and Tenant portal service layers:
letmcClienthandles HTTP with retry and timeout- 404 errors return
null/[]for graceful UI degradation - Dashboard insights use
Promise.allSettledso partial API failures don't block the page - All endpoints are authenticated via
protectedProcedure