repull 0.2.34 → 0.2.36

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/lib/repull/api/connect_api.rb +6 -6
  3. data/lib/repull/api/health_api.rb +3 -3
  4. data/lib/repull/api/listings_api.rb +8 -8
  5. data/lib/repull/api/migrate_api.rb +68 -0
  6. data/lib/repull/models/{calendar_updated_event.rb → booking_unacknowledged_event.rb} +4 -4
  7. data/lib/repull/models/booking_unacknowledged_payload.rb +229 -0
  8. data/lib/repull/models/channel_degraded_event.rb +279 -0
  9. data/lib/repull/models/channel_degraded_payload.rb +174 -0
  10. data/lib/repull/models/channel_degraded_payload_object.rb +262 -0
  11. data/lib/repull/models/channel_sync_failed_event.rb +280 -0
  12. data/lib/repull/models/channel_sync_failure_payload.rb +214 -0
  13. data/lib/repull/models/channel_sync_failure_payload_failures_inner.rb +213 -0
  14. data/lib/repull/models/channel_sync_failure_payload_object.rb +289 -0
  15. data/lib/repull/models/charge_per.rb +42 -0
  16. data/lib/repull/models/connect_session_completed_payload.rb +1 -1
  17. data/lib/repull/models/connect_status_accounts_inner.rb +12 -1
  18. data/lib/repull/models/create_connect_session_request.rb +26 -2
  19. data/lib/repull/models/create_connection_request.rb +3 -23
  20. data/lib/repull/models/{plumguide_listing_list_response.rb → import_from_channex200_response.rb} +8 -19
  21. data/lib/repull/models/import_from_channex200_response_data.rb +324 -0
  22. data/lib/repull/models/import_from_channex200_response_data_channels_inner.rb +263 -0
  23. data/lib/repull/models/import_from_channex200_response_data_properties_inner.rb +222 -0
  24. data/lib/repull/models/import_from_channex200_response_data_summary.rb +201 -0
  25. data/lib/repull/models/import_from_channex200_response_data_summary_bookings.rb +165 -0
  26. data/lib/repull/models/import_from_channex200_response_data_summary_properties.rb +165 -0
  27. data/lib/repull/models/import_from_channex_request.rb +223 -0
  28. data/lib/repull/models/list_connection_units200_response.rb +12 -1
  29. data/lib/repull/models/list_connection_units200_response_units_inner.rb +1 -0
  30. data/lib/repull/models/listing.rb +82 -1
  31. data/lib/repull/models/listing_address.rb +62 -5
  32. data/lib/repull/models/listing_content_photo.rb +206 -0
  33. data/lib/repull/models/listing_fee.rb +229 -0
  34. data/lib/repull/models/listing_policies.rb +257 -0
  35. data/lib/repull/models/{calendar_updated_payload.rb → listing_policies_check_in.rb} +33 -38
  36. data/lib/repull/models/listing_policies_check_out.rb +148 -0
  37. data/lib/repull/models/{calendar_updated_payload_range.rb → listing_policies_quiet_hours.rb} +5 -5
  38. data/lib/repull/models/listing_pricing_settings.rb +233 -0
  39. data/lib/repull/models/listing_room.rb +190 -0
  40. data/lib/repull/models/{plumguide_listing.rb → listing_room_beds_inner.rb} +16 -27
  41. data/lib/repull/models/listing_rules.rb +212 -0
  42. data/lib/repull/models/listing_tax.rb +241 -0
  43. data/lib/repull/models/message.rb +24 -1
  44. data/lib/repull/models/postal_address.rb +216 -0
  45. data/lib/repull/models/property.rb +12 -2
  46. data/lib/repull/models/reservation_thread_assigned_event.rb +279 -0
  47. data/lib/repull/models/reservation_thread_assigned_payload.rb +174 -0
  48. data/lib/repull/models/reservation_thread_assigned_payload_object.rb +249 -0
  49. data/lib/repull/models/webhook_event.rb +8 -2
  50. data/lib/repull/models/webhook_event_type.rb +5 -2
  51. data/lib/repull/version.rb +1 -1
  52. data/lib/repull.rb +33 -6
  53. data/openapi/v1.json +1712 -352
  54. metadata +35 -10
  55. data/lib/repull/api/plumguide_api.rb +0 -552
  56. data/spec/api/plumguide_api_spec.rb +0 -85
