Transaction Builder API¶
Create and manage transaction builders with full participant and property management capabilities.
Overview¶
Transaction Builder Workflow
The Transaction Builder API allows you to:
- Create new transaction builders for various types of real estate transactions
- Configure property details, participants, and financial information
- Manage buyers, sellers, agents, and other transaction participants
- Submit completed transactions for processing
- Convert listings to transactions
- Backward Compatibility with legacy method names
🚨 CRITICAL API REQUIREMENTS
These requirements are MANDATORY for successful API calls:
Location Updates: - Basic address fields (street, city, state, zip) alone will FAIL - Additional fields are REQUIRED: county
, yearBuilt
, mlsNumber
Price/Date Updates: - Basic price fields alone will FAIL - BOTH commission objects are REQUIRED: listingCommission
AND saleCommission
Co-Agent Roles: - ✅ Working: "REAL"
, "BUYERS_AGENT"
, "SELLERS_AGENT"
- ❌ Fails: "LISTING_AGENT"
Owner Agents: - Require specific sequence: location → price/date → participants → owner agent - Need valid officeId
and teamId
Quick Start¶
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
# Step 1: Create transaction builder
transaction_id: str = client.transaction_builder.create_transaction_builder()
# Step 2: Add property information - CRITICAL REQUIREMENTS
# ⚠️ Additional fields beyond basic address are REQUIRED
location_data: Dict[str, Any] = {
"street": "123 Main Street", # Use 'street' not 'address'
"city": "Salt Lake City",
"state": "UTAH", # MUST BE ALL CAPS
"zip": "84101", # Use 'zip' not 'zipCode'
"county": "Salt Lake", # REQUIRED - API fails without this
"yearBuilt": 2020, # REQUIRED - API fails without this
"mlsNumber": "MLS123456" # REQUIRED - API fails without this
}
client.transaction_builder.update_location_info(transaction_id, location_data)
# Step 3: Add price/date information - CRITICAL REQUIREMENTS
# ⚠️ BOTH commission objects are REQUIRED together
price_data: Dict[str, Any] = {
"dealType": "COMPENSATING",
"propertyType": "RESIDENTIAL",
"salePrice": {"amount": 500000, "currency": "USD"},
"representationType": "BUYER",
"listingCommission": { # REQUIRED - cannot omit
"commissionPercent": 3.0,
"percentEnabled": True,
"negativeOrEmpty": False
},
"saleCommission": { # REQUIRED - cannot omit
"commissionPercent": 3.0,
"percentEnabled": True,
"negativeOrEmpty": False
}
}
client.transaction_builder.update_price_and_date_info(transaction_id, price_data)
# Step 4: Add participants (use camelCase)
buyer_data: Dict[str, Any] = {
"firstName": "John", # Use camelCase
"lastName": "Doe", # Use camelCase
"email": "john.doe@email.com",
"phoneNumber": "(555) 123-4567" # Use camelCase
}
client.transaction_builder.add_buyer(transaction_id, buyer_data)
# Step 5: Add co-agent (working roles only)
co_agent_data: Dict[str, Any] = {
"agentId": "bd465129-b224-43e3-b92f-524ea5f53783",
"role": "REAL", # ✅ Working role
"receivesInvoice": False
}
client.transaction_builder.add_co_agent(transaction_id, co_agent_data)
# Step 6: Submit transaction
client.transaction_builder.submit_transaction(transaction_id)
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
# Create listing builder using dedicated method
listing_id: str = client.transaction_builder.create_listing_builder()
# Configure listing-specific details (use camelCase)
seller_data: Dict[str, Any] = {
"firstName": "Jane", # Use camelCase
"lastName": "Smith", # Use camelCase
"email": "jane.smith@email.com",
"phoneNumber": "(555) 987-6543" # Use camelCase
}
client.transaction_builder.add_seller(listing_id, seller_data)
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
# Convert existing listing to transaction
listing_id: str = "existing-listing-id"
response: Dict[str, Any] = client.transaction_builder.convert_listing_to_transaction(listing_id)
transaction_id: str = response['id']
print(f"Converted listing {listing_id} to transaction {transaction_id}")
Core Transaction Management¶
Create Transaction Builder¶
Create empty transaction builder.
This is the starting point for creating a new transaction. After creation, you'll receive a transaction ID that you'll use for all subsequent operations.
⚠️ CRITICAL: Follow the recommended workflow for successful transaction creation. Many endpoints require specific data to be present before they will work.
Recommended Workflow
- Create transaction builder (this method)
- Add location info (update_location_info) - REQUIRES additional fields
- Add price/date info (update_price_and_date_info) - REQUIRES commission objects
- Add buyers/sellers (add_buyer/add_seller) - Works after location data
- Add co-agents (add_co_agent) - Works with specific roles
- Add owner agent (update_owner_agent_info) - Requires complete setup + office/team IDs
Successful Working Example
# Complete working sequence with co-agent
client = RezenClient()
# 1. Create transaction
transaction_id = client.transaction_builder.create_transaction_builder()
# 2. Add location (with required additional fields)
location_data = {
"street": "123 Main Street",
"city": "Salt Lake City",
"state": "UTAH",
"zip": "84101",
"county": "Salt Lake", # REQUIRED
"yearBuilt": 2020, # REQUIRED
"mlsNumber": "MLS123456" # REQUIRED
}
client.transaction_builder.update_location_info(transaction_id, location_data)
# 3. Add price/date (with both commission objects)
price_data = {
"dealType": "COMPENSATING",
"propertyType": "RESIDENTIAL",
"salePrice": {"amount": 550000, "currency": "USD"},
"representationType": "BUYER",
"listingCommission": { # REQUIRED
"commissionPercent": 3.0,
"percentEnabled": True,
"negativeOrEmpty": False
},
"saleCommission": { # REQUIRED
"commissionPercent": 3.0,
"percentEnabled": True,
"negativeOrEmpty": False
}
}
client.transaction_builder.update_price_and_date_info(transaction_id, price_data)
# 4. Add participants
client.transaction_builder.add_buyer(transaction_id, {
"firstName": "John",
"lastName": "Buyer",
"email": "john@example.com",
"phoneNumber": "(801) 555-1234"
})
# 5. Add co-agent (this works immediately)
co_agent_info = {
"agentId": "bd465129-b224-43e3-b92f-524ea5f53783",
"role": "REAL",
"receivesInvoice": False
}
client.transaction_builder.add_co_agent(transaction_id, co_agent_info)
# Result: Complete working transaction with co-agent
print(f"✅ Successfully created transaction {transaction_id} with co-agent")
Builder Types
- "TRANSACTION": Standard real estate transaction
- "LISTING": Property listing
Parameters:
Name | Type | Description | Default |
---|---|---|---|
builder_type | str | Type of builder to create ("TRANSACTION" or "LISTING") | 'TRANSACTION' |
Returns:
Type | Description |
---|---|
str | Transaction builder ID as string |
Raises:
Type | Description |
---|---|
ValidationError | If builder_type is invalid |
RezenError | If transaction creation fails |
Consistent Response Format
The method now returns a consistent {"id": "transaction_id"}
format instead of a raw string.
Create Listing Builder¶
Create a listing builder (wrapper for create_transaction_builder).
Returns:
Type | Description |
---|---|
str | Listing builder ID |
Convenience Method
This is a wrapper around create_transaction_builder(builder_type='LISTING')
for easier listing creation.
Convert Listing to Transaction¶
Convert a listing to a transaction (wrapper for create_builder_from_transaction).
Parameters:
Name | Type | Description | Default |
---|---|---|---|
listing_id | str | Listing ID to convert | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder response data |
Create Different Builder Types
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
# Convert listing to transaction
listing_id = "existing-listing-id"
response: Dict[str, Any] = client.transaction_builder.convert_listing_to_transaction(listing_id)
print(f"New transaction ID: {response['id']}")
Get Transaction Builder¶
Get a specific transaction builder by ID.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder data |
Response Structure
The transaction builder response includes:
- Basic Information: ID, type, status, creation date
- Participants: All buyers, sellers, agents, and other participants
- Property Details: Location, pricing, and property information
- Financial Data: Commission splits and payment information
Submit Transaction¶
Submit a transaction builder to create a transaction.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction preview response data |
Submission Requirements
Before submitting, ensure:
- At least one participant is added
- Property location is specified
- Required financial information is complete
- All mandatory fields are populated
Delete Transaction Builder¶
Delete transaction builder.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Deletion response data |
Deletion Warning
This operation is irreversible. Ensure you have backups of any critical data before deletion.
Participant Management¶
Buyers¶
Add a new buyer.
Important: Use camelCase for field names: - firstName (not first_name) - lastName (not last_name) - phoneNumber (not phone_number)
Example
buyer_info = { "firstName": "John", "lastName": "Doe", "email": "john.doe@example.com", "phoneNumber": "(555) 123-4567" }
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
buyer_info | Dict[str, Any] | Buyer information data with camelCase fields | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder response data |
Required Buyer Fields:
Field | Type | Description |
---|---|---|
firstName | str | Buyer's first name (camelCase) |
lastName | str | Buyer's last name (camelCase) |
email | str | Valid email address |
Optional Buyer Fields:
Field | Type | Description |
---|---|---|
phoneNumber | str | Phone number (camelCase) |
company | str | Company name |
address | str | Mailing address |
Complete Buyer Example
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
transaction_id: str = "your-transaction-id-here"
buyer_data: Dict[str, Any] = {
"firstName": "John", # Use camelCase
"lastName": "Doe", # Use camelCase
"email": "john.doe@email.com",
"phoneNumber": "+1-555-123-4567", # Use camelCase
"company": "Doe Enterprises",
"address": "456 Business Ave, Business City, BC 12345"
}
# Using new method name
response: Dict[str, Any] = client.transaction_builder.add_buyer(transaction_id, buyer_data)
# Or using backward compatibility alias
response: Dict[str, Any] = client.transaction_builder.put_buyer_to_draft(transaction_id, buyer_data)
Sellers¶
Add a new seller to a transaction builder.
Important: Use camelCase for field names: - firstName (not first_name) - lastName (not last_name) - phoneNumber (not phone_number)
Example
seller_info = { "firstName": "Jane", "lastName": "Smith", "email": "jane.smith@example.com", "phoneNumber": "(555) 987-6543" }
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
seller_info | Dict[str, Any] | Seller information data with camelCase fields | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder response data |
Seller Configuration
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
transaction_id: str = "your-transaction-id-here"
seller_data: Dict[str, Any] = {
"firstName": "Jane", # Use camelCase
"lastName": "Smith", # Use camelCase
"email": "jane.smith@email.com",
"phoneNumber": "+1-555-987-6543" # Use camelCase
}
# Using new method name
response: Dict[str, Any] = client.transaction_builder.add_seller(transaction_id, seller_data)
# Or using backward compatibility alias
response: Dict[str, Any] = client.transaction_builder.put_seller_to_draft(transaction_id, seller_data)
Agents & Co-Agents¶
Add a new co-agent to the transaction.
Co-agents can be added at any time after transaction creation, unlike owner agents which require a specific sequence. The co-agent will appear in the transaction's agentsInfo.coAgents array.
⚠️ ROLE LIMITATIONS ⚠️ Based on testing, only certain roles work with co-agents:
✅ WORKING ROLES: - "REAL" - Always works (may display differently based on representationType) - "BUYERS_AGENT" - Works on transactions with location data - "SELLERS_AGENT" - Works on transactions with location data
❌ NON-WORKING ROLES: - "LISTING_AGENT" - Fails with "Bad request: Invalid request"
Required Fields
- agentId (str): UUID of the co-agent (must be a valid agent ID)
- role (str): Agent role - use one of the working roles above
- receivesInvoice (bool): Whether the co-agent receives invoice
Optional Fields
- opCityReferral (bool): Whether this is an OpCity referral (default: False)
- optedInForEcp (bool): Whether opted in for ECP (default: False)
Note on Role Display
The role field accepts "REAL" but may be displayed differently in the response based on the transaction's representationType. For example, if representationType is "BUYER", a co-agent with role "REAL" may appear as "BUYERS_AGENT" in the response.
Working Examples
# ✅ Co-agent with REAL role (always works)
co_agent_info = {
"agentId": "bd465129-b224-43e3-b92f-524ea5f53783",
"role": "REAL",
"receivesInvoice": False,
"opCityReferral": False,
"optedInForEcp": False
}
result = client.add_co_agent(transaction_id, co_agent_info)
# ✅ Co-agent with BUYERS_AGENT role (works with location data)
co_agent_info = {
"agentId": "bd465129-b224-43e3-b92f-524ea5f53783",
"role": "BUYERS_AGENT",
"receivesInvoice": False
}
result = client.add_co_agent(transaction_id, co_agent_info)
# ❌ This FAILS (LISTING_AGENT role not supported)
co_agent_info = {
"agentId": "bd465129-b224-43e3-b92f-524ea5f53783",
"role": "LISTING_AGENT", # This role fails
"receivesInvoice": False
}
# Will return "Bad request: Invalid request"
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
co_agent_info | Dict[str, Any] | Co-agent information data | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder response data with updated co-agents list |
Raises:
Type | Description |
---|---|
ValidationError | If role is not supported or agent ID is invalid |
Agent Roles:
Available Agent Roles
BUYERS_AGENT
: Represents the buyerSELLERS_AGENT
: Represents the sellerLISTING_AGENT
: Lists the propertyDUAL_AGENT
: Represents both parties
Co-Agent Examples
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
transaction_id: str = "your-transaction-id-here"
co_agent_data: Dict[str, Any] = {
"agent_id": "agent-uuid-here",
"role": "BUYERS_AGENT"
}
client.transaction_builder.add_co_agent(transaction_id, co_agent_data)
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
transaction_id: str = "your-transaction-id-here"
co_agent_data: Dict[str, Any] = {
"agent_id": "seller-agent-uuid",
"role": "SELLERS_AGENT"
}
client.transaction_builder.add_co_agent(transaction_id, co_agent_data)
Owner Agents¶
Update owner agent information for the transaction.
✅ WORKING SOLUTION ✅ This method now works correctly when called in the proper sequence.
🔄 REQUIRED SEQUENCE: 1. Create transaction (create_transaction_builder) 2. Add location info with ALL required fields (update_location_info) 3. Add price/date info with commission objects (update_price_and_date_info) 4. Add buyers/sellers (add_buyer/add_seller) 5. THEN add owner agent (this method) - ✅ WORKS!
📋 COMPLETE DATA REQUIREMENTS:
Location Info Must Include
- street, city, state, zip (basic)
- county: Required additional field
- yearBuilt: Required additional field
- mlsNumber: Required additional field
Price/Date Info Must Include: - dealType, propertyType, salePrice, representationType (basic) - listingCommission: Required commission object - saleCommission: Required commission object
Owner Agent Data Structure
owner_agent_info = { "ownerAgent": { "agentId": str, # User ID (same as agent ID in ReZEN) "role": str # "BUYERS_AGENT" or "SELLERS_AGENT" }, "officeId": str, # From user.offices[0].id "teamId": str # UUID of the team }
🎯 GETTING THE RIGHT IDS: - agentId: Use current user's ID (user["id"] from get_current_user()) - officeId: Use user["offices"][0]["id"] from get_current_user() - teamId: Use team ID from get_user_teams_and_offices()
Role Matching
The role MUST match the representationType from price/date info: - representationType: "BUYER" → role: "BUYERS_AGENT" - representationType: "SELLER" → role: "SELLERS_AGENT"
💡 TIP: Use convenience methods instead of manual setup: - set_current_user_as_owner_agent() for default team - set_current_user_as_owner_agent_with_team() for specific team
Example - Complete Working Sequence
# 1. Create transaction
builder_id = client.transaction_builder.create_transaction_builder()
# 2. Add location with ALL required fields (REQUIRED FIRST)
client.transaction_builder.update_location_info(builder_id, {
"street": "123 Main St",
"city": "Salt Lake City",
"state": "UTAH",
"zip": "84101",
"county": "Salt Lake", # REQUIRED
"yearBuilt": 2020, # REQUIRED
"mlsNumber": "MLS-123456" # REQUIRED
})
# 3. Add price/date with commission objects (REQUIRED SECOND)
client.transaction_builder.update_price_and_date_info(builder_id, {
"dealType": "COMPENSATING",
"propertyType": "RESIDENTIAL",
"salePrice": {"amount": 500000, "currency": "USD"},
"representationType": "BUYER",
"listingCommission": { # REQUIRED
"commissionPercent": 3.0,
"percentEnabled": True,
"negativeOrEmpty": False
},
"saleCommission": { # REQUIRED
"commissionPercent": 3.0,
"percentEnabled": True,
"negativeOrEmpty": False
}
})
# 4. Add buyer (REQUIRED THIRD)
client.transaction_builder.add_buyer(builder_id, {
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"phoneNumber": "(555) 123-4567"
})
# 5. Get user and office info
user = client.users.get_current_user()
# 6. NOW add owner agent (WORKS!)
owner_info = {
"ownerAgent": {
"agentId": user["id"], # User ID = Agent ID
"role": "BUYERS_AGENT" # Must match representationType
},
"officeId": user["offices"][0]["id"], # From user's offices
"teamId": "your-team-uuid" # Your team ID
}
result = client.transaction_builder.update_owner_agent_info(builder_id, owner_info)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_builder_id | str | UUID of the transaction builder | required |
owner_agent_info | Dict[str, Any] | Dictionary containing owner agent details | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Updated transaction builder data |
Raises:
Type | Description |
---|---|
ValidationError | If owner agent info is invalid or sequence not followed |
NotFoundError | If transaction builder not found |
Multiple Teams Support¶
✅ New Feature: Multiple Teams Support
Many ReZEN users belong to multiple teams. These convenience methods help handle team selection automatically:
Get current user's teams and offices with smart default selection.
✅ WORKING METHOD - Handles multiple team scenarios automatically.
This method helps handle users who belong to multiple teams by: 1. Fetching all teams the user belongs to 2. Determining a smart default team (prefers LEADER role over ADMIN) 3. Extracting office information from user profile 4. Providing clear guidance on team selection
🎯 SMART DEFAULT LOGIC: - If user has LEADER role in any team → that team becomes default - If user only has ADMIN roles → first ADMIN team becomes default - If user has only one team → that team becomes default
💡 USE CASES: - Check if user needs team selection before transaction creation - Get default team for automatic owner agent setup - Display available teams for user selection
Parameters:
Name | Type | Description | Default |
---|---|---|---|
users_client | Optional[Any] | Optional users client instance (uses parent client if None) | None |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Dictionary containing: |
Dict[str, Any] |
|
Dict[str, Any] |
|
Dict[str, Any] |
|
Dict[str, Any] |
|
Dict[str, Any] |
|
Dict[str, Any] |
|
Dict[str, Any] |
|
Dict[str, Any] |
|
Example
info = client.transaction_builder.get_user_teams_and_offices()
print(f"Agent ID: {info['agent_id']}")
print(f"Office ID: {info['office_id']}")
if info["has_multiple_teams"]:
print("\nAvailable teams:")
for team in info["teams"]:
role = team["role"]
name = team["name"]
is_default = team["id"] == info["default_team"]["id"]
marker = " (DEFAULT)" if is_default else ""
print(f" - {name} (Role: {role}){marker}")
# Use default team or let user choose
selected_team = info["default_team"]
print(f"\nUsing default team: {selected_team['name']}")
else:
print(f"Single team: {info['default_team']['name']}")
# Ready-to-use IDs for transaction setup
team_id = info["default_team"]["id"]
office_id = info["office_id"]
agent_id = info["agent_id"]
Team Data Structure
Each team in the teams list contains: - id: Team UUID - name: Team name - role: User's role in the team ("LEADER", "ADMIN", etc.)
Raises:
Type | Description |
---|---|
APIError | If user data cannot be retrieved |
ValueError | If user has no offices (required for transactions) |
Smart Default Logic: - Prefers teams where you have LEADER role - Falls back to ADMIN teams - Uses first available team as last resort
Set the current authenticated user as the owner agent with default team.
✅ WORKING CONVENIENCE METHOD
⚠️ MULTIPLE TEAMS WARNING ⚠️ If you belong to multiple teams, this method will use your DEFAULT team (prefers LEADER role). To specify a particular team, use set_current_user_as_owner_agent_with_team()
instead.
This is a convenience method that automatically: 1. Gets current user information (user ID and office ID) 2. Determines default team using smart logic 3. Sets up owner agent with all required fields
🎯 SMART DEFAULT TEAM LOGIC: - Prefers teams where you have LEADER role - Falls back to teams where you have ADMIN role - Uses first available team as last resort
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_builder_id | str | UUID of the transaction builder | required |
role | str | Agent role ("BUYERS_AGENT" or "SELLERS_AGENT") | required |
users_client | Optional[Any] | Optional UsersClient instance. If None, will create one. | None |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Updated transaction builder data |
Raises:
Type | Description |
---|---|
ValidationError | If owner agent info is invalid or user has no teams |
NotFoundError | If transaction builder not found |
AuthenticationError | If not authenticated |
ValueError | If user has no offices |
Example
# Simple case - uses default team automatically
result = client.transaction_builder.set_current_user_as_owner_agent(
builder_id,
"BUYERS_AGENT"
)
# For multiple teams - check first, then choose approach
teams_info = client.transaction_builder.get_user_teams_and_offices()
if teams_info["has_multiple_teams"]:
print(f"You have {len(teams_info['teams'])} teams.")
print(f"Will use default: {teams_info['default_team']['name']}")
# Option 1: Use this method with default team
result = client.transaction_builder.set_current_user_as_owner_agent(
builder_id, "BUYERS_AGENT"
)
# Option 2: Specify team explicitly
# result = client.transaction_builder.set_current_user_as_owner_agent_with_team(
# builder_id, "BUYERS_AGENT", teams_info["teams"][1]["id"]
# )
else:
# Single team - use this convenience method
result = client.transaction_builder.set_current_user_as_owner_agent(
builder_id, "BUYERS_AGENT"
)
Best for: Users with single team or who want automatic team selection.
Set current user as owner agent with explicit team selection.
✅ WORKING CONVENIENCE METHOD
This method allows users to specify which team to use when they belong to multiple teams. This gives full control over team selection and is recommended when you need to be explicit about which team to use.
🎯 PERFECT FOR: - Users who belong to multiple teams - When you need specific team for business reasons - Programmatic team selection based on criteria
This method automatically: 1. Gets current user information (user ID and office ID) 2. Validates the user belongs to the specified team 3. Sets up owner agent with all required fields
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_builder_id | str | UUID of the transaction builder | required |
role | str | Agent role ("BUYERS_AGENT" or "SELLERS_AGENT") | required |
team_id | str | Specific team ID to use for the transaction | required |
users_client | Optional[Any] | Optional UsersClient instance. If None, will create one. | None |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Updated transaction builder data |
Raises:
Type | Description |
---|---|
ValidationError | If user is not a member of the specified team |
ValidationError | If team_id is invalid |
NotFoundError | If transaction builder not found |
AuthenticationError | If not authenticated |
ValueError | If user has no offices |
Example
# Option 1: Get available teams and choose
teams_info = client.transaction_builder.get_user_teams_and_offices()
if teams_info["has_multiple_teams"]:
print("Available teams:")
for team in teams_info["teams"]:
print(f" {team['name']} (ID: {team['id']}, Role: {team['role']})")
# Choose a specific team (e.g., select LEADER team)
leader_teams = [t for t in teams_info["teams"] if t["role"] == "LEADER"]
selected_team_id = leader_teams[0]["id"] if leader_teams else teams_info["teams"][0]["id"]
else:
selected_team_id = teams_info["default_team"]["id"]
# Set owner agent with specific team
result = client.transaction_builder.set_current_user_as_owner_agent_with_team(
builder_id,
role="BUYERS_AGENT",
team_id=selected_team_id
)
# Option 2: Direct usage if you know the team ID
result = client.transaction_builder.set_current_user_as_owner_agent_with_team(
builder_id,
role="SELLERS_AGENT",
team_id="12345678-1234-1234-1234-123456789012"
)
Best for: Users with multiple teams who need explicit control.
Prerequisites Required
CRITICAL: The owner agent endpoint requires the transaction to be properly set up BEFORE adding agents:
- Location info must be added first (
update_location_info
) - Price and date info must be added second (
update_price_and_date_info
) - Buyers/Sellers must be added third (
add_buyer
/add_seller
) - THEN owner agent can be added successfully
Owner Data Structure:
{
"ownerAgent": {
"agentId": "agent_uuid",
"role": "BUYERS_AGENT" # or "SELLERS_AGENT"
},
"officeId": "office_uuid",
"teamId": "team_uuid"
}
Multiple Teams Support
New in ReZEN: If you belong to multiple teams, use the enhanced methods:
get_user_teams_and_offices()
- Discover available teamsset_current_user_as_owner_agent_with_team()
- Specify exact team
See Multiple Teams Guide for details.
Complete Working Example
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
# Step 1: Create transaction
builder_id = client.transaction_builder.create_transaction_builder()
# Step 2: Add location (REQUIRED FIRST)
location_data: Dict[str, Any] = {
"street": "123 Main St",
"city": "Salt Lake City",
"state": "UTAH",
"zip": "84101"
}
client.transaction_builder.update_location_info(builder_id, location_data)
# Step 3: Add price/date info (REQUIRED SECOND)
price_data: Dict[str, Any] = {
"dealType": "COMPENSATING",
"propertyType": "RESIDENTIAL",
"salePrice": {"amount": 500000, "currency": "USD"},
"representationType": "BUYER" # Must match agent role
}
client.transaction_builder.update_price_and_date_info(builder_id, price_data)
# Step 4: Add clients (REQUIRED THIRD)
client.transaction_builder.add_buyer(builder_id, {
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"phoneNumber": "(801) 555-1234"
})
# Step 5: NOW add owner agent (will work!)
owner_data: Dict[str, Any] = {
"ownerAgent": {
"agentId": "your_agent_id",
"role": "BUYERS_AGENT" # Must match representationType
},
"officeId": "your_office_id",
"teamId": "your_team_id"
}
client.transaction_builder.update_owner_agent_info(builder_id, owner_data)
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
# Set up transaction (same steps 1-4 as above)
builder_id = client.transaction_builder.create_transaction_builder()
# ... add location, price, and clients ...
# Use convenience method for current user
client.transaction_builder.set_current_user_as_owner_agent(
builder_id,
role="BUYERS_AGENT"
)
Role Matching
The role
in ownerAgent
must match the representationType
in the price/date info:
representationType: "BUYER"
→role: "BUYERS_AGENT"
representationType: "SELLER"
→role: "SELLERS_AGENT"
Other Participants¶
Add a new participant to the transaction builder.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
participant_info | Dict[str, Any] | Participant information data | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder response data |
Participant Types:
Type | Description |
---|---|
INSPECTOR | Property inspector |
APPRAISER | Property appraiser |
LENDER | Mortgage lender |
TITLE_COMPANY | Title company representative |
ATTORNEY | Legal counsel |
CONTRACTOR | Contractor or repair specialist |
Service Provider Examples
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
transaction_id: str = "your-transaction-id-here"
inspector_data: Dict[str, Any] = {
"type": "INSPECTOR",
"firstName": "Mike", # Use camelCase
"lastName": "Inspector", # Use camelCase
"company": "Quality Inspections Inc",
"phoneNumber": "+1-555-INSPECT", # Use camelCase
"email": "mike@qualityinspections.com"
}
client.transaction_builder.add_participant(transaction_id, inspector_data)
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
transaction_id: str = "your-transaction-id-here"
lender_data: Dict[str, Any] = {
"type": "LENDER",
"firstName": "Sarah", # Use camelCase
"lastName": "Banker", # Use camelCase
"company": "First National Bank",
"phoneNumber": "+1-555-LOANS", # Use camelCase
"email": "sarah.banker@firstnational.com"
}
client.transaction_builder.add_participant(transaction_id, lender_data)
Property & Location Details¶
Location Information¶
Update location information.
⚠️ CRITICAL REQUIREMENT ⚠️ Basic address fields alone (street, city, state, zip) will FAIL. The API requires additional property details for successful location updates.
REQUIRED ADDITIONAL FIELDS (beyond basic address): - county (str): County name (e.g., "Salt Lake") - yearBuilt (int): Year the property was built (e.g., 2020) - mlsNumber (str): MLS listing number (e.g., "MLS123456")
Field Name Requirements
- Use 'street' not 'address'
- Use 'zip' not 'zipCode' or 'zip_code'
- State must be ALL CAPS (e.g., 'UTAH', 'CALIFORNIA')
- Use camelCase for: yearBuilt, mlsNumber, escrowNumber
Required Fields for Success
- street (str): Property street address
- city (str): City name
- state (str): State name in ALL CAPS
- zip (str): ZIP code
- county (str): County name - REQUIRED
- yearBuilt (int): Year built - REQUIRED
- mlsNumber (str): MLS number - REQUIRED
Optional Fields
- street2 (str): Secondary address line
- unit (str): Unit number
- escrowNumber (str): Escrow number
Working Example
# ✅ This WORKS (includes required additional fields)
location_info = {
"street": "123 Main Street",
"city": "Salt Lake City",
"state": "UTAH",
"zip": "84101",
"county": "Salt Lake", # REQUIRED
"yearBuilt": 2020, # REQUIRED
"mlsNumber": "MLS123456", # REQUIRED
"escrowNumber": "ESC-2024-001" # Optional
}
# ❌ This FAILS (missing required additional fields)
location_info = {
"street": "123 Main Street",
"city": "Salt Lake City",
"state": "UTAH",
"zip": "84101"
# Missing county, yearBuilt, mlsNumber - API returns "Bad request: Invalid request"
}
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
location_info | Dict[str, Any] | Location information data with ALL required fields | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder response data |
Raises:
Type | Description |
---|---|
InvalidFieldNameError | If using wrong field names (address, zipCode, etc.) |
InvalidFieldValueError | If state is not in ALL CAPS |
ValidationError | If missing required additional fields |
Backward Compatibility
You can also use put_location_to_draft()
which is an alias for update_location_info()
.
Property Location Examples
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
transaction_id: str = "your-transaction-id-here"
location_data: Dict[str, Any] = {
"street": "123 Maple Street", # Use 'street' not 'address'
"street2": "",
"city": "Springfield",
"state": "UTAH", # Must be UTAH (all caps)
"zip": "84101", # Use 'zip' not 'zipCode'
"county": "Salt Lake",
"unit": "Unit 2A", # For condos/apartments
"subdivision": "Maple Grove",
"yearBuilt": 2020, # Use camelCase
"mlsNumber": "MLS123", # Use camelCase
"escrowNumber": ""
}
# Using new method name
client.transaction_builder.update_location_info(transaction_id, location_data)
# Or using backward compatibility alias
client.transaction_builder.put_location_to_draft(transaction_id, location_data)
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
transaction_id: str = "your-transaction-id-here"
location_data: Dict[str, Any] = {
"street": "456 Business Blvd", # Use 'street' not 'address'
"street2": "",
"city": "Commerce City",
"state": "UTAH", # Must be UTAH (all caps)
"zip": "84111", # Use 'zip' not 'zipCode'
"county": "Salt Lake",
"yearBuilt": 2018,
"mlsNumber": "COM456",
"escrowNumber": "",
"building_name": "Commerce Center",
"floor": "15th Floor"
}
client.transaction_builder.update_location_info(transaction_id, location_data)
Pricing & Dates¶
Update price and date information.
⚠️ CRITICAL REQUIREMENT ⚠️ Basic price/date fields alone will FAIL with "Bad request: Invalid request". The API requires BOTH commission objects for successful price/date updates.
REQUIRED COMMISSION FIELDS
Both listingCommission AND saleCommission objects are REQUIRED together. You cannot provide just one - the API needs both.
Field Structure Requirements
- salePrice MUST be an object with 'amount' and 'currency', NOT a simple number
- All dates use camelCase format: acceptanceDate, closingDate, etc.
- representationType determines valid agent roles (BUYER → BUYERS_AGENT, SELLER → SELLERS_AGENT)
Required Fields for Success
- dealType (str): "COMPENSATING" or "NON_COMPENSATING"
- propertyType (str): "RESIDENTIAL", "COMMERCIAL", etc.
- salePrice (dict): {"amount": 500000, "currency": "USD"}
- representationType (str): "BUYER" or "SELLER" - affects owner agent role
- listingCommission (dict): Commission object - REQUIRED
- saleCommission (dict): Commission object - REQUIRED
Optional Fields
- acceptanceDate (str): Date in "YYYY-MM-DD" format
- closingDate (str): Date in "YYYY-MM-DD" format
- earnestMoney (float): Earnest money amount
- downPayment (float): Down payment amount
- loanAmount (float): Loan amount
Working Example
# ✅ This WORKS (includes both required commission objects)
price_date_info = {
"dealType": "COMPENSATING",
"propertyType": "RESIDENTIAL",
"salePrice": {
"amount": 565000,
"currency": "USD"
},
"representationType": "BUYER",
"listingCommission": { # REQUIRED
"commissionPercent": 3.0,
"percentEnabled": True,
"negativeOrEmpty": False
},
"saleCommission": { # REQUIRED
"commissionPercent": 3.0,
"percentEnabled": True,
"negativeOrEmpty": False
},
"acceptanceDate": "2024-01-15",
"closingDate": "2024-02-28"
}
# ❌ This FAILS (missing commission objects)
price_date_info = {
"dealType": "COMPENSATING",
"propertyType": "RESIDENTIAL",
"salePrice": {"amount": 500000, "currency": "USD"},
"representationType": "BUYER"
# Missing both commission objects - API returns "Bad request: Invalid request"
}
# ❌ This ALSO FAILS (only one commission object)
price_date_info = {
"dealType": "COMPENSATING",
"propertyType": "RESIDENTIAL",
"salePrice": {"amount": 500000, "currency": "USD"},
"representationType": "BUYER",
"listingCommission": { # Only one commission
"commissionPercent": 3.0,
"percentEnabled": True,
"negativeOrEmpty": False
}
# Missing saleCommission - API still returns "Bad request: Invalid request"
}
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
price_date_info | Dict[str, Any] | Price and date information data with BOTH commission objects | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder response data |
Raises:
Type | Description |
---|---|
ValidationError | If missing required fields or commission objects |
InvalidFieldValueError | If salePrice format is incorrect or representationType invalid |
Backward Compatibility
You can also use put_price_and_date_to_draft()
which is an alias for update_price_and_date_info()
.
Key Date Fields:
Field | Format | Description |
---|---|---|
contractDate | YYYY-MM-DD | Date contract was signed (camelCase) |
closingDate | YYYY-MM-DD | Expected closing date (camelCase) |
inspectionDate | YYYY-MM-DD | Property inspection date (camelCase) |
appraisalDate | YYYY-MM-DD | Appraisal completion date (camelCase) |
acceptanceDate | YYYY-MM-DD | Offer acceptance date (camelCase) |
Pricing Information
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
transaction_id: str = "your-transaction-id-here"
price_date_data: Dict[str, Any] = {
"salePrice": { # Use camelCase and object structure
"amount": 750000,
"currency": "USD"
},
"earnestMoney": 15000, # Use camelCase
"downPayment": 150000, # Use camelCase
"loanAmount": 600000, # Use camelCase
"contractDate": "2024-02-01", # Use camelCase
"closingDate": "2024-03-15", # Use camelCase
"inspectionDate": "2024-02-10", # Use camelCase
"appraisalDate": "2024-02-20" # Use camelCase
}
client.transaction_builder.update_price_and_date_info(
transaction_id,
price_date_data
)
Title Information¶
Update title details for a transaction builder.
Important: Use camelCase for field names: - firstName (not first_name) - lastName (not last_name) - phoneNumber (not phone_number)
Example
title_info = { "company": "Premier Title Company", "firstName": "Sarah", "lastName": "Johnson", "email": "sarah@premiertitle.com", "phoneNumber": "(555) 555-5555" }
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
title_info | Dict[str, Any] | Title information data with camelCase fields | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder response data |
Update Real Title¶
Update real title (alias for update_title_info).
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
title_info | Dict[str, Any] | Title information data | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder response data |
Alias Method
This is an alias for update_title_info()
provided for backward compatibility.
Title Company Details
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
transaction_id: str = "your-transaction-id-here"
title_data: Dict[str, Any] = {
"company": "Premier Title Co", # Use 'company' not 'title_company'
"firstName": "Sarah", # Use camelCase
"lastName": "Johnson", # Use camelCase
"phoneNumber": "+1-555-789-0123", # Use camelCase
"email": "sarah@premiertitle.com",
"address": "789 Title Lane, Title City, TC 54321",
"policyNumber": "PT-2024-001234" # Use camelCase
}
# Using either method works the same
client.transaction_builder.update_title_info(transaction_id, title_data)
# or
client.transaction_builder.update_real_title(transaction_id, title_data)
Personal Deal Information¶
Update personal deal information.
Sets whether this transaction is a personal deal (agent buying/selling own property).
Required Fields
- isPersonalDeal (bool): Whether this is a personal deal
Example
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
deal_info | Dict[str, Any] | Personal deal information data | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder response data |
Update Personal Deal¶
Update personal deal (alias for update_personal_deal_info).
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
deal_info | Dict[str, Any] | Personal deal information data | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder response data |
Alias Method
This is an alias for update_personal_deal_info()
provided for backward compatibility.
Financial Management¶
Commission Splits¶
Update commission splits information.
IMPORTANT: Pass a LIST of commission split objects, even for a single split.
Commission Split Structure
Each split in the list should contain: - agentId (str): UUID of the agent receiving the split - receivesInvoice (bool): Whether this agent receives an invoice - splitPercent (float): Percentage of commission (e.g., 50.0 for 50%) - opCityReferral (bool): Whether this is an OpCity referral (optional) - optedInForEcp (bool): Whether opted in for ECP (optional)
Example
commission_splits = [
{
"agentId": "agent-uuid-1",
"receivesInvoice": True,
"splitPercent": 50.0,
"opCityReferral": False,
"optedInForEcp": False
},
{
"agentId": "agent-uuid-2",
"receivesInvoice": False,
"splitPercent": 50.0,
"opCityReferral": False,
"optedInForEcp": False
}
]
client.update_commission_splits(transaction_id, commission_splits)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
commission_splits | List[Dict[str, Any]] | List of commission split data | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder response data |
Commission Split Examples
from typing import Dict, List, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
transaction_id: str = "your-transaction-id-here"
commission_data: List[Dict[str, Any]] = [
{
"agentId": "buyer-agent-uuid", # Use camelCase
"splitPercentage": 50.0, # Use camelCase
"commissionAmount": 15000 # Use camelCase
},
{
"agentId": "seller-agent-uuid", # Use camelCase
"splitPercentage": 50.0, # Use camelCase
"commissionAmount": 15000 # Use camelCase
}
]
client.transaction_builder.update_commission_splits(
transaction_id,
commission_data
)
from typing import Dict, List, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
transaction_id: str = "your-transaction-id-here"
commission_data: List[Dict[str, Any]] = [
{
"agentId": "listing-agent-uuid", # Use camelCase
"splitPercentage": 60.0, # Use camelCase
"commissionAmount": 18000 # Use camelCase
},
{
"agentId": "buyer-agent-uuid", # Use camelCase
"splitPercentage": 40.0, # Use camelCase
"commissionAmount": 12000 # Use camelCase
}
]
client.transaction_builder.update_commission_splits(
transaction_id,
commission_data
)
Commission Payers¶
Add commission payer information.
IMPORTANT: This endpoint requires multipart/form-data format. The method automatically handles the conversion for you.
Required Fields
- role (str): Commission payer role (e.g., "REAL", "NA", "LISTING_AGENT", "BUYERS_AGENT")
Optional Fields
- receivesInvoice (bool): Whether the payer receives invoice
- opCityReferral (bool): Whether this is an OpCity referral
- optedInForEcp (bool): Whether opted in for ECP
Special Note
Based on testing, the "role" field accepts specific values that may differ from what's shown in API documentation. Common working values include: - "REAL" - For standard commission payers - "NA" - Not applicable/none - Role values matching agent roles (LISTING_AGENT, BUYERS_AGENT, etc.)
Example
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
commission_info | Dict[str, Any] | Commission payer information data | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder response data |
Update Commission Payer¶
Update commission payer information (alias for add_commission_payer).
Parameters:
Name | Type | Description | Default |
---|---|---|---|
transaction_id | str | Transaction builder ID | required |
commission_info | Dict[str, Any] | Commission payer information data | required |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Transaction builder response data |
Alias Method
This is an alias for add_commission_payer()
provided for backward compatibility.
Payer Types:
Type | Description |
---|---|
SELLER | Seller pays commission |
BUYER | Buyer pays commission |
BOTH | Split between buyer and seller |
Commission Payer Configuration
from typing import Dict, Any
from rezen import RezenClient
client: RezenClient = RezenClient()
transaction_id: str = "your-transaction-id-here"
payer_data: Dict[str, Any] = {
"payerType": "SELLER", # Use camelCase
"commissionRate": 6.0, # 6% commission, use camelCase
"flatFee": False # Percentage-based, not flat fee, use camelCase
}
# Using either method works the same
client.transaction_builder.add_commission_payer(transaction_id, payer_data)
# or
client.transaction_builder.update_commission_payer(transaction_id, payer_data)
Field Name Requirements¶
Critical Field Name Requirements
The ReZEN API has specific field name requirements that must be followed exactly:
Location Fields: - ✅ Use street
NOT address
- ✅ Use zip
NOT zipCode
- ✅ State must be UTAH
(all caps) - ✅ Use camelCase: yearBuilt
, mlsNumber
, escrowNumber
Contact Fields: - ✅ Use firstName
NOT first_name
- ✅ Use lastName
NOT last_name
- ✅ Use phoneNumber
NOT phone
Price Fields: - ✅ salePrice
must be an object with amount
and currency
- ✅ Use camelCase: earnestMoney
, downPayment
, loanAmount
Date Fields: - ✅ Use camelCase: contractDate
, closingDate
, acceptanceDate
- ✅ Format: YYYY-MM-DD
Commission Fields: - ✅ Use camelCase: agentId
, splitPercentage
, commissionAmount
Backward Compatibility¶
Legacy Method Names
The library provides backward compatibility aliases for users migrating from older versions:
Old Method Name | New Method Name |
---|---|
put_buyer_to_draft() | add_buyer() |
put_seller_to_draft() | add_seller() |
put_location_to_draft() | update_location_info() |
put_price_and_date_to_draft() | update_price_and_date_info() |
update_commission_payer() | add_commission_payer() |
update_personal_deal() | update_personal_deal_info() |
update_real_title() | update_title_info() |
Using Backward Compatibility
from rezen import RezenClient
client = RezenClient()
transaction_id = "your-transaction-id"
# These method pairs do the same thing:
# Add buyer
client.transaction_builder.add_buyer(transaction_id, buyer_data)
client.transaction_builder.put_buyer_to_draft(transaction_id, buyer_data)
# Add seller
client.transaction_builder.add_seller(transaction_id, seller_data)
client.transaction_builder.put_seller_to_draft(transaction_id, seller_data)
# Update location
client.transaction_builder.update_location_info(transaction_id, location_data)
client.transaction_builder.put_location_to_draft(transaction_id, location_data)
# Update price and date
client.transaction_builder.update_price_and_date_info(transaction_id, price_data)
client.transaction_builder.put_price_and_date_to_draft(transaction_id, price_data)
Query & Search Operations¶
List Transaction Builders¶
Get a paginated list of transaction builders.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
limit | int | Maximum number of results to return | required |
from_offset | int | Starting offset for pagination | required |
yenta_id | str | User ID | required |
builder_type | str | Type of builder ('TRANSACTION' or 'LISTING') | 'TRANSACTION' |
Returns:
Type | Description |
---|---|
Dict[str, Any] | Paginated list of transaction builders |
Advanced Filtering
Error Handling¶
Enhanced Error Messages¶
The Transaction Builder now includes enhanced error handling that catches common mistakes before they reach the API.
New Error Types
InvalidFieldNameError
: Catches incorrect field names (e.g.,address
instead ofstreet
)InvalidFieldValueError
: Validates field formats (e.g., state must be uppercase)TransactionSequenceError
: Identifies when operations are called in wrong orderValidationError
: General validation failures with detailed messages
Common Field Name Errors¶
Field Name Validation
from rezen.exceptions import InvalidFieldNameError
try:
# Using wrong field name
location_data = {
"address": "123 Main St", # ❌ Wrong! Should be 'street'
"city": "Salt Lake City",
"state": "UTAH",
"zipCode": "84101" # ❌ Wrong! Should be 'zip'
}
client.transaction_builder.update_location_info(transaction_id, location_data)
except InvalidFieldNameError as e:
print(f"Field name error: {e}")
print(f"Use '{e.correct_name}' instead of '{e.field_name}'")
Field Value Validation¶
Field Value Validation
from rezen.exceptions import InvalidFieldValueError
try:
# Wrong state format
location_data = {
"street": "123 Main St",
"city": "Salt Lake City",
"state": "utah", # ❌ Wrong! Must be uppercase
"zip": "84101"
}
client.transaction_builder.update_location_info(transaction_id, location_data)
except InvalidFieldValueError as e:
print(f"Invalid value for '{e.field_name}': {e.value}")
print(f"Expected: {e.expected_format}")
Transaction Sequence Errors¶
Sequence Requirements
The owner agent endpoint requires specific setup steps in order:
from rezen.exceptions import TransactionSequenceError
try:
# Trying to add owner agent without proper setup
client.transaction_builder.update_owner_agent_info(builder_id, owner_data)
except TransactionSequenceError as e:
print(f"Sequence error: {e}")
# Error message includes required steps:
# 1. Create transaction (create_transaction_builder)
# 2. Add location info (update_location_info) - REQUIRED FIRST
# 3. Add price/date info (update_price_and_date_info) - REQUIRED SECOND
# 4. Add buyers/sellers (add_buyer/add_seller) - REQUIRED THIRD
# 5. THEN add owner agent (update_owner_agent_info)
Price Structure Validation¶
Price Field Validation
from rezen.exceptions import InvalidFieldValueError, ValidationError
try:
price_data = {
"dealType": "COMPENSATING",
"propertyType": "RESIDENTIAL",
"salePrice": 500000, # ❌ Wrong! Must be object
"representationType": "BUYERS_AGENT" # ❌ Wrong! Should be 'BUYER'
}
client.transaction_builder.update_price_and_date_info(transaction_id, price_data)
except InvalidFieldValueError as e:
# Catches: "Invalid value for 'salePrice': 500000.
# Expected: Object with 'amount' and 'currency' fields"
print(f"Error: {e}")
except ValidationError as e:
# Catches missing required fields
print(f"Validation error: {e}")
Best Practices¶
Error Handling Best Practices
- Catch Specific Exceptions: Use specific exception types for better error handling
- Check Field Names: The enhanced validation catches common camelCase vs snake_case errors
- Validate Before Submission: Required fields are now validated before API calls
- Follow Sequence Requirements: Especially important for owner agent endpoints
- Use Error Details: Exception objects contain helpful properties like
field_name
andcorrect_name
Complete Workflow Example¶
End-to-End Transaction Creation
from rezen import RezenClient
from rezen.exceptions import RezenError
import logging
def create_complete_transaction():
"""Create a complete transaction with all participants and details."""
try:
client = RezenClient()
# Step 1: Create transaction builder
print("Creating transaction builder...")
response = client.transaction_builder.create_transaction_builder()
transaction_id = response['id']
print(f"✅ Created transaction: {transaction_id}")
# Step 2: Add buyer
print("Adding buyer...")
buyer_data = {
"firstName": "John", # Use camelCase
"lastName": "Doe", # Use camelCase
"email": "john.doe@email.com",
"phoneNumber": "+1-555-123-4567" # Use camelCase
}
client.transaction_builder.add_buyer(transaction_id, buyer_data)
print("✅ Added buyer")
# Step 3: Add seller
print("Adding seller...")
seller_data = {
"firstName": "Jane", # Use camelCase
"lastName": "Smith", # Use camelCase
"email": "jane.smith@email.com",
"phoneNumber": "+1-555-987-6543" # Use camelCase
}
client.transaction_builder.add_seller(transaction_id, seller_data)
print("✅ Added seller")
# Step 4: Add property location
print("Setting property location...")
location_data = {
"street": "123 Dream House Lane", # Use 'street' not 'address'
"street2": "",
"city": "Salt Lake City",
"state": "UTAH", # Must be UTAH (all caps)
"zip": "84101", # Use 'zip' not 'zipCode'
"county": "Salt Lake",
"unit": "",
"yearBuilt": 2020, # Use camelCase
"mlsNumber": "MLS123456", # Use camelCase
"escrowNumber": ""
}
client.transaction_builder.update_location_info(transaction_id, location_data)
print("✅ Set property location")
# Step 5: Set pricing and dates
print("Setting pricing and dates...")
price_data = {
"salePrice": { # Use camelCase and object structure
"amount": 850000,
"currency": "USD"
},
"earnestMoney": 17000, # Use camelCase
"acceptanceDate": "2024-02-01", # Use camelCase
"closingDate": "2024-03-15" # Use camelCase
}
client.transaction_builder.update_price_and_date_info(transaction_id, price_data)
print("✅ Set pricing and dates")
# Step 6: Add service providers
print("Adding service providers...")
inspector_data = {
"type": "INSPECTOR",
"firstName": "Mike", # Use camelCase
"lastName": "Inspector", # Use camelCase
"company": "Quality Inspections Inc",
"phoneNumber": "+1-555-INSPECT", # Use camelCase
"email": "mike@qualityinspections.com"
}
client.transaction_builder.add_participant(transaction_id, inspector_data)
print("✅ Added inspector")
# Step 7: Submit transaction
print("Submitting transaction...")
submit_response = client.transaction_builder.submit_transaction(transaction_id)
print("✅ Transaction submitted successfully!")
return {
"success": True,
"transaction_id": transaction_id,
"submit_response": submit_response
}
except RezenError as e:
logging.error(f"ReZEN API error: {e}")
return {
"success": False,
"error": str(e),
"transaction_id": transaction_id if 'transaction_id' in locals() else None
}
except Exception as e:
logging.error(f"Unexpected error: {e}")
return {
"success": False,
"error": str(e)
}
# Run the example
result = create_complete_transaction()
if result["success"]:
print(f"🎉 Transaction {result['transaction_id']} created successfully!")
else:
print(f"❌ Failed to create transaction: {result['error']}")
Next Steps¶
-
:material-handshake: Transactions API
Work with live transactions and manage ongoing deals
-
:material-account-group: Teams API
Search and manage team information
-
:material-account-tie: Agents API
Find and manage agent information
-
:material-file-document: Examples
See more practical usage examples