Skip to content

API Usage Guide

This guide covers programmatic usage of PyPropertyMe for accessing the PropertyMe API.

Client Overview

The Client class provides a clean interface to all PropertyMe API endpoints.

from pypropertyme.client import Client

# Create client with OAuth token
client = Client.get_client(token)

# Access entity clients
contacts = await client.contacts.all()
properties = await client.properties.all()

Basic Usage

Fetching All Entities

Every entity client supports the .all() method to fetch all records:

# Fetch all contacts
contacts = await client.contacts.all()

# Fetch all properties
properties = await client.properties.all()

# Fetch all tenancies
tenancies = await client.tenancies.all()

# Fetch all tenancy balances
balances = await client.tenancy_balances.all()

# Fetch all members
members = await client.members.all()

# Fetch all tasks
tasks = await client.tasks.all()

# Fetch all inspections
inspections = await client.inspections.all()

# Fetch all jobs
jobs = await client.jobs.all()

Fetching by ID

Most entity clients support fetching a single record with full details:

# Get contact with full details
contact = await client.contacts.get("contact-id")
# Returns ContactDetail with nested contact data

# Get property with full details
property = await client.properties.get("property-id")
# Returns PropertyDetail with ownership, tenancy, listings

# Get task
task = await client.tasks.get("task-id")

# Get job
job = await client.jobs.get("job-id")

# Get inspection with full report
inspection = await client.inspections.get("inspection-id")
# Returns InspectionDetail with embedded property, tenant, owner, report
# Get tenancy balance by tenancy ID
balance = await client.tenancy_balances.get("tenancy-id")

API Limitations

members and tenancies do not support fetching by ID due to PropertyMe API limitations.

Property Endpoints

Properties have additional filtered endpoints with pagination support:

# All properties (no pagination)
all_properties = await client.properties.all()

# Filtered endpoints (with pagination)
sales = await client.sales_properties.all()
rentals = await client.rental_properties.all()
archived = await client.archived_properties.all()
vacant = await client.vacant_properties.all()

Tenancy Endpoints

# All tenancies
tenancies = await client.tenancies.all()

# Tenancy financial balances
balances = await client.tenancy_balances.all()

Model Types

PyPropertyMe uses Pydantic models for type safety. Each entity has a list model and (usually) a detail model:

Entity List Model Detail Model
Contact Contact ContactDetail
Property Property PropertyDetail
Tenancy Tenancy -
TenancyBalance TenancyBalance TenancyBalance
Member Member -
Task Task -
Inspection Inspection InspectionDetail
Job Job -

Working with Models

# Models are Pydantic BaseModel instances
contact = contacts[0]

# Access attributes directly
print(contact.name_text)
print(contact.email)
print(contact.is_owner)

# Serialize to dict
contact_dict = contact.model_dump()

# Serialize to JSON
contact_json = contact.model_dump_json()

Detail Models

Detail models often have nested structures:

# ContactDetail has nested contact object
contact_detail = await client.contacts.get("contact-id")
print(contact_detail.contact.name_text)
print(contact_detail.contact.roles)
print(contact_detail.folio_id)

# PropertyDetail has ownership and tenancy info
property_detail = await client.properties.get("property-id")
print(property_detail.ownership)
print(property_detail.tenancy)

# InspectionDetail has embedded related entities
inspection_detail = await client.inspections.get("inspection-id")
print(inspection_detail.property)
print(inspection_detail.tenant)
print(inspection_detail.owner)
print(inspection_detail.inspection_report)

Pagination

The .all() method automatically handles pagination for endpoints that support it:

# Automatically fetches all pages
rentals = await client.rental_properties.all()

For manual control over pagination, use the iterator:

# Use get_iter() for paginated endpoints
async for property in client.rental_properties.get_iter():
    print(property.reference)

Pagination Support

Not all endpoints support pagination. The main properties endpoint does NOT support pagination; use the filtered endpoints (rental_properties, sales_properties, etc.) for pagination.

Complete Example

import asyncio
import json
from pathlib import Path
from pypropertyme.client import Client

async def main():
    # Load tokens from CLI authentication
    token_path = Path.home() / ".pypropertyme" / "tokens.json"
    token = json.loads(token_path.read_text())

    # Create client
    client = Client.get_client(token)

    # Fetch all properties
    properties = await client.properties.all()
    print(f"Found {len(properties)} properties")

    # Get details for first property
    if properties:
        detail = await client.properties.get(properties[0].id)
        print(f"Property: {detail.address.full_address}")
        if detail.ownership:
            print(f"Owner: {detail.ownership}")
        if detail.tenancy:
            print(f"Tenancy: {detail.tenancy}")

asyncio.run(main())

Next Steps