@@ -0,0 +1,289 @@
1
+ =begin
2
+ #Repull API
3
+
4
+ #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_live_YOUR_API_KEY ``` ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resetsAt` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | unlimited (10 included, then billed per listing) | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
+
6
+ The version of the OpenAPI document: 1.0.0
7
+
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.22.0
10
+
11
+ =end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ module Repull
17
+ class ChannelSyncFailurePayloadObject < ApiModelBase
18
+ attr_accessor :listing_id
19
+
20
+ attr_accessor :customer_id
21
+
22
+ # Which wire failed. A refused rate and a closed connection call for different responses.
23
+ attr_accessor :operation
24
+
25
+ # true when NO mapping accepted the push. false means some did — the more dangerous case, because the listing is live somewhere and inconsistent.
26
+ attr_accessor :total
27
+
28
+ # Start of the date range the push covered, when the operation is date-scoped.
29
+ attr_accessor :from
30
+
31
+ attr_accessor :to
32
+
33
+ class EnumAttributeValidator
34
+ attr_reader :datatype
35
+ attr_reader :allowable_values
36
+
37
+ def initialize(datatype, allowable_values)
38
+ @allowable_values = allowable_values.map do |value|
39
+ case datatype.to_s
40
+ when /Integer/i
41
+ value.to_i
42
+ when /Float/i
43
+ value.to_f
44
+ else
45
+ value
46
+ end
47
+ end
48
+ end
49
+
50
+ def valid?(value)
51
+ !value || allowable_values.include?(value)
52
+ end
53
+ end
54
+
55
+ # Attribute mapping from ruby-style variable name to JSON key.
56
+ def self.attribute_map
57
+ {
58
+ :'listing_id' => :'listingId',
59
+ :'customer_id' => :'customerId',
60
+ :'operation' => :'operation',
61
+ :'total' => :'total',
62
+ :'from' => :'from',
63
+ :'to' => :'to'
64
+ }
65
+ end
66
+
67
+ # Returns attribute mapping this model knows about
68
+ def self.acceptable_attribute_map
69
+ attribute_map
70
+ end
71
+
72
+ # Returns all the JSON keys this model knows about
73
+ def self.acceptable_attributes
74
+ acceptable_attribute_map.values
75
+ end
76
+
77
+ # Attribute type mapping.
78
+ def self.openapi_types
79
+ {
80
+ :'listing_id' => :'Integer',
81
+ :'customer_id' => :'Integer',
82
+ :'operation' => :'String',
83
+ :'total' => :'Boolean',
84
+ :'from' => :'Date',
85
+ :'to' => :'Date'
86
+ }
87
+ end
88
+
89
+ # List of attributes with nullable: true
90
+ def self.openapi_nullable
91
+ Set.new([
92
+ :'from',
93
+ :'to'
94
+ ])
95
+ end
96
+
97
+ # Initializes the object
98
+ # @param [Hash] attributes Model attributes in the form of hash
99
+ def initialize(attributes = {})
100
+ if (!attributes.is_a?(Hash))
101
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Repull::ChannelSyncFailurePayloadObject` initialize method"
102
+ end
103
+
104
+ # check to see if the attribute exists and convert string to symbol for hash key
105
+ acceptable_attribute_map = self.class.acceptable_attribute_map
106
+ attributes = attributes.each_with_object({}) { |(k, v), h|
107
+ if (!acceptable_attribute_map.key?(k.to_sym))
108
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Repull::ChannelSyncFailurePayloadObject`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
109
+ end
110
+ h[k.to_sym] = v
111
+ }
112
+
113
+ if attributes.key?(:'listing_id')
114
+ self.listing_id = attributes[:'listing_id']
115
+ else
116
+ self.listing_id = nil
117
+ end
118
+
119
+ if attributes.key?(:'customer_id')
120
+ self.customer_id = attributes[:'customer_id']
121
+ else
122
+ self.customer_id = nil
123
+ end
124
+
125
+ if attributes.key?(:'operation')
126
+ self.operation = attributes[:'operation']
127
+ else
128
+ self.operation = nil
129
+ end
130
+
131
+ if attributes.key?(:'total')
132
+ self.total = attributes[:'total']
133
+ else
134
+ self.total = nil
135
+ end
136
+
137
+ if attributes.key?(:'from')
138
+ self.from = attributes[:'from']
139
+ end
140
+
141
+ if attributes.key?(:'to')
142
+ self.to = attributes[:'to']
143
+ end
144
+ end
145
+
146
+ # Show invalid properties with the reasons. Usually used together with valid?
147
+ # @return Array for valid properties with the reasons
148
+ def list_invalid_properties
149
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
150
+ invalid_properties = Array.new
151
+ if @listing_id.nil?
152
+ invalid_properties.push('invalid value for "listing_id", listing_id cannot be nil.')
153
+ end
154
+
155
+ if @customer_id.nil?
156
+ invalid_properties.push('invalid value for "customer_id", customer_id cannot be nil.')
157
+ end
158
+
159
+ if @operation.nil?
160
+ invalid_properties.push('invalid value for "operation", operation cannot be nil.')
161
+ end
162
+
163
+ if @total.nil?
164
+ invalid_properties.push('invalid value for "total", total cannot be nil.')
165
+ end
166
+
167
+ invalid_properties
168
+ end
169
+
170
+ # Check to see if the all the properties in the model are valid
171
+ # @return true if the model is valid
172
+ def valid?
173
+ warn '[DEPRECATED] the `valid?` method is obsolete'
174
+ return false if @listing_id.nil?
175
+ return false if @customer_id.nil?
176
+ return false if @operation.nil?
177
+ operation_validator = EnumAttributeValidator.new('String', ["availability", "rate", "restriction", "content", "reservation"])
178
+ return false unless operation_validator.valid?(@operation)
179
+ return false if @total.nil?
180
+ true
181
+ end
182
+
183
+ # Custom attribute writer method with validation
184
+ # @param [Object] listing_id Value to be assigned
185
+ def listing_id=(listing_id)
186
+ if listing_id.nil?
187
+ fail ArgumentError, 'listing_id cannot be nil'
188
+ end
189
+
190
+ @listing_id = listing_id
191
+ end
192
+
193
+ # Custom attribute writer method with validation
194
+ # @param [Object] customer_id Value to be assigned
195
+ def customer_id=(customer_id)
196
+ if customer_id.nil?
197
+ fail ArgumentError, 'customer_id cannot be nil'
198
+ end
199
+
200
+ @customer_id = customer_id
201
+ end
202
+
203
+ # Custom attribute writer method checking allowed values (enum).
204
+ # @param [Object] operation Object to be assigned
205
+ def operation=(operation)
206
+ validator = EnumAttributeValidator.new('String', ["availability", "rate", "restriction", "content", "reservation"])
207
+ unless validator.valid?(operation)
208
+ fail ArgumentError, "invalid value for \"operation\", must be one of #{validator.allowable_values}."
209
+ end
210
+ @operation = operation
211
+ end
212
+
213
+ # Custom attribute writer method with validation
214
+ # @param [Object] total Value to be assigned
215
+ def total=(total)
216
+ if total.nil?
217
+ fail ArgumentError, 'total cannot be nil'
218
+ end
219
+
220
+ @total = total
221
+ end
222
+
223
+ # Checks equality by comparing each attribute.
224
+ # @param [Object] Object to be compared
225
+ def ==(o)
226
+ return true if self.equal?(o)
227
+ self.class == o.class &&
228
+ listing_id == o.listing_id &&
229
+ customer_id == o.customer_id &&
230
+ operation == o.operation &&
231
+ total == o.total &&
232
+ from == o.from &&
233
+ to == o.to
234
+ end
235
+
236
+ # @see the `==` method
237
+ # @param [Object] Object to be compared
238
+ def eql?(o)
239
+ self == o
240
+ end
241
+
242
+ # Calculates hash code according to all attributes.
243
+ # @return [Integer] Hash code
244
+ def hash
245
+ [listing_id, customer_id, operation, total, from, to].hash
246
+ end
247
+
248
+ # Builds the object from hash
249
+ # @param [Hash] attributes Model attributes in the form of hash
250
+ # @return [Object] Returns the model itself
251
+ def self.build_from_hash(attributes)
252
+ return nil unless attributes.is_a?(Hash)
253
+ attributes = attributes.transform_keys(&:to_sym)
254
+ transformed_hash = {}
255
+ openapi_types.each_pair do |key, type|
256
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
257
+ transformed_hash["#{key}"] = nil
258
+ elsif type =~ /\AArray<(.*)>/i
259
+ # check to ensure the input is an array given that the attribute
260
+ # is documented as an array but the input is not
261
+ if attributes[attribute_map[key]].is_a?(Array)
262
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
263
+ end
264
+ elsif !attributes[attribute_map[key]].nil?
265
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
266
+ end
267
+ end
268
+ new(transformed_hash)
269
+ end
270
+
271
+ # Returns the object in the form of hash
272
+ # @return [Hash] Returns the object in the form of hash
273
+ def to_hash
274
+ hash = {}
275
+ self.class.attribute_map.each_pair do |attr, param|
276
+ value = self.send(attr)
277
+ if value.nil?
278
+ is_nullable = self.class.openapi_nullable.include?(attr)
279
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
280
+ end
281
+
282
+ hash[param] = _to_hash(value)
283
+ end
284
+ hash
285
+ end
286
+
287
+ end
288
+
289
+ end
@@ -0,0 +1,42 @@
1
+ =begin
2
+ #Repull API
3
+
4
+ #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_live_YOUR_API_KEY ``` ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resetsAt` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | unlimited (10 included, then billed per listing) | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
+
6
+ The version of the OpenAPI document: 1.0.0
7
+
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.22.0
10
+
11
+ =end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ module Repull
17
+ class ChargePer
18
+ STAY = "stay".freeze
19
+ NIGHT = "night".freeze
20
+ GUEST = "guest".freeze
21
+ GUEST_NIGHT = "guest_night".freeze
22
+
23
+ def self.all_vars
24
+ @all_vars ||= [STAY, NIGHT, GUEST, GUEST_NIGHT].freeze
25
+ end
26
+
27
+ # Builds the enum from string
28
+ # @param [String] The enum value in the form of the string
29
+ # @return [String] The enum value
30
+ def self.build_from_hash(value)
31
+ new.build_from_hash(value)
32
+ end
33
+
34
+ # Builds the enum from string
35
+ # @param [String] The enum value in the form of the string
36
+ # @return [String] The enum value
37
+ def build_from_hash(value)
38
+ return value if ChargePer.all_vars.include?(value)
39
+ raise "Invalid ENUM value #{value} for class #ChargePer"
40
+ end
41
+ end
42
+ end
@@ -21,7 +21,7 @@ module Repull
21
21
  # The `state` you passed when creating the session.
