spark_api 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. data/README.md +86 -3
  2. data/VERSION +1 -1
  3. data/lib/spark_api.rb +1 -0
  4. data/lib/spark_api/authentication/oauth2.rb +43 -2
  5. data/lib/spark_api/configuration/oauth2_configurable.rb +3 -1
  6. data/lib/spark_api/models.rb +1 -0
  7. data/lib/spark_api/models/listing.rb +17 -1
  8. data/lib/spark_api/models/rental_calendar.rb +26 -0
  9. data/lib/spark_api/options_hash.rb +18 -0
  10. data/script/combined_flow_example.rb +55 -0
  11. data/script/oauth2_example.rb +2 -2
  12. data/spec/fixtures/listings/rental_calendar.json +19 -0
  13. data/spec/fixtures/listings/with_rental_calendar.json +52 -0
  14. data/spec/unit/spark_api/authentication/oauth2_spec.rb +79 -1
  15. data/spec/unit/spark_api/models/listing_spec.rb +7 -0
  16. data/spec/unit/spark_api/models/rental_calendar_spec.rb +30 -0
  17. data/spec/unit/spark_api/options_hash_spec.rb +14 -0
  18. metadata +15 -96
  19. data/bin/spark_api~ +0 -8
  20. data/lib/spark_api/authentication/api_auth.rb~ +0 -104
  21. data/lib/spark_api/authentication/base_auth.rb~ +0 -47
  22. data/lib/spark_api/authentication/oauth2.rb~ +0 -199
  23. data/lib/spark_api/authentication/oauth2_impl/grant_type_base.rb~ +0 -87
  24. data/lib/spark_api/authentication/oauth2_impl/grant_type_code.rb~ +0 -49
  25. data/lib/spark_api/authentication/oauth2_impl/grant_type_password.rb~ +0 -45
  26. data/lib/spark_api/authentication/oauth2_impl/grant_type_refresh.rb~ +0 -36
  27. data/lib/spark_api/authentication/oauth2_impl/middleware.rb~ +0 -39
  28. data/lib/spark_api/authentication/oauth2_impl/password_provider.rb~ +0 -25
  29. data/lib/spark_api/cli.rb~ +0 -158
  30. data/lib/spark_api/cli/api_auth.rb~ +0 -8
  31. data/lib/spark_api/cli/oauth2.rb~ +0 -14
  32. data/lib/spark_api/cli/setup.rb~ +0 -47
  33. data/lib/spark_api/configuration.rb~ +0 -54
  34. data/lib/spark_api/configuration/yaml.rb~ +0 -101
  35. data/lib/spark_api/faraday.rb~ +0 -64
  36. data/lib/spark_api/models.rb~ +0 -33
  37. data/lib/spark_api/models/account.rb~ +0 -115
  38. data/lib/spark_api/models/base.rb~ +0 -118
  39. data/lib/spark_api/models/connect_prefs.rb~ +0 -10
  40. data/lib/spark_api/models/constraint.rb~ +0 -16
  41. data/lib/spark_api/models/contact.rb~ +0 -49
  42. data/lib/spark_api/models/custom_fields.rb~ +0 -12
  43. data/lib/spark_api/models/document.rb~ +0 -11
  44. data/lib/spark_api/models/finders.rb~ +0 -45
  45. data/lib/spark_api/models/idx_link.rb~ +0 -47
  46. data/lib/spark_api/models/listing.rb~ +0 -197
  47. data/lib/spark_api/models/listing_cart.rb~ +0 -72
  48. data/lib/spark_api/models/market_statistics.rb~ +0 -33
  49. data/lib/spark_api/models/message.rb~ +0 -21
  50. data/lib/spark_api/models/note.rb~ +0 -41
  51. data/lib/spark_api/models/notification.rb~ +0 -42
  52. data/lib/spark_api/models/open_house.rb~ +0 -24
  53. data/lib/spark_api/models/photo.rb~ +0 -70
  54. data/lib/spark_api/models/property_types.rb~ +0 -7
  55. data/lib/spark_api/models/saved_search.rb~ +0 -16
  56. data/lib/spark_api/models/shared_listing.rb~ +0 -35
  57. data/lib/spark_api/models/standard_fields.rb~ +0 -50
  58. data/lib/spark_api/models/subresource.rb~ +0 -19
  59. data/lib/spark_api/models/system_info.rb~ +0 -14
  60. data/lib/spark_api/models/tour_of_home.rb~ +0 -24
  61. data/lib/spark_api/models/video.rb~ +0 -16
  62. data/lib/spark_api/models/virtual_tour.rb~ +0 -18
  63. data/lib/spark_api/multi_client.rb~ +0 -59
  64. data/lib/spark_api/paginate.rb~ +0 -109
  65. data/lib/spark_api/primary_array.rb~ +0 -29
  66. data/lib/spark_api/request.rb~ +0 -96
  67. data/lib/spark_api/response.rb~ +0 -70
  68. data/lib/spark_api/version.rb~ +0 -4
  69. data/script/console~ +0 -6
  70. data/script/example.rb~ +0 -27
  71. data/spec/unit/flexmls_api_spec.rb~ +0 -23
  72. data/spec/unit/spark_api/authentication/api_auth_spec.rb~ +0 -169
  73. data/spec/unit/spark_api/authentication/base_auth_spec.rb~ +0 -10
  74. data/spec/unit/spark_api/authentication/oauth2_impl/grant_type_base_spec.rb~ +0 -10
  75. data/spec/unit/spark_api/authentication/oauth2_spec.rb~ +0 -205
  76. data/spec/unit/spark_api/authentication_spec.rb~ +0 -38
  77. data/spec/unit/spark_api/configuration/yaml_spec.rb~ +0 -72
  78. data/spec/unit/spark_api/configuration_spec.rb~ +0 -122
  79. data/spec/unit/spark_api/faraday_spec.rb~ +0 -90
  80. data/spec/unit/spark_api/models/contact_spec.rb~ +0 -108
  81. data/spec/unit/spark_api/models/listing_cart_spec.rb~ +0 -127
  82. data/spec/unit/spark_api/models/listing_spec.rb~ +0 -320
  83. data/spec/unit/spark_api/models/message_spec.rb~ +0 -47
  84. data/spec/unit/spark_api/models/note_spec.rb~ +0 -63
  85. data/spec/unit/spark_api/models/notification_spec.rb~ +0 -62
  86. data/spec/unit/spark_api/models/shared_listing_spec.rb~ +0 -45
  87. data/spec/unit/spark_api/multi_client_spec.rb~ +0 -56
  88. data/spec/unit/spark_api/paginate_spec.rb~ +0 -224
  89. data/spec/unit/spark_api/primary_array_spec.rb~ +0 -41
  90. data/spec/unit/spark_api/request_spec.rb~ +0 -344
