PropertyMe Entity Relationships¶
This document defines how all entities in the PropertyMe API are related to each other.
Overview¶
The PropertyMe API models a property management system with these core concepts:
| Entity | Description | API Endpoint |
|---|---|---|
| Property | A rental or sale property (internally called "Lot") | /lots |
| Contact | People: owners, tenants, suppliers | /contacts |
| Member | Staff/team members at the agency | /members |
| Tenancy | A rental agreement between property and tenant | /tenancies |
| Job | Maintenance work orders | /jobtasks |
| Inspection | Property condition inspections | /inspections |
| Task | General workflow tasks/todos | /tasks |
Contact Roles¶
A single Contact can have multiple roles, indicated by boolean flags:
is_owner - Property owner
is_tenant - Tenant/renter
is_supplier - Maintenance supplier/tradesperson
is_seller - Property seller
Entity Relationship Diagram¶
erDiagram
Property ||--o| Contact : "owner_contact_id"
Property ||--o| Contact : "tenant_contact_id"
Property ||--o| Contact : "strata_manager_contact_id"
Property ||--o| Member : "active_manager_member_id"
Property ||--o| Tenancy : "active_tenancy_id"
Property ||--o| Ownership : "active_ownership_id"
Property ||--o| Listing : "active_rental_listing_id"
Property ||--o| Listing : "active_sale_listing_id"
Tenancy ||--|| Property : "lot_id"
Tenancy ||--|| Contact : "contact_id (tenant)"
Tenancy ||--o| Ownership : "active_ownership_id"
TenancyBalance ||--|| Property : "lot_id"
TenancyBalance ||--|| Contact : "contact_id (tenant)"
TenancyBalance ||--o| Ownership : "active_ownership_id"
Job ||--|| Property : "lot_id"
Job ||--o| Contact : "owner_contact_id"
Job ||--o| Contact : "tenant_contact_id"
Job ||--o| Contact : "contact_id (reporter)"
Job ||--o| Member : "manager_member_id"
Inspection ||--|| Property : "lot_id"
Inspection ||--o| Contact : "owner_contact_id"
Inspection ||--o| Contact : "tenant_contact_id"
Inspection ||--o| Contact : "contact_id"
Inspection ||--o| Member : "manager_member_id"
Task ||--o| Property : "lot_id"
Task ||--o| Contact : "owner_contact_id"
Task ||--o| Contact : "tenant_contact_id"
Task ||--o| Contact : "contact_id"
Task ||--o| Member : "manager_member_id"
Contact ||--o{ ContactPerson : "has many"
Contact ||--o{ FolioAccount : "has many"
Simplified Overview¶
graph TB
subgraph "Core Entities"
P[Property/Lot]
C[Contact]
M[Member]
T[Tenancy]
end
subgraph "Work Items"
J[Job]
I[Inspection]
TK[Task]
end
P -->|owner_contact_id| C
P -->|tenant_contact_id| C
P -->|active_manager_member_id| M
P -->|active_tenancy_id| T
T -->|lot_id| P
T -->|contact_id| C
J -->|lot_id| P
J -->|owner_contact_id / tenant_contact_id / contact_id| C
J -->|manager_member_id| M
I -->|lot_id| P
I -->|owner_contact_id / tenant_contact_id / contact_id| C
I -->|manager_member_id| M
TK -->|lot_id| P
TK -->|owner_contact_id / tenant_contact_id / contact_id| C
TK -->|manager_member_id| M
Core Entities¶
Property (Lot)¶
The central entity representing a rental or sale property.
| Field | Target Entity | Description |
|---|---|---|
id |
- | Primary key |
owner_contact_id |
Contact | The property owner |
tenant_contact_id |
Contact | Current tenant (if rented) |
strata_manager_contact_id |
Contact | Strata/body corporate manager |
active_manager_member_id |
Member | Assigned property manager (staff) |
active_tenancy_id |
Tenancy | Current active tenancy agreement |
active_ownership_id |
Ownership | Current ownership record |
properties = await client.properties.all()
property_detail = await client.properties.get("property-id")
Contact¶
Represents people in the system: owners, tenants, suppliers.
| Field | Target Entity | Description |
|---|---|---|
id |
- | Primary key |
customer_id |
Customer | The agency this contact belongs to |
Role Flags:
is_owner- This contact owns propertiesis_tenant- This contact rents propertiesis_supplier- This contact provides maintenance servicesis_seller- This contact is selling a property
contacts = await client.contacts.all()
contact_detail = await client.contacts.get("contact-id")
Member¶
Agency staff members who manage properties.
| Field | Target Entity | Description |
|---|---|---|
id |
- | Primary key |
customer_id |
Customer | The agency this member works for |
members = await client.members.all()
Tenancy¶
A rental agreement linking a property to a tenant.
| Field | Target Entity | Description |
|---|---|---|
id |
- | Primary key |
lot_id |
Property | The rented property |
contact_id |
Contact | The tenant contact |
active_ownership_id |
Ownership | Related ownership record |
tenancies = await client.tenancies.all()
Job (Maintenance)¶
Maintenance work orders for properties.
| Field | Target Entity | Description |
|---|---|---|
id |
- | Primary key |
lot_id |
Property | The property needing work |
owner_contact_id |
Contact | The property owner |
tenant_contact_id |
Contact | The tenant (if relevant) |
contact_id |
Contact | Who reported the issue |
manager_member_id |
Member | Assigned staff member |
jobs = await client.jobs.all()
job_detail = await client.jobs.get("job-id")
Inspection¶
Property condition inspections (entry, exit, routine).
| Field | Target Entity | Description |
|---|---|---|
id |
- | Primary key |
lot_id |
Property | The inspected property |
owner_contact_id |
Contact | The property owner |
tenant_contact_id |
Contact | The tenant |
manager_member_id |
Member | Assigned inspector |
inspections = await client.inspections.all()
inspection = await client.inspections.get("inspection-id")
Task¶
General workflow tasks/todos.
| Field | Target Entity | Description |
|---|---|---|
id |
- | Primary key |
lot_id |
Property | Related property (optional) |
owner_contact_id |
Contact | Related owner (optional) |
tenant_contact_id |
Contact | Related tenant (optional) |
manager_member_id |
Member | Assigned staff member |
tasks = await client.tasks.all()
task = await client.tasks.get("task-id")
Quick Reference¶
"Where do I find...?"¶
| To find... | Use this field on... | Points to... |
|---|---|---|
| Property's owner | Property.owner_contact_id |
Contact |
| Property's tenant | Property.tenant_contact_id |
Contact |
| Property's manager | Property.active_manager_member_id |
Member |
| Property's tenancy | Property.active_tenancy_id |
Tenancy |
| Tenancy's property | Tenancy.lot_id |
Property |
| Tenancy's tenant | Tenancy.contact_id |
Contact |
| Job's property | Job.lot_id |
Property |
| Job's owner | Job.owner_contact_id |
Contact |
| Job's tenant | Job.tenant_contact_id |
Contact |
| Job's reporter | Job.contact_id |
Contact |
| Job's manager | Job.manager_member_id |
Member |
Common Foreign Key Patterns¶
| Pattern | Target Entity | Example Fields |
|---|---|---|
*_contact_id |
Contact | owner_contact_id, tenant_contact_id |
*_member_id |
Member | manager_member_id, active_manager_member_id |
lot_id |
Property | lot_id (in Tenancy, Job, Inspection, Task) |
API Quirks¶
Property List vs Detail Response¶
Important
The Property list response (/lots) contains MORE relationship data than the Property detail response (/lots/{id}/detail).
| Field | List Response | Detail Response |
|---|---|---|
owner_contact_id |
Yes | No |
tenant_contact_id |
Yes | No |
active_manager_member_id |
Yes | No |
active_tenancy_id |
Yes | Yes |
active_ownership_id |
Yes | Yes |
Recommendation: Use the list endpoint and filter client-side when you need relationship IDs.
Reference Text Fields¶
Many responses include both ID and human-readable text:
owner_contact_id+owner_contact_reference(e.g., "Gary Jarrel (Owner)")tenant_contact_id+tenant_contact_reference(e.g., "Naomi Saldano")lot_id+lot_reference(e.g., "Horne St 41")
The *_reference fields are display strings - always use *_id fields for lookups.
Example: Resolving Related Entities¶
# Get property from list (has all relationship IDs)
properties = await client.properties.all()
prop = next(p for p in properties if "Horne" in p.address_text)
# Resolve owner contact
owner = await client.contacts.get(prop.owner_contact_id)
print(owner.contact.name_text) # "Gary Jarrel"
print(owner.contact.is_owner) # True
# Resolve tenant contact
tenant = await client.contacts.get(prop.tenant_contact_id)
print(tenant.contact.name_text) # "Naomi Saldano"
print(tenant.contact.is_tenant) # True
Summary¶
The PropertyMe data model centers around Property as the core entity, with Contacts representing people (owners, tenants, suppliers) and Members representing agency staff. Work items (Jobs, Inspections, Tasks) link back to properties and relevant contacts/members.
Key patterns:
- Properties have an owner contact and optionally a tenant contact
- Properties are assigned to a manager (Member)
- Tenancies link properties to tenants with financial data
- Work items reference the property, relevant contacts, and assigned manager
- Contacts can have multiple roles (owner, tenant, supplier, seller)