22
22
  attr_accessor :state
23
23
 
24
- # Channel or PMS: airbnb, booking, booking_extranet, vrbo, plumguide, hostaway, …
24
+ # Channel or PMS: airbnb, booking, booking_extranet, vrbo, hostaway, …
25
25
  attr_accessor :provider
26
26
 
27
27
  # The provider's own account id — Airbnb host id, Booking.com hotel id, Vrbo account id, or the PMS account.
@@ -33,6 +33,9 @@ module Repull
33
33
  # Vrbo only.
34
34
  attr_accessor :access_type
35
35
 
36
+ # Vrbo only. The address the host can add on Vrbo as a secondary email (with message and reservation notifications on) so new bookings, inquiries and messages arrive within a minute instead of at the scheduled check. Ask every host to add it: notifications are how Vrbo updates reach Repull, the scheduled check is the backup. Hosted Connect shows it on its mapping screen; show it in your own app when you create sessions with `mapping: \"api\"`.
37
+ attr_accessor :notification_email
38
+
36
39
  # Vrbo only: where the account import stands.
37
40
  attr_accessor :import
38
41
 
@@ -68,6 +71,7 @@ module Repull
68
71
  :'connected' => :'connected',
69
72
  :'email' => :'email',
70
73
  :'access_type' => :'accessType',