data/README.md CHANGED
@@ -15,13 +15,56 @@ Installation
15
15
  Usage Examples
16
16
  ------------------------
17
17
 
18
+ #### Ruby Script: OpenId/OAuth2 Combined Flow
19
+ # initialize the gem with your key/secret.
20
+ # See also: script/combined_flow_example.rb
21
+ # api_key, api_secret, and callback are all required.
22
+ # The following options are required:
23
+ # - api_key: Your client key
24
+ # - api_secret: Your client secret
25
+ # - callback: Your redirect_uri, which the end user will be redirected
26
+ # to after authorizing your application to access their data.
27
+ # - auth_endpoint: The URI to redirect the user's web browser to, in order for them to
28
+ # authorize your application to access their data.
29
+ # other options and their defaults:
30
+ # - endpoint: 'https://api.sparkapi.com'
31
+ # - version: 'v1'
32
+ # - ssl: true
33
+ # - user_agent: 'Spark API Ruby Gem'
34
+ SparkApi.configure do |config|
35
+ config.authentication_mode = SparkApi::Authentication::OpenIdOAuth2Hybrid
36
+ config.api_key = "YOUR_CLIENT_ID"
37
+ config.api_secret = "YOUR_CLIENT_SECRET"
38
+ config.callback = "YOUR_REDIRECT_URI"
39
+ config.auth_endpoint = "https://developers.sparkplatform.com/openid"
40
+ config.endpoint = 'https://developers.sparkapi.com'
41
+ end
42
+
43
+ # Code is retrieved from the method: SparkApi.client.authenticator.authorization_url
44
+ # See script/combined_flow_example.rb for more details.
45
+
46
+
47
+ SparkApi.client.oauth2_provider.code = "CODE_FROM_ABOVE_URI"
48
+ SparkApi.client.authenticate
49
+
50
+ # Alternatively, if you've already received an access token, you may
51
+ # do the following instead of the above two lines:
52
+ # SparkApi.client.session = SparkApi::Authentication::OAuthSession.new "access_token"=> "ACCESS_TOKEN",
53
+ # "refresh_token" => "REFRESH_TOKEN", "expires_in" => 86400
54
+
55
+ # mixin the models so you can use them without prefix
56
+ include SparkApi::Models
57
+
58
+ # Grab your listings!
59
+ my_listings = Listing.my()
60
+
18
61
  #### Ruby Script: OAuth 2
