Realogy

Ruby implementation of the Realogy DataSync API to synchronize local data store with the data maintained by Realogy.

The Realogy gem:

  • Retrieves the JSON for the supported entities Agents, Companies, Listings, Offices, and Teams.
  • Uses the JSON column type, so make sure your database is a recent version that supports it.
  • Does not perform any data mapping, as it strives to be agnostic to existing data structures. Add after_save hooks to capture saved JSON, transform it and save it where you want it saved.

Installation

Add this line to your application's Gemfile:

gem 'realogy'

And then execute:

bundle

Or install it yourself as:

gem install realogy

Usage

Set up for usage by creating Realogy's migration and running it.

rails g realogy:install
rails db:migrate

Realogy is expecting these encrypted credentials to be present to be able to function:

realogy:
  client_id: 
  client_secret: 
  token_url: 
  scope: 
  subscription_key: 
  api_base_url: 

Available Rake Tasks

Syncing Active Entities

There are a number of rake tasks for syncing active entities. By default, all countries are synced. A country code can optionally be passed in to sync only that country.

rails realogy:sync_active_agents         # Sync Active Agents Everywhere
rails realogy:sync_active_agents[SE]     # Sync Active Agents in Sweden

rails realogy:sync_active_companies      # Sync Active Companies Everywhere
rails realogy:sync_active_companies[SE]  # Sync Active Companies in Sweden

rails realogy:sync_active_listings       # Sync Active Listings Everywhere
rails realogy:sync_active_listings[SE]   # Sync Active Listings in Sweden

rails realogy:sync_active_offices        # Sync Active Offices Everywhere
rails realogy:sync_active_offices[SE]    # Sync Active Offices in Sweden

rails realogy:sync_active_teams          # Sync Active Teams Everywhere
rails realogy:sync_active_teams[SE]      # Sync Active Teams in Sweden

Catch-all that runs all other syncing tasks:

rails realogy:sync_active_entities       # Sync all active entities

Syncing Entities Delta

There are a number of rake tasks for syncing entities within a delta span of time. Tasks default to last 15 minutes if not otherwise specified. These tasks will both update new/updated entities, as well as delete expired ones.

rails realogy:sync_agents_delta         # Sync agents delta for last 15 minutes 
rails realogy:sync_agents_delta[10]     # Sync agents delta for last 10 minutes

rails realogy:sync_companies_delta      # Sync companies delta for last 15 minutes
rails realogy:sync_companies_delta[10]  # Sync companies delta for last 10 minutes

rails realogy:sync_listings_delta       # Sync listings delta for last 15 minutes
rails realogy:sync_listings_delta[10]   # Sync listings delta for last 10 minutes

rails realogy:sync_offices_delta        # Sync offices delta for last 15 minutes
rails realogy:sync_offices_delta[10]    # Sync offices delta for last 10 minutes

rails realogy:sync_teams_delta          # Sync teams delta for last 15 minutes
rails realogy:sync_teams_delta[10]      # Sync teams delta for last 10 minutes

Delete All Expired Entities

rails realogy:delete_expired_agents         # Delete All Expired Agents
rails realogy:delete_expired_companies      # Delete All Expired Companies
rails realogy:delete_expired_listings       # Delete All Expired Listings
rails realogy:delete_expired_offices        # Delete All Expired Offices
rails realogy:delete_expired_teams          # Delete All Expired Teams

Catch-all that runs all other deletion tasks:

rails realogy:delete_expired_entities       # Delete all expired entities

Background/parallel processing

If Active Job isn't configured for queueing and background processing, Realogy will default to running rake tasks sequentially on the main thread.

Because of the volume of Realogy data, you will want to use Active Job for parallel processing in production. Configuring Active Job will cause available rake tasks to use it.

For example, if you've got Delayed Job installed, you'd add to your application.rb:

config.active_job.queue_adapter = :delayed_job

API Calls

Set up Realogy client

realogy = Realogy::DataSync.client

Get active objects

The calls to retrieve active entities are:

realogy.get_active_agents
realogy.get_active_companies
realogy.get_active_listings
realogy.get_active_offices
realogy.get_active_teams

When no argument is submitted, all active entities are returned.

Filters can be applied for brandCode and countryCode. For example:

# Fetch all active agents, for all brands, in all countries:
realogy.get_active_agents

# Fetch all active agents, for all brands, in Sweden:
realogy.get_active_companies(countryCode: "SE")

# Allowed brandCode values: C21, CB, ERA, SIR, BHG, CBC, ZIP, CLB, & COR
# Fetch all active Sotheby's agents in all countries:
realogy.get_active_offices(brandCode: "SIR")