74
+ :'notification_email' => :'notificationEmail',
71
75
  :'import' => :'import'
72
76
  }
73
77
  end
@@ -92,6 +96,7 @@ module Repull
92
96
  :'connected' => :'Boolean',
93
97
  :'email' => :'String',
94
98
  :'access_type' => :'String',
99
+ :'notification_email' => :'String',
95
100
  :'import' => :'VrboImportStatus'
96
101
  }
97
102
  end
@@ -104,6 +109,7 @@ module Repull
104
109
  :'status',
105
110
  :'email',
106
111
  :'access_type',
112
+ :'notification_email',
107
113
  :'import'
108
114
  ])
109
115
  end
@@ -152,6 +158,10 @@ module Repull
152
158
  self.access_type = attributes[:'access_type']
153
159
  end
154
160
 
161
+ if attributes.key?(:'notification_email')
162
+ self.notification_email = attributes[:'notification_email']
163
+ end
164
+
155
165
  if attributes.key?(:'import')
156
166
  self.import = attributes[:'import']
157
167
  end
@@ -196,6 +206,7 @@ module Repull
196
206
  connected == o.connected &&
197
207
  email == o.email &&
198
208
  access_type == o.access_type &&
209
+ notification_email == o.notification_email &&
199
210
  import == o.import