19
62
  # initialize the gem with your OAuth 2 key/secret.
20
63
  # See also: script/oauth2_example.rb
21
64
  # api_key, api_secret, and callback are all required.
22
65
  # The following options are required:
23
66
  # - api_key: Your OAuth 2 client key
24
- # - api-secret: Your OAuth 2 client secret
67
+ # - api_secret: Your OAuth 2 client secret
25
68
  # - callback: Your OAuth 2 redirect_uri, which the end user will be redirected
26
69
  # to after authorizing your application to access their data.
27
70
  # - auth_endpoint: The URI to redirect the user's web browser to, in order for them to
@@ -40,7 +83,7 @@ Usage Examples
40
83
  config.endpoint = 'https://developers.sparkapi.com'
41
84
  end
42
85
 
43
- # Code is retrieved from the method. client.authenticator.authorization_url
86
+ # Code is retrieved from the method. SparkApi.client.authenticator.authorization_url
44
87
  # See script/oauth2_example.rb for more details.
45
88
 
46
89
 
@@ -58,6 +101,36 @@ Usage Examples
58
101
  # Grab your listings!
59
102
  my_listings = Listing.my()
60
103
 
104
+
105
+ #### Ruby Script: OpenId Only
106
+ # initialize the gem with your key/secret.
107
+ # api_key, api_secret, and callback are all required.
108
+ # The following options are required:
109
+ # - api_key: Your client key
110
+ # - api_secret: Your client secret
111
+ # - callback: Your redirect_uri, which the end user will be redirected
112
+ # to after authorizing your application to access their data.
113
+ # - auth_endpoint: The URI to redirect the user's web browser to, in order for them to
114
+ # authorize your application to access their data.
115
+ # other options and their defaults:
116
+ # - user_agent: 'Spark API Ruby Gem'
117
+ SparkApi.configure do |config|
118
+ config.authentication_mode = SparkApi::Authentication::OpenId
119
+ config.api_key = "YOUR_CLIENT_ID"
120
+ config.api_secret = "YOUR_CLIENT_SECRET"
121
+ config.callback = "YOUR_REDIRECT_URI"
122
+ config.auth_endpoint = "https://developers.sparkplatform.com/openid"
123
+ end
124
+
125
+ # Code is retrieved from the method:
126
+ # See script/combined_flow_example.rb for more details.
127
+ # Optionally, additional a GET parameters can be supplied as a hash to
128
+ # authorization_url.
129
+ # SparkApi.client.authenticator.authorization_url
130
+
131
+ # That's it! No API Access is available when using OpenID alone.
132
+
133
+
61
134
  #### Ruby Script
62
135
  # initialize the gem with your key/secret
63
136
  # api_key and _api_secret are the only required settings