# Fetch all active Sotheby's agents in Sweden:
realogy.get_active_teams(brandCode: "SIR", countryCode: "SE")

When fetching listings, the type of listing can also be specified:

# Allowed type values: ForSale, ForRent, ForSaleCommercial, & ForLeaseCommercial
# Fetch all active agents, for all brands, in all countries:
realogy.get_active_listings(type: "ForSale")

Retrieve delta of objects

The calls to retrieve entities that have recently changed are:

realogy.get_agents_delta
realogy.get_companies_delta
realogy.get_listings_delta
realogy.get_offices_delta
realogy.get_teams_delta

Each hash in the returned arrays includes a key action that returns either Delete or Upsert to indicate if the object has been deleted or created/updated.

When no argument is passed, the delta returned is for the last 20 minutes. A custom minutes delta can be passed in:

realogy.get_agents_delta(since: 20.minutes.ago)     # 20 minutes is the default
realogy.get_companies_delta(since: 1.hour.ago)
realogy.get_listings_delta(since: 2.hours.ago)
realogy.get_offices_delta(since: 5.minutes.ago)
realogy.get_teams_delta(since: 1.day.ago)

A few additional parameters are allowed:

realogy.get_listings_delta(brandCode: "SIR")
realogy.get_listings_delta(companyIds: "12345")
realogy.get_listings_delta(companyIds: "12345, 23456, 34567")
realogy.get_listings_delta(countryCode: "IT")
realogy.get_listings_delta(limit: 10)
realogy.get_listings_delta(type: "ForSale")

In case there are more entities available than is returned by the initial call, there will be a nextLink value present in the JSON response. By calling the nextLink URL as long as it is present, you will make retrieve all results.

If you want to automatically return all entities, pass in the flag followNext: true in your call:

realogy.get_listings_delta( ... , followNext: true)

When passing in followNext: true, the returned result will be an array of entities rather than the JSON object returned if it is omitted.

Get all listings

To retrieve all listings, fromDate and brandCode are mandatory parameters. A minimum call to retrieve all listing entities could look like this:

realogy.get_all_listings(brandCode: "COR", fromDate: 1.week.ago.json_string)

These are additional filters that can be applied:

# fromDate and toDate must be converted to supported text format. This is done with json_string:
realogy.get_all_listings(brandCode: "COR", fromDate: 1.week.ago.json_string, toDate: DateTime.now.json_string)

# Allowed type values: ForSale, ForRent, ForSaleCommercial, & ForLeaseCommercial
realogy.get_all_listings(brandCode: "C21", fromDate: 1.week.ago.json_string, type: "ForSale")

# Allowed status values: Active, Available, Pending, & Closed
realogy.get_all_listings(brandCode: "CB", fromDate: 1.week.ago.json_string, status: "Active")

# Limit results to a particular country
realogy.get_all_listings(brandCode: "SIR", fromDate: 1.week.ago.json_string, countryCode: "IT")

# Limit number of listings per result batch. Allowed span: 10–1000.
realogy.get_all_listings(brandCode: "BHG", fromDate: 1.week.ago.json_string, limit: 10)

In case there are more listings available than is returned by the get_all_listings call, there will be a nextLink value present in the JSON response. By calling the nextLink URL as long as it is present, you will traverse through all results.

If you want to automatically return all results, pass in the flag followNext: true in your call:

realogy.get_all_listings( ... , followNext: true)

When passing in followNext: true, the returned result will be an array of entities rather than the JSON object returned if it is omitted.

Retrieve JSON object

realogy.get_agent_by_id(entity_id)
realogy.get_agent_by_id(entity_id)
realogy.get_listing_by_id(entity_id)
realogy.get_office_by_id(entity_id)
realogy.get_team_by_id(entity_id)

Instance methods

Convenience methods to access JSON.

Realogy::Agent

  • addl_emails
  • addl_languages_names
  • addl_phones
  • agent_summary
  • agent_id
  • areas_of_specialization
  • business_phone
  • business_phone_ext
  • company_brand_code
  • company_id
  • company_name
  • default_photo_url
  • designations
  • display_title
  • email_address
  • first_name
  • gender
  • has_producing_role?
  • is_agent?
  • is_full_time?
  • is_team_member?
  • languages_spoken
  • last_name
  • last_update_on
  • lead_email_address
  • license_info
  • media
  • middle_name
  • mls_information
  • mobile_phone
  • name
  • office
  • office_address
  • office_city
  • office_country
  • office_country_code
  • office_district
  • office_email_address
  • office_fax_number
  • office_formatted_address
  • office_id
  • office_latitude
  • office_longitude
  • office_name
  • office_phone_number
  • office_postal_code
  • office_state_province
  • office_state_province_code
  • office_street_address
  • office_type
  • remarks
  • roles
  • specialty
  • websites