200
211
  end
201
212
 
@@ -208,7 +219,7 @@ module Repull
208
219
  # Calculates hash code according to all attributes.
209
220
  # @return [Integer] Hash code
210
221
  def hash
211
- [external_account_id, name, picture_url, status, connected, email, access_type, import].hash
222
+ [external_account_id, name, picture_url, status, connected, email, access_type, notification_email, import].hash
212
223
  end
213
224
 
214
225
  # Builds the object from hash
@@ -24,6 +24,9 @@ module Repull
24
24
  # Airbnb — how many months of past reservations the first import pulls (1–60). Omit it for the default window. Upcoming stays are always imported. A wider window takes longer to import, because every extra month is more stays to fetch.
25
25
  attr_accessor :reservation_history_months
26
26
 
27
+ # Where the channel's units get linked to listings. `hosted` (default): after a Vrbo or Booking.com Extranet sign-in, Connect shows a mapping step and returns to `redirectUrl` when it's confirmed. `api`: Connect skips that step and finishes right after sign-in. The connection reaches you in the `connect.session.completed` webhook as `account.externalAccountId` (its `connectionId` is null for these two), and as `connectionId` in the popup message and `accountId` on the redirect, all the same id; its handle is `vrbo:{id}` or `booking_extranet:{id}`; you list the units with `GET /v1/connections/{id}/units` and link them with `POST /v1/connections/{id}/mappings`. Nothing is imported until you post the mappings. Other providers ignore it.
28
+ attr_accessor :mapping
29
+
27
30
  # What the connection may do. Airbnb: the OAuth scope tier. Vrbo: `messaging` (or `read_only`) imports bookings and messages and never pushes the calendar; `full_access` also pushes prices and availability. Setting it locks the choice; omit it to let the host choose on the hosted page (default `full_access`).
28
31
  attr_accessor :access_type
29
32
 
@@ -33,7 +36,7 @@ module Repull
33
36
  # Also list PMSes Repull doesn't connect yet (`status: request-only` in `GET /v1/connect/providers?includeRequestOnly=true`), plus an Other PMS card. Picking one opens a form that collects the host's contact and access details for the Repull team and ends with \"A team member will contact you\". No connection is made: the redirect carries `status=requested&provider=<id>`, and no `connect.session.completed` webhook fires. Naming a request-only id in `allowedProviders` offers it without this flag.
34
37
  attr_accessor :include_request_only
35
38
 