@@ -105,11 +178,21 @@ Authentication is handled transparently by the request framework in the gem, so
105
178
  #### API Authentication (Default)
106
179
  Usually supplied for a single user, this authentication mode is the simplest, and is setup as the default. The example usage above demonstrates how to get started using this authentication mode.
107
180
 
108
- #### OAuth2 Authorization (Preferred)
181
+ #### OpenId/OAuth2 Combined Flow (Preferred)
182
+ Authorization mode the separates application and user authentication. This mode requires the end user to be redirected to Spark Platform's openid endpoint. See "script/combined_flow_example.rb" for an example.
183
+
184
+ Read more about Spark Platform's combined flow <a href="http://sparkplatform.com/docs/authentication/openid_oauth2_authentication">here</a>.
185
+
186
+ #### OAuth2 Authorization
109
187
  Authorization mode the separates application and user authentication. This mode requires the end user to be redirected to Spark Platform's auth endpoint. See "script/oauth2_example.rb" for an example.
110
188
 
111
189
  Read more about Spark Platform's OAuth 2 flow <a href="http://sparkplatform.com/docs/authentication/oauth2_authentication">here</a>.
112
190
 
191
+ #### OpenId Authentication
192
+ There is also the option to only access a user's Spark Platform identity without accessing any data (e.g. listings, contacts, etc.). In circumstances where you ONLY with to authenticate users through the Spark Platform, but do not have a use case to access any of their data, consider the OpenId authentication flow in lieu of API Authentication or the Combined flow.
193
+
194
+ Read more about Spark Platform's OpenId flow <a href="http://sparkplatform.com/docs/authentication/openid_authentication">here</a>.
195
+
113
196
  Error Codes
114
197
  ---------------------
115
198
  <table>
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.2
1
+ 1.0.4
data/lib/spark_api.rb CHANGED
@@ -13,6 +13,7 @@ require 'spark_api/connection'
13
13
  require 'spark_api/client'
14
14
  require 'spark_api/faraday'
15
15
  require 'spark_api/primary_array'
16
+ require 'spark_api/options_hash'
16
17
  require 'spark_api/models'
17
18
 
18
19
  module SparkApi
@@ -67,7 +67,6 @@ module SparkApi
67
67
  }
68
68
  "#{@provider.authorization_uri}?#{build_url_parameters(params)}"
69
69
  end
70
-
71
70
 
72
71
  protected
73
72
 
@@ -83,12 +82,54 @@ module SparkApi
83
82
  end
84
83
 
85
84
  end
85
+
86
+ #==OpenId/OAuth 2 Hybrid
87
+ # Uses OpenId for Authentication, but also uses OAuth2 for authorization.
88
+ class OpenIdOAuth2Hybrid < OAuth2
89
+ def authorization_url(parameters={})
90
+ params = openid_parameters.merge(parameters)
91
+ params["openid.spark.combined_flow"] = true
92
+ build_openid_uri(params)
93
+ end
94
+
95
+ protected
96
+
97
+ def build_openid_uri(params)
98
+ "#{@provider.authorization_uri}?#{build_url_parameters(params)}"
99
+ end
100
+
101
+ def openid_parameters
102
+ {
103
+ "openid.mode" => "checkid_setup",
104
+ "openid.spark.client_id" => @provider.client_id,
105
+ "openid.return_to" => @provider.redirect_uri
106
+ }
107
+ end
108
+ end
109
+
110
+ class OpenId < OpenIdOAuth2Hybrid
111
+ def authorization_url(parameters={})
112
+ params = openid_parameters.merge(parameters)
113
+ build_openid_uri(params)
114
+ end
115
+
116
+ def authenticate
117
+ raise RuntimeError, "API Authorization not available with an OpenId-only Auth instance"
118
+ end
119
+
120
+ def request(method, path, body, options={})
121
+ raise RuntimeError, "API Data not available with an OpenId-only Auth instance"
122
+ end
123
+ end
86
124
 
