spark_api 1.0.2 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
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
+ }