36
- # Optional UI language for the hosted Connect pages. Accepts any supported locale code (currently `en`, `fr`). When set it pins the language for the whole flow, overriding the workspace `default_language`. Unknown codes are ignored and the page falls back to the workspace default, then `Accept-Language`, then `en`. The end user can still override per-visit with a `?locale=` query param on the hosted page.
39
+ # Optional UI language for the hosted Connect pages. Accepts any supported locale code (currently `en`, `fr`, `de`, `es`, `it`, `nl`). When set it pins the language for the whole flow, overriding the workspace `default_language`. Unknown codes are ignored and the page falls back to the workspace default, then `Accept-Language`, then `en`. The end user can still override per-visit with a `?locale=` query param on the hosted page.
37
40
  attr_accessor :locale
38
41
 
39
42
  # `migrate` starts a Repull Migrate session: the property manager connects their current PMS (or channel) and their data is copied into a new workspace of theirs, which you read with `X-Workspace-Id`. The hosted pages use migration wording, and after connecting they show the import's progress.
@@ -74,6 +77,7 @@ module Repull
74
77
  :'redirect_url' => :'redirectUrl',
75
78
  :'state' => :'state',
76
79
  :'reservation_history_months' => :'reservationHistoryMonths',
80
+ :'mapping' => :'mapping',
77
81
  :'access_type' => :'accessType',
78
82
  :'allowed_providers' => :'allowedProviders',
79
83
  :'include_request_only' => :'includeRequestOnly',
@@ -101,6 +105,7 @@ module Repull
101
105
  :'redirect_url' => :'String',
102
106
  :'state' => :'String',
103
107
  :'reservation_history_months' => :'Integer',
108
+ :'mapping' => :'String',
104
109
  :'access_type' => :'String',
105
110
  :'allowed_providers' => :'Array<String>',
106
111
  :'include_request_only' => :'Boolean',
@@ -151,6 +156,12 @@ module Repull
151
156
  self.reservation_history_months = attributes[:'reservation_history_months']
152
157
  end
153
158
 
159
+ if attributes.key?(:'mapping')
160
+ self.mapping = attributes[:'mapping']
161
+ else
162
+ self.mapping = 'hosted'
163
+ end
164
+
154
165
  if attributes.key?(:'access_type')
155
166
  self.access_type = attributes[:'access_type']
156
167
  end
@@ -219,6 +230,8 @@ module Repull
219
230
  return false if @redirect_url.nil?
220
231
  return false if !@reservation_history_months.nil? && @reservation_history_months > 60
221
232
  return false if !@reservation_history_months.nil? && @reservation_history_months < 1
233
+ mapping_validator = EnumAttributeValidator.new('String', ["hosted", "api"])
234
+ return false unless mapping_validator.valid?(@mapping)
222
235
  access_type_validator = EnumAttributeValidator.new('String', ["full_access", "messaging", "read_only"])
223
236
  return false unless access_type_validator.valid?(@access_type)
224
237
  purpose_validator = EnumAttributeValidator.new('String', ["connect", "migrate"])
@@ -254,6 +267,16 @@ module Repull
254
267
  @reservation_history_months = reservation_history_months
255
268
  end
256
269
 
270
+ # Custom attribute writer method checking allowed values (enum).
271
+ # @param [Object] mapping Object to be assigned
272
+ def mapping=(mapping)
273
+ validator = EnumAttributeValidator.new('String', ["hosted", "api"])
274
+ unless validator.valid?(mapping)
275
+ fail ArgumentError, "invalid value for \"mapping\", must be one of #{validator.allowable_values}."
276
+ end
277
+ @mapping = mapping
278
+ end
279
+
257
280
  # Custom attribute writer method checking allowed values (enum).
258
281
  # @param [Object] access_type Object to be assigned
259
282
  def access_type=(access_type)
@@ -282,6 +305,7 @@ module Repull
282
305
  redirect_url == o.redirect_url &&
283
306
  state == o.state &&
284
307
  reservation_history_months == o.reservation_history_months &&
308
+ mapping == o.mapping &&
285
309
  access_type == o.access_type &&
286
310
  allowed_providers == o.allowed_providers &&
287
311
  include_request_only == o.include_request_only &&