87
125
  # Representation of a session with the api using oauth2
88
126
  class OAuthSession
89
127
  SESSION_ATTRIBUTES = [:access_token, :expires_in, :scope, :refresh_token, :refresh_timeout, :start_time]
90
128
  attr_accessor *SESSION_ATTRIBUTES
91
- def initialize(options={})
129
+ def initialize(o={})
130
+
131
+ options = OptionsHash.new(o)
132
+
92
133
  @access_token = options["access_token"]
93
134
  @expires_in = options["expires_in"]
94
135
  @scope = options["scope"]
@@ -2,7 +2,9 @@ module SparkApi
2
2
  module Configuration
3
3
  module OAuth2Configurable
4
4
  def convert_to_oauth2?
5
- self.authentication_mode == SparkApi::Authentication::OAuth2 &&
5
+ (self.authentication_mode == SparkApi::Authentication::OAuth2 ||
6
+ self.authentication_mode == SparkApi::Authentication::OpenId ||
7
+ self.authentication_mode == SparkApi::Authentication::OpenIdOAuth2Hybrid) &&
6
8
  self.oauth2_provider.nil?
7
9
  end
8
10
 
@@ -25,6 +25,7 @@ require 'spark_api/models/system_info'
25
25
  require 'spark_api/models/tour_of_home'
26
26
  require 'spark_api/models/video'
27
27
  require 'spark_api/models/virtual_tour'
28
+ require 'spark_api/models/rental_calendar'
28
29
 
29
30
  module SparkApi
30
31
  module Models
@@ -2,7 +2,7 @@ module SparkApi
2
2
  module Models
3
3
  class Listing < Base
4
4
  extend Finders
5
- attr_accessor :photos, :videos, :virtual_tours, :documents, :open_houses, :tour_of_homes
5
+ attr_accessor :photos, :videos, :virtual_tours, :documents, :open_houses, :tour_of_homes, :rental_calendars
6
6
  attr_accessor :constraints
7
7
  self.element_name="listings"
8
8
  DATA_MASK = "********"
@@ -12,6 +12,7 @@ module SparkApi
12
12
  @photos = []
13
13
  @videos = []
14
14
  @virtual_tours = []
15
+ @rental_calendars = []
15
16
  @documents = []
16
17
  @constraints = []
17
18
  #@tour_of_homes = []
@@ -20,6 +21,10 @@ module SparkApi
20
21
  pics, vids, tours, docs, ohouses, tourhomes = attributes['StandardFields'].values_at('Photos','Videos', 'VirtualTours', 'Documents', 'OpenHouses', 'TourOfHomes')
21
22
  end
22
23
 
24
+ if attributes.has_key?('RentalCalendar')
25
+ rentalcalendars = attributes['RentalCalendar']
26
+ end
27
+
23
28
  if pics != nil
24
29
  pics.collect { |pic| @photos.push(Photo.new(pic)) }
25
30
  attributes['StandardFields'].delete('Photos')
@@ -52,6 +57,11 @@ module SparkApi
52
57
  attributes['StandardFields'].delete('TourOfHomes')
53
58
  end
54
59
 
60
+ if rentalcalendars != nil
61
+ rentalcalendars.collect { |rentalcalendar| @rental_calendars.push(RentalCalendar.new(rentalcalendar)) }
62
+ attributes.delete('RentalCalendar')
63
+ end
64
+
55
65
  super(attributes)
56
66
  end
57
67
 
@@ -82,6 +92,12 @@ module SparkApi
82
92
  return @tour_of_homes unless @tour_of_homes.nil?
83
93
  end
84
94
 
95
+ def rental_calendars(arguments={})
96
+ @rental_calendars ||= RentalCalendar.find_by_listing_key(self.Id, arguments)
97
+ return @rental_calendars unless @rental_calendars.nil?
98
+ end
99
+
100
+
85
101
  def open_houses(arguments={})
86
102
  @open_houses ||= OpenHouse.find_by_listing_key(self.Id, arguments)
87
103
  return @open_houses unless @open_houses.nil?
