WFRMLS Python Client
A comprehensive Python wrapper for the Wasatch Front Regional MLS (WFRMLS) API, providing easy access to all RESO-certified endpoints.
⚠️ Important Notice
Media, History, and Green Verification endpoints are currently unavailable due to server-side issues (504 Gateway Timeouts and missing entity types). These features have been temporarily disabled until the server issues are resolved.
🚀 Quick Start
from wfrmls import WFRMLSClient
client = WFRMLSClient(bearer_token="your_bearer_token")
client = WFRMLSClient()
properties = client.property.get_properties(
top=10,
filter_query="StandardStatus eq 'Active'"
)
property_detail = client.property.get_property("12345678")
members = client.member.get_active_members(top=10)
offices = client.office.get_active_offices(top=10)
📦 Installation
pip install wfrmls
🔧 Setup
Environment Variables
Create a .env
file in your project root:
WFRMLS_BEARER_TOKEN=your_bearer_token_here
Getting Your Bearer Token
- Visit the Vendor Dashboard
- Login to your account
- Navigate to Service Details to retrieve your bearer token
📚 API Reference
Core Resources
- Property - Real estate listings and property data
- Member - Real estate agent information
- Office - Brokerage and office details
- OpenHouse - Open house schedules and events
Service Clients
client.property.get_properties()
client.property.get_property(listing_id)
client.property.search_properties_by_radius(lat, lng, radius)
client.member.get_members()
client.member.get_member(member_id)
client.office.get_offices()
client.office.get_office(office_id)
client.openhouse.get_open_houses()
client.openhouse.get_open_house(openhouse_id)
🔍 Advanced Features
OData Query Support
properties = client.property.get_properties(
select=["ListingId", "ListPrice", "StandardStatus"],
top=50
)
properties = client.property.get_properties(
filter_query="ListPrice ge 200000 and ListPrice le 500000 and StandardStatus eq 'Active'",
orderby="ListPrice desc"
)
properties = client.property.get_properties(
expand=["Media", "Member"],
top=25
)
Geolocation Search
properties = client.property.search_properties_by_radius(
latitude=40.7608,
longitude=-111.8910,
radius_miles=10,
additional_filters="StandardStatus eq 'Active'"
)
polygon = [
{"lat": 40.7608, "lng": -111.8910},
{"lat": 40.7708, "lng": -111.8810},
{"lat": 40.7508, "lng": -111.8710},
{"lat": 40.7608, "lng": -111.8910}
]
properties = client.property.search_properties_by_polygon(
polygon_coordinates=polygon,
additional_filters="PropertyType eq 'Residential'"
)
Data Synchronization
from datetime import datetime, timedelta
cutoff_time = datetime.utcnow() - timedelta(minutes=15)
updates = client.property.get_properties(
filter_query=f"ModificationTimestamp gt {cutoff_time.isoformat()}Z"
)
deleted_records = client.deleted.get_deleted(
filter_query="ResourceName eq 'Property'"
)
🏗️ Architecture
The client follows a modular architecture with service separation:
WFRMLSClient
├── property # Property listings
├── member # Real estate agents
├── office # Brokerages/offices
├── openhouse # Open house events
├── lookup # Lookup tables
├── adu # Accessory Dwelling Units
├── deleted # Deletion tracking
└── data_system # API metadata
Note: Media, History, and Green Verification clients are currently disabled due to server-side issues.
⚠️ Error Handling
from wfrmls.exceptions import (
WFRMLSError,
AuthenticationError,
NotFoundError,
RateLimitError
)
try:
property = client.property.get_property("12345678")
except NotFoundError:
print("Property not found")
except RateLimitError:
print("Rate limit exceeded - wait before retrying")
except AuthenticationError:
print("Invalid bearer token")
except WFRMLSError as e:
print(f"API error: {e}")
📊 Utah Grid Address System
The API supports Utah's unique grid address system:
properties = client.property.get_properties(
filter_query="StreetName eq '9400 S'"
)
🚦 Rate Limits
- 200 records per request maximum
- 15-minute recommended update frequency for data sync
- Use NextLink pagination for large datasets (more efficient than $skip)
🧪 Development
Setup Development Environment
git clone https://github.com/theperrygroup/wfrmls.git
cd wfrmls
python -m venv venv
source venv/bin/activate
pip install -e .[dev]
Running Tests
pytest --cov=wfrmls --cov-report=html
pytest tests/test_property.py
pytest -v
Code Quality
black wfrmls tests
isort wfrmls tests
flake8 wfrmls tests
pylint wfrmls
mypy wfrmls
📝 Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
)
- Follow the style guide in
STYLE_GUIDE.md
- Ensure 100% test coverage
- Commit changes (
git commit -m 'Add amazing feature'
)
- Push to branch (
git push origin feature/amazing-feature
)
- Open a Pull Request
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🔗 Links
🆘 Support
For API access issues, contact UtahRealEstate.com support.
For library issues, open an issue in this repository.