Realogy::Company

  • addl_language_names
  • addl_websites
  • brand_code
  • can_do_commercial_business?
  • commercial_company_name
  • company_id
  • company_summary
  • is_nrt?
  • last_update_on
  • media
  • name
  • programs
  • rfg_id
  • website_url

Realogy::Listing

  • active?
  • agents
  • agricultural_property_number
  • anchor_stores
  • annual_tax
  • available_floors
  • available_space
  • average_floor_size
  • average_occupancy_rate
  • bay_depth
  • building_area
  • building_class
  • by_appointment_only?
  • call_to_show?
  • cap_rate_percent
  • cash_flow
  • ceiling_height
  • city
  • clearance
  • column_spacing
  • common_area_factor
  • country
  • country_code
  • default_photo_url
  • development
  • district
  • dock_height
  • down_payment
  • floors
  • formatted_address
  • full_bath
  • fully_leased_income
  • geocode_confidence_level
  • geographic_regions
  • gross_income
  • ground_level?
  • half_bath
  • has_cross_docks?
  • has_rail_access?
  • has_sprinkler?
  • hide_list_price?
  • is_for_auction?
  • is_foreclosure?
  • is_short_sale?
  • last_sold_on
  • last_update_on
  • latitude
  • lead_email
  • lease_term
  • lease_type
  • levels
  • linked_office
  • list_price
  • list_price_amount
  • list_price_currency_code
  • listed_on
  • listing_id
  • listing_type
  • listing_url
  • loan_payment
  • longitude
  • lot_dimension
  • lot_size
  • mapping_allowed?
  • max_contiguous_area
  • maximum_lease_rate
  • media
  • min_divisible_area
  • minimum_lease_rate
  • mls_information
  • mls_numbers
  • net_operating_income
  • new_construction?
  • no_of_bedrooms
  • number_of_ballrooms
  • number_of_conference_rooms
  • number_of_docks
  • occupancy_rate
  • open_house
  • parking_places
  • parking_ratio
  • partial_bath
  • pending?
  • photo_count
  • postal_code
  • power
  • price_per_area
  • price_upon_request?
  • property_address
  • property_category
  • property_features
  • property_fees
  • property_floors
  • property_name
  • property_rooms
  • property_style
  • property_type
  • property_use
  • provider_category
  • provider_key
  • provider_name
  • provider_url
  • quarter_bath
  • remarks
  • rental_frequency
  • rfg_listing_id
  • schedule_income
  • schools
  • show_address_on_internet?
  • square_footage
  • state_province
  • state_province_code
  • street_address
  • sub_lease?
  • sub_units
  • suite_apartment_name
  • suites
  • tax_id_number
  • tax_information
  • tax_roll_number
  • tax_year
  • team
  • three_quarter_bath
  • total_acres
  • total_bath
  • total_expenses
  • total_rooms
  • total_units
  • turning_radius
  • video_count
  • websites
  • year_built
  • year_renovated
  • zoning

Realogy::Office

  • addl_language_names
  • addl_phone_numbers
  • addl_websites
  • area_served
  • brand_code
  • broker_name
  • city
  • company_id
  • company_name
  • country
  • country_code
  • default_photo_url
  • district
  • email_address
  • entity_preference
  • fax_number
  • formatted_address
  • geographic_regions
  • languages_spoken
  • last_update_on
  • latitude
  • lead_email_address
  • longitude
  • media
  • mls_information
  • name
  • office_address
  • office_id
  • office_manager_name
  • office_summary
  • office_type
  • phone_number
  • postal_code
  • recruiting_email_address
  • remarks
  • rfg_company_id
  • rfg_office_id
  • seasonal_close_mmdd
  • seasonal_open_mmdd
  • special_markets
  • state_province
  • state_province_code
  • street_address
  • website_url

Realogy::Team

  • awards
  • addl_phone_numbers
  • addl_emails
  • addl_language_names
  • addl_websites
  • email_address
  • last_update_on
  • media
  • members
  • name
  • office
  • phone_number
  • remarks
  • rfg_team_id
  • team_id
  • team_type
  • team_summary
  • website_url

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/arcticleo/realogy-sync. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.