@@ -0,0 +1,26 @@
1
+ module SparkApi
2
+ module Models
3
+ class RentalCalendar < Base
4
+ extend Subresource
5
+ self.element_name="rentalcalendar"
6
+
7
+ def initialize(attributes={})
8
+ # Transform the date strings
9
+ unless attributes['StartDate'].nil?
10
+ date = Date.parse(attributes['StartDate'])
11
+ attributes['StartDate'] = date
12
+ end
13
+ unless attributes['EndDate'].nil?
14
+ date = Date.parse(attributes['EndDate'])
15
+ attributes['EndDate'] = date
16
+ end
17
+ super(attributes)
18
+ end
19
+
20
+ def include_date? (day)
21
+ day >= self.StartDate && day <= self.EndDate
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ module SparkApi
2
+ # Used for API client options that accept string keys instead of symbols --
3
+ # turns all symbol keys into a string for consistancy, allowing applications
4
+ # using the client to pass in parameters as symbols or strings.
5
+ class OptionsHash < Hash
6
+ def initialize(from_hash={})
7
+ from_hash.keys.each do |k|
8
+ if k.is_a?(Symbol)
9
+ self[k.to_s] = from_hash[k]
10
+ else
11
+ self[k] = from_hash[k]
12
+ end
13
+ end
14
+ self
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+ require "rubygems"
3
+
4
+ Bundler.require(:default, "development") if defined?(Bundler)
5
+
6
+ path = File.expand_path(File.dirname(__FILE__) + "/../lib/")
7
+ $LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
8
+ require path + '/spark_api'
9
+
10
+ SparkApi.logger.info("Hello!")
11
+
12
+ SparkApi.configure do |config|
13
+ config.authentication_mode = SparkApi::Authentication::OpenIdOAuth2Hybrid
14
+ config.api_key = "YOUR_CLIENT_ID"
15
+ config.api_secret = "YOUR_CLIENT_SECRET"
16
+ config.callback = "YOUR_REDIRECT_URI"
17
+ config.auth_endpoint = "https://developers.sparkplatform.com/openid"
18
+ config.endpoint = 'https://developers.sparkapi.com'
19
+ end
20
+
21
+ client = SparkApi.client
22
+
23
+
24
+ # Step 1:
25
+ # To get your code to post to /v1/oauth2/grant, send the end user to this URI, replacing the all-capped strings with
26
+ # the CGI-escaped credentials for your key:
27
+ # https://developers.sparkplatform.com/oauth2?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI
28
+ # When the user has finished, they will land at:
29
+ # YOUR_REDIRECT_URI?code=CODE.
30
+ puts "Go here and log in to get your code: #{client.authenticator.authorization_url}"
31
+
32
+ # Step 2: Uncomment the following, and add your code in place of CODE_FROM_ABOVE_URI
33
+ # Hold on to the tokens. Unless you lose them, you can now pass in these
34
+ # values until the access_token expires.
35
+ #client.oauth2_provider.code = "CODE_FROM_ABOVE_URI"
36
+ #client.authenticate
37
+ #puts "Access Token: #{client.session.access_token}, Refresh Token: #{client.session.refresh_token}"
38
+
39
+
40
+ # Step 3: Comment out Step 2, and uncomment the following.
41
+ # Pass in your access_token and refresh_token to make authenticated requests to the API
42
+ #client.session = SparkApi::Authentication::OAuthSession.new "access_token"=> "ACCESS_TOKEN",
43
+ # "refresh_token" => "REFRESH_TOKEN", "expires_in" => 86400
44
+
45
+
46
+ # Step 2a and 3a: Uncomment with Step 3 and 4.
47
+ # Make requests for authorized listing data
48
+ #list = client.get '/contacts'
49
+ #puts "client: #{list.inspect}"
50
+ #list = SparkApi::Models::Contact.get
51
+ #puts "model: #{list.inspect}"
52
+
53
+
54
+
55
+
@@ -38,13 +38,13 @@ puts "Go here and log in to get your code: #{client.authenticator.authorization_
38
38
  #puts "Access Token: #{client.session.access_token}, Refresh Token: #{client.session.refresh_token}"