@@ -301,7 +325,7 @@ module Repull
301
325
  # Calculates hash code according to all attributes.
302
326
  # @return [Integer] Hash code
303
327
  def hash
304
- [redirect_url, state, reservation_history_months, access_type, allowed_providers, include_request_only, locale, purpose, workspace, copy, scope].hash
328
+ [redirect_url, state, reservation_history_months, mapping, access_type, allowed_providers, include_request_only, locale, purpose, workspace, copy, scope].hash
305
329
  end
306
330
 
307
331
  # Builds the object from hash
@@ -19,7 +19,7 @@ module Repull
19
19
  # Airbnb + Booking.com — where to redirect the user after they finish the hosted connect flow.
20
20
  attr_accessor :redirect_url
21
21
 
22
- # Airbnb only — selects the OAuth scope set. 'read_only' grants read-only scopes; 'messaging' grants read scopes plus message read/send but NOT property management, so it can coexist with another app (e.g. an existing PMS) that already holds property management on the same Airbnb account; 'full_access' (default) grants full host scopes including the exclusive property management (only one app per Airbnb account can hold it). The hosted consent screen normally lets the host pick a tier; passing `accessType` explicitly fixes the tier and hides that choice, so the host can only continue with the tier you requested. Omit it to let the host choose.
22
+ # Airbnb only — selects the OAuth scope set. 'read_only' grants read-only scopes; 'messaging' (shown to hosts as \"Messaging & reviews\") grants read scopes plus message read/send and review writes (reply to guest reviews, submit host reviews — Airbnb's reviews_write) but NOT property management, so it can coexist with another app (e.g. an existing PMS) that already holds property management on the same Airbnb account; 'full_access' (default) grants full host scopes including the exclusive property management (only one app per Airbnb account can hold it). The hosted consent screen normally lets the host pick a tier; passing `accessType` explicitly fixes the tier and hides that choice, so the host can only continue with the tier you requested. Omit it to let the host choose.
23
23
  attr_accessor :access_type
24
24
 
25
25
  # Airbnb — how many months of past reservations the first import pulls (1–60). Omit it for the default window. Upcoming stays are always imported. A wider window takes longer to import, because every extra month is more stays to fetch.
@@ -28,13 +28,7 @@ module Repull
28
28
  # Airbnb + Booking.com — your own correlation token, e.g. your user id (at most 500 characters). Echoed on the redirect back (`&state=`) and in the `connect.session.completed` webhook.
29
29
  attr_accessor :state
30
30
 
31
- # Plumguide — client ID.
32
- attr_accessor :client_id
33
-
34
- # Plumguide — client secret.
35
- attr_accessor :client_secret
36
-
37
- # Airbnb only — optional UI language for the hosted Connect pages. Accepts any supported locale code (currently `en`, `fr`); unknown codes are ignored and resolution falls back to the workspace `default_language`, then `Accept-Language`, then `en`.
31
+ # Airbnb and Booking.com — optional UI language for the hosted Connect pages. Accepts any supported locale code (currently `en`, `fr`, `de`, `es`, `it`, `nl`); unknown codes are ignored and resolution falls back to the workspace `default_language`, then `Accept-Language`, then `en`.
38
32
  attr_accessor :locale
39
33
 
40
34
  class EnumAttributeValidator
@@ -66,8 +60,6 @@ module Repull
66
60
  :'access_type' => :'accessType',
67
61
  :'reservation_history_months' => :'reservationHistoryMonths',
68
62
  :'state' => :'state',
69
- :'client_id' => :'clientId',
70
- :'client_secret' => :'clientSecret',
71
63
  :'locale' => :'locale'
72
64
  }
73
65
  end
@@ -89,8 +81,6 @@ module Repull
89
81
  :'access_type' => :'String',
90
82
  :'reservation_history_months' => :'Integer',
91
83
  :'state' => :'String',
92
- :'client_id' => :'String',
93
- :'client_secret' => :'String',
94
84
  :'locale' => :'String'
95
85
  }
96
86
  end
@@ -136,14 +126,6 @@ module Repull
136
126
  self.state = attributes[:'state']
137
127
  end
138
128
 