39
39
 
40
40
 
41
- # Step 4: Comment out Step 3, and uncomment the following.
41
+ # Step 3: Comment out Step 2, and uncomment the following.
42
42
  # Pass in your access_token and refresh_token to make authenticated requests to the API
43
43
  #client.session = SparkApi::Authentication::OAuthSession.new "access_token"=> "ACCESS_TOKEN",
44
44
  # "refresh_token" => "REFRESH_TOKEN", "expires_in" => 86400
45
45
 
46
46
 
47
- # Step 3a and 4a: Uncomment with Step 3 and 4.
47
+ # Step 2a and 3a: Uncomment with Step 2 and 3.
48
48
  # Make requests for authorized listing data
49
49
  #list = client.get '/contacts'
50
50
  #puts "client: #{list.inspect}"
@@ -0,0 +1,19 @@
1
+ {
2
+ "D": {
3
+ "Results": [
4
+ {
5
+ "EndDate": "2012-07-16",
6
+ "Id": "20120705192139246257000000",
7
+ "StartDate": "2012-07-12",
8
+ "Type": "Rented"
9
+ },
10
+ {
11
+ "EndDate": "2012-07-23",
12
+ "Id": "20120705192148668143000000",
13
+ "StartDate": "2012-07-20",
14
+ "Type": "Rented"
15
+ }
16
+ ],
17
+ "Success": true
18
+ }
19
+ }
@@ -0,0 +1,52 @@
1
+ {
2
+ "D": {
3
+ "Results": [
4
+ {
5
+ "ResourceUri": "/v1/listings/20060813163018826257000000",
6
+ "StandardFields": {
7
+ "StreetNumber": "2755",
8
+ "Longitude": "-116.7506",
9
+ "City": "Hayden",
10
+ "ListingId": "06-10376",
11
+ "PublicRemarks": "Incredible horse estate in Hayden. Over 14 acres with panoramic views. Cape Cod style residence, 4500+ sq ft w/4 bdrms, 4.5 baths. 82x60 horse barn, heated with hayloft & lg guest house. 70x160 indoor horse arean, heated, viewing area boasts large river rock fireplace & bbq area. The Ultimate in luxury living!",
12
+ "BuildingAreaTotal": "5400.0",
13
+ "YearBuilt": 1996,
14
+ "StreetName": "SPRING ROCK LN",
15
+ "ListPrice": "2950000.0",
16
+ "PostalCode": "83835",
17
+ "Latitude": "47.7959",
18
+ "BathsThreeQuarter": null,
19
+ "BathsFull": null,
20
+ "BathsTotal": "4.5",
21
+ "StateOrProvince": "ID",
22
+ "PropertyType": "A",
23
+ "StreetAdditionalInfo": null,
24
+ "StreetDirPrefix": "E",
25
+ "BedsTotal": 4,
26
+ "StreetDirSuffix": null,
27
+ "ListingKey": "20060813163018826257000000",
28
+ "ListOfficeName": "Coldwell Banker Schneidmiller Realty",
29
+ "BathsHalf": null,
30
+ "ModificationTimestamp": "2010-11-22T20:52:54Z",
31
+ "CountyOrParish": "Kootenai"
32
+ },
33
+ "Id": "20060813163018826257000000",
34
+ "RentalCalendar": [
35
+ {
36
+ "EndDate": "2012-07-16",
37
+ "Id": "20120705192139246257000000",
38
+ "StartDate": "2012-07-12",
39
+ "Type": "Rented"
40
+ },
41
+ {
42
+ "EndDate": "2012-07-23",
43
+ "Id": "20120705192148668143000000",
44
+ "StartDate": "2012-07-20",
45
+ "Type": "Rented"
46
+ }
47
+ ]
48
+ }
49
+ ],
50
+ "Success": true
51
+ }
52
+ }