139
- if attributes.key?(:'client_id')
140
- self.client_id = attributes[:'client_id']
141
- end
142
-
143
- if attributes.key?(:'client_secret')
144
- self.client_secret = attributes[:'client_secret']
145
- end
146
-
147
129
  if attributes.key?(:'locale')
148
130
  self.locale = attributes[:'locale']
149
131
  end
@@ -213,8 +195,6 @@ module Repull
213
195
  access_type == o.access_type &&
214
196
  reservation_history_months == o.reservation_history_months &&
215
197
  state == o.state &&
216
- client_id == o.client_id &&
217
- client_secret == o.client_secret &&
218
198
  locale == o.locale
219
199
  end
220
200
 
@@ -227,7 +207,7 @@ module Repull
227
207
  # Calculates hash code according to all attributes.
228
208
  # @return [Integer] Hash code
229
209
  def hash
230
- [redirect_url, access_type, reservation_history_months, state, client_id, client_secret, locale].hash
210
+ [redirect_url, access_type, reservation_history_months, state, locale].hash
231
211
  end
232
212
 
233
213
  # Builds the object from hash
@@ -14,16 +14,13 @@ require 'date'
14
14
  require 'time'
15
15
 
16
16
  module Repull
17
- class PlumguideListingListResponse < ApiModelBase
17
+ class ImportFromChannex200Response < ApiModelBase
18
18
  attr_accessor :data
19
19
 
20
- attr_accessor :pagination
21
-
22
20
  # Attribute mapping from ruby-style variable name to JSON key.
23
21
  def self.attribute_map
24
22
  {
25
- :'data' => :'data',
26
- :'pagination' => :'pagination'
23
+ :'data' => :'data'
27
24
  }
28
25
  end
29
26
 
@@ -40,8 +37,7 @@ module Repull
40
37
  # Attribute type mapping.
41
38
  def self.openapi_types
42
39
  {
43
- :'data' => :'Array<PlumguideListing>',
44
- :'pagination' => :'Pagination'
40
+ :'data' => :'ImportFromChannex200ResponseData'
45
41
  }
46
42
  end
47
43
 
@@ -55,26 +51,20 @@ module Repull
55
51
  # @param [Hash] attributes Model attributes in the form of hash
56
52
  def initialize(attributes = {})
57
53
  if (!attributes.is_a?(Hash))
58
- fail ArgumentError, "The input argument (attributes) must be a hash in `Repull::PlumguideListingListResponse` initialize method"
54
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Repull::ImportFromChannex200Response` initialize method"
59
55
  end
60
56
 
61
57
  # check to see if the attribute exists and convert string to symbol for hash key
62
58
  acceptable_attribute_map = self.class.acceptable_attribute_map
63
59
  attributes = attributes.each_with_object({}) { |(k, v), h|
64
60
  if (!acceptable_attribute_map.key?(k.to_sym))
65
- fail ArgumentError, "`#{k}` is not a valid attribute in `Repull::PlumguideListingListResponse`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
61
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Repull::ImportFromChannex200Response`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
66
62
  end
67
63
  h[k.to_sym] = v
68
64
  }
69
65
 
70
66
  if attributes.key?(:'data')
71
- if (value = attributes[:'data']).is_a?(Array)
72
- self.data = value
73
- end
74
- end
75
-
76
- if attributes.key?(:'pagination')
77
- self.pagination = attributes[:'pagination']
67
+ self.data = attributes[:'data']
78
68
  end
79
69
  end
80
70
 
@@ -98,8 +88,7 @@ module Repull
98
88
  def ==(o)
99
89
  return true if self.equal?(o)
100
90
  self.class == o.class &&
101
- data == o.data &&
102
- pagination == o.pagination
91
+ data == o.data
103
92
  end
104
93
 
105
94
  # @see the `==` method
@@ -111,7 +100,7 @@ module Repull
111
100
  # Calculates hash code according to all attributes.
112
101
  # @return [Integer] Hash code
113
102
  def hash
114
- [data, pagination].hash
103
+ [data].hash
115
104
  end
116
105
 
117
106
  # Builds the object from hash