repull 0.2.14 → 0.2.15

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 (110) hide show
  1. checksums.yaml +4 -4
  2. data/lib/repull/api/airbnb_api.rb +1265 -125
  3. data/lib/repull/api/availability_api.rb +2 -2
  4. data/lib/repull/api/connect_api.rb +4 -4
  5. data/lib/repull/api/listings_api.rb +97 -13
  6. data/lib/repull/models/airbnb_account_freshness.rb +239 -0
  7. data/lib/repull/models/airbnb_alteration.rb +46 -2
  8. data/lib/repull/models/airbnb_alteration_create_request.rb +264 -0
  9. data/lib/repull/models/airbnb_connection.rb +69 -2
  10. data/lib/repull/models/airbnb_connection_host.rb +1 -1
  11. data/lib/repull/models/airbnb_content_write_response.rb +275 -0
  12. data/lib/repull/models/airbnb_data_freshness.rb +22 -10
  13. data/lib/repull/models/{create_airbnb_alteration_request.rb → airbnb_description_write_request.rb} +44 -47
  14. data/lib/repull/models/airbnb_description_write_request_description.rb +365 -0
  15. data/lib/repull/models/airbnb_listing.rb +12 -1
  16. data/lib/repull/models/airbnb_listing_action200_response.rb +105 -0
  17. data/lib/repull/models/airbnb_listing_action200_response_one_of.rb +157 -0
  18. data/lib/repull/models/airbnb_listing_action200_response_one_of1.rb +175 -0
  19. data/lib/repull/models/airbnb_listing_action_request.rb +2 -2
  20. data/lib/repull/models/airbnb_listing_details_response.rb +284 -0
  21. data/lib/repull/models/airbnb_listing_details_write_request.rb +209 -0
  22. data/lib/repull/models/airbnb_listing_details_write_request_check_in_option.rb +214 -0
  23. data/lib/repull/models/airbnb_listing_details_write_request_quiet_hours_inner.rb +190 -0
  24. data/lib/repull/models/airbnb_listing_lifecycle_response.rb +196 -0
  25. data/lib/repull/models/airbnb_permits_response.rb +163 -0
  26. data/lib/repull/models/airbnb_permits_response_cached_inner.rb +200 -0
  27. data/lib/repull/models/airbnb_permits_write_request.rb +176 -0
  28. data/lib/repull/models/airbnb_permits_write_request_permits_inner.rb +228 -0
  29. data/lib/repull/models/airbnb_permits_write_request_permits_inner_answers_inner.rb +198 -0
  30. data/lib/repull/models/airbnb_photo_position.rb +159 -0
  31. data/lib/repull/models/airbnb_publish_result.rb +263 -0
  32. data/lib/repull/models/airbnb_reservation.rb +23 -1
  33. data/lib/repull/models/airbnb_reservation_list_response.rb +13 -4
  34. data/lib/repull/models/airbnb_review.rb +23 -1
  35. data/lib/repull/models/airbnb_review_list_response.rb +13 -4
  36. data/lib/repull/models/airbnb_safety_disclosure.rb +202 -0
  37. data/lib/repull/models/airbnb_safety_disclosures_response.rb +162 -0
  38. data/lib/repull/models/airbnb_safety_disclosures_write_request.rb +176 -0
  39. data/lib/repull/models/airbnb_thread.rb +23 -1
  40. data/lib/repull/models/airbnb_thread_list_response.rb +13 -4
  41. data/lib/repull/models/airbnb_transaction.rb +23 -1
  42. data/lib/repull/models/create_airbnb_listing_room_request.rb +315 -0
  43. data/lib/repull/models/delete_airbnb_listing_photo200_response.rb +14 -4
  44. data/lib/repull/models/delete_airbnb_listing_room200_response.rb +157 -0
  45. data/lib/repull/models/error_error.rb +31 -1
  46. data/lib/repull/models/get_airbnb_booking_settings200_response.rb +190 -0
  47. data/lib/repull/models/get_airbnb_booking_settings200_response_data.rb +246 -0
  48. data/lib/repull/models/get_airbnb_booking_settings200_response_data_advance_notice.rb +172 -0
  49. data/lib/repull/models/get_airbnb_booking_settings200_response_data_booking_window.rb +160 -0
  50. data/lib/repull/models/get_airbnb_booking_settings200_response_data_cancellation.rb +203 -0
  51. data/lib/repull/models/get_airbnb_booking_settings200_response_data_cancellation_non_refundable.rb +218 -0
  52. data/lib/repull/models/get_airbnb_booking_settings200_response_data_check_in.rb +159 -0
  53. data/lib/repull/models/get_airbnb_booking_settings200_response_data_check_in_start.rb +104 -0
  54. data/lib/repull/models/get_airbnb_booking_settings200_response_data_check_out.rb +172 -0
  55. data/lib/repull/models/get_airbnb_booking_settings200_response_data_instant_book.rb +206 -0
  56. data/lib/repull/models/get_airbnb_booking_settings200_response_data_preparation_time.rb +173 -0
  57. data/lib/repull/models/get_airbnb_listing_details200_response.rb +192 -0
  58. data/lib/repull/models/list_airbnb_listing_permits200_response.rb +190 -0
  59. data/lib/repull/models/list_airbnb_listing_safety_disclosures200_response.rb +190 -0
  60. data/lib/repull/models/listing.rb +2 -1
  61. data/lib/repull/models/listing_content.rb +13 -2
  62. data/lib/repull/models/listing_content_update_request.rb +21 -2
  63. data/lib/repull/models/listing_content_update_request_details.rb +206 -0
  64. data/lib/repull/models/listing_content_update_request_policies.rb +95 -5
  65. data/lib/repull/models/listing_content_update_response.rb +1 -1
  66. data/lib/repull/models/listing_publish_airbnb_response.rb +165 -0
  67. data/lib/repull/models/listing_pull_airbnb_request.rb +149 -0
  68. data/lib/repull/models/listing_pull_response.rb +231 -0
  69. data/lib/repull/models/publish_section_error.rb +232 -0
  70. data/lib/repull/models/reorder_airbnb_listing_photos200_response.rb +191 -0
  71. data/lib/repull/models/reorder_airbnb_listing_photos200_response_data.rb +172 -0
  72. data/lib/repull/models/reorder_airbnb_listing_photos_request.rb +185 -0
  73. data/lib/repull/models/reservation.rb +23 -1
  74. data/lib/repull/models/reservation_webhook_object.rb +38 -5
  75. data/lib/repull/models/set_airbnb_listing_cover_photo200_response.rb +191 -0
  76. data/lib/repull/models/set_airbnb_listing_cover_photo200_response_data.rb +171 -0
  77. data/lib/repull/models/set_airbnb_listing_cover_photo_request.rb +165 -0
  78. data/lib/repull/models/update_airbnb_booking_settings200_response.rb +164 -0
  79. data/lib/repull/models/update_airbnb_booking_settings200_response_data.rb +205 -0
  80. data/lib/repull/models/update_airbnb_booking_settings_request.rb +202 -0
  81. data/lib/repull/models/update_airbnb_booking_settings_request_advance_notice.rb +183 -0
  82. data/lib/repull/models/update_airbnb_booking_settings_request_booking_window.rb +183 -0
  83. data/lib/repull/models/update_airbnb_booking_settings_request_cancellation.rb +201 -0
  84. data/lib/repull/models/update_airbnb_booking_settings_request_cancellation_non_refundable.rb +183 -0
  85. data/lib/repull/models/update_airbnb_booking_settings_request_check_in.rb +159 -0
  86. data/lib/repull/models/update_airbnb_booking_settings_request_check_out.rb +182 -0
  87. data/lib/repull/models/update_airbnb_booking_settings_request_instant_book.rb +203 -0
  88. data/lib/repull/models/update_airbnb_booking_settings_request_preparation_time.rb +182 -0
  89. data/lib/repull/models/update_airbnb_listing_amenities200_response.rb +191 -0
  90. data/lib/repull/models/update_airbnb_listing_amenities200_response_data.rb +158 -0
  91. data/lib/repull/models/update_airbnb_listing_amenities_request.rb +199 -0
  92. data/lib/repull/models/update_airbnb_listing_amenities_request_accessibility_amenities_inner.rb +246 -0
  93. data/lib/repull/models/update_airbnb_listing_amenities_request_amenities_inner.rb +218 -0
  94. data/lib/repull/models/update_airbnb_listing_permits200_response.rb +168 -0
  95. data/lib/repull/models/update_airbnb_listing_photo200_response.rb +194 -0
  96. data/lib/repull/models/update_airbnb_listing_photo_request.rb +242 -0
  97. data/lib/repull/models/update_airbnb_listing_room200_response.rb +194 -0
  98. data/lib/repull/models/update_airbnb_listing_room_request.rb +293 -0
  99. data/lib/repull/models/update_airbnb_listing_room_request_beds_inner.rb +209 -0
  100. data/lib/repull/models/update_airbnb_listing_room_request_room_amenities_inner.rb +182 -0
  101. data/lib/repull/models/update_airbnb_listing_room_request_room_amenities_inner_value.rb +105 -0
  102. data/lib/repull/models/update_airbnb_listing_safety_disclosures200_response.rb +180 -0
  103. data/lib/repull/models/upload_airbnb_listing_photos_request.rb +184 -0
  104. data/lib/repull/models/upload_airbnb_listing_photos_request_photos_inner.rb +305 -0
  105. data/lib/repull/models/upload_airbnb_listing_photos_request_photos_inner_listing_id.rb +105 -0
  106. data/lib/repull/version.rb +1 -1
  107. data/lib/repull.rb +78 -1
  108. data/openapi/v1.json +4523 -1282
  109. data/scripts/regen.sh +1 -1
  110. metadata +80 -3
@@ -14,7 +14,7 @@ require 'date'
14
14
  require 'time'
15
15
 
16
16
  module Repull
17
- # An Airbnb reservation alteration request (date change, guest-count change, or price change), mirrored locally in `reservation_alterations`. Fields prefixed `original*` describe the reservation as it stands today; `new*` fields describe the proposed change. Compare them to render a diff and decide whether to accept (`POST .../{id}/accept`) or decline (`POST .../{id}/decline`).
17
+ # An Airbnb reservation alteration request (date change, guest-count change, price change, or a move to another listing), mirrored locally in `reservation_alterations`. Fields prefixed `original*` describe the reservation as it stands today; `new*` fields describe the proposed change. Compare them to render a diff and decide whether to accept (`POST .../{id}/accept`) or decline (`POST .../{id}/decline`) — or, for one you proposed yourself, to withdraw it (`POST .../{id}/cancel`).
18
18
  class AirbnbAlteration < ApiModelBase
19
19
  # Internal Repull mirror-row id (not the Airbnb alteration id — use `alterationId` for the `{id}` path param on the get / accept / decline routes).
20
20
  attr_accessor :id
@@ -25,6 +25,12 @@ module Repull
25
25
  # Repull reservation id the alteration belongs to.
26
26
  attr_accessor :reservation_id
27
27
 
28
+ # Which connected Airbnb account this row belongs to — the Airbnb host id, as a string (they exceed 2^53). The same value `?account_id=` accepts and `GET /v1/connect/airbnb` returns as `accounts[].externalAccountId`.
29
+ attr_accessor :account_id
30
+
31
+ # Display name of that connected Airbnb account.
32
+ attr_accessor :account_name
33
+
28
34
  # Always `airbnb` on this surface.
29
35
  attr_accessor :platform
30
36
 
@@ -64,6 +70,12 @@ module Repull
64
70
  # Proposed new total price (decimal string).
65
71
  attr_accessor :new_total_price
66
72
 
73
+ # Repull listing id the alteration moves the reservation to — a **listing transfer**. `null` when the alteration does not change the listing, which is the usual case. Compare it with the reservation's current `listingId` to render the move. Like every id on this API it is a string.
74
+ attr_accessor :new_listing_id
75
+
76
+ # The same transfer target as Airbnb spells it (the Airbnb listing id). Present alongside `newListingId`; it is also the only one of the two that is set when the destination listing has not been imported into this workspace.
77
+ attr_accessor :new_airbnb_listing_id
78
+
67
79
  # When the alteration was first mirrored locally.
68
80
  attr_accessor :created_at
69
81
 
@@ -76,6 +88,8 @@ module Repull
76
88
  :'id' => :'id',
77
89
  :'alteration_id' => :'alterationId',
78
90
  :'reservation_id' => :'reservationId',
91
+ :'account_id' => :'accountId',
92
+ :'account_name' => :'accountName',
79
93
  :'platform' => :'platform',
80
94
  :'status' => :'status',
81
95
  :'initiator' => :'initiator',
@@ -89,6 +103,8 @@ module Repull
89
103
  :'new_check_out' => :'newCheckOut',
90
104
  :'new_guest_count' => :'newGuestCount',
91
105
  :'new_total_price' => :'newTotalPrice',
106
+ :'new_listing_id' => :'newListingId',
107
+ :'new_airbnb_listing_id' => :'newAirbnbListingId',
92
108
  :'created_at' => :'createdAt',
93
109
  :'updated_at' => :'updatedAt'
94
110
  }
@@ -110,6 +126,8 @@ module Repull
110
126
  :'id' => :'String',
111
127
  :'alteration_id' => :'String',
112
128
  :'reservation_id' => :'String',
129
+ :'account_id' => :'String',
130
+ :'account_name' => :'String',
113
131
  :'platform' => :'String',
114
132
  :'status' => :'String',
115
133
  :'initiator' => :'String',
@@ -123,6 +141,8 @@ module Repull
123
141
  :'new_check_out' => :'Time',
124
142
  :'new_guest_count' => :'Integer',
125
143
  :'new_total_price' => :'String',
144
+ :'new_listing_id' => :'String',
145
+ :'new_airbnb_listing_id' => :'String',
126
146
  :'created_at' => :'Time',
127
147
  :'updated_at' => :'Time'
128
148
  }
@@ -133,6 +153,8 @@ module Repull
133
153
  Set.new([
134
154
  :'alteration_id',
135
155
  :'reservation_id',
156
+ :'account_id',
157
+ :'account_name',
136
158
  :'status',
137
159
  :'initiator',
138
160
  :'reason',
@@ -145,6 +167,8 @@ module Repull
145
167
  :'new_check_out',
146
168
  :'new_guest_count',
147
169
  :'new_total_price',
170
+ :'new_listing_id',
171
+ :'new_airbnb_listing_id',
148
172
  :'created_at',
149
173
  :'updated_at'
150
174
  ])
@@ -178,6 +202,14 @@ module Repull
178
202
  self.reservation_id = attributes[:'reservation_id']
179
203
  end
180
204
 
205
+ if attributes.key?(:'account_id')
206
+ self.account_id = attributes[:'account_id']
207
+ end
208
+
209
+ if attributes.key?(:'account_name')
210
+ self.account_name = attributes[:'account_name']
211
+ end
212
+
181
213
  if attributes.key?(:'platform')
182
214
  self.platform = attributes[:'platform']
183
215
  end
@@ -230,6 +262,14 @@ module Repull
230
262
  self.new_total_price = attributes[:'new_total_price']
231
263
  end
232
264
 
265
+ if attributes.key?(:'new_listing_id')
266
+ self.new_listing_id = attributes[:'new_listing_id']
267
+ end
268
+
269
+ if attributes.key?(:'new_airbnb_listing_id')
270
+ self.new_airbnb_listing_id = attributes[:'new_airbnb_listing_id']
271
+ end
272
+
233
273
  if attributes.key?(:'created_at')
234
274
  self.created_at = attributes[:'created_at']
235
275
  end
@@ -262,6 +302,8 @@ module Repull
262
302
  id == o.id &&
263
303
  alteration_id == o.alteration_id &&
264
304
  reservation_id == o.reservation_id &&
305
+ account_id == o.account_id &&
306
+ account_name == o.account_name &&
265
307
  platform == o.platform &&
266
308
  status == o.status &&
267
309
  initiator == o.initiator &&
@@ -275,6 +317,8 @@ module Repull
275
317
  new_check_out == o.new_check_out &&
276
318
  new_guest_count == o.new_guest_count &&
277
319
  new_total_price == o.new_total_price &&
320
+ new_listing_id == o.new_listing_id &&
321
+ new_airbnb_listing_id == o.new_airbnb_listing_id &&
278
322
  created_at == o.created_at &&
279
323
  updated_at == o.updated_at
280
324
  end
@@ -288,7 +332,7 @@ module Repull
288
332
  # Calculates hash code according to all attributes.
289
333
  # @return [Integer] Hash code
290
334
  def hash
291
- [id, alteration_id, reservation_id, platform, status, initiator, reason, notes, original_check_in, original_check_out, original_guest_count, original_total_price, new_check_in, new_check_out, new_guest_count, new_total_price, created_at, updated_at].hash
335
+ [id, alteration_id, reservation_id, account_id, account_name, platform, status, initiator, reason, notes, original_check_in, original_check_out, original_guest_count, original_total_price, new_check_in, new_check_out, new_guest_count, new_total_price, new_listing_id, new_airbnb_listing_id, created_at, updated_at].hash
292
336
  end
293
337
 
294
338
  # Builds the object from hash
@@ -0,0 +1,264 @@
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` | 50 | | `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
+ Contact: ivan@vanio.ai
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
+ # A proposed change to an existing Airbnb reservation. `confirmation_code` names the reservation; at least one of `check_in`, `check_out`, `number_of_guests`, `total_price` or `listing_id` must be sent with it, because an alteration that changes nothing is not something Airbnb can act on (it is refused with `422 invalid_params`). Unknown fields are refused rather than silently dropped. The older connector-native spellings (`start_date`, `end_date`, `total_price_override`, and an Airbnb guest-details object in place of `number_of_guests`) are still accepted for existing integrations; send the canonical names above in new code, and never a canonical field and its older spelling with different values.
18
+ class AirbnbAlterationCreateRequest < ApiModelBase
19
+ # Airbnb confirmation code of the reservation to alter. `GET /v1/channels/airbnb/reservations` lists them.
20
+ attr_accessor :confirmation_code
21
+
22
+ # New check-in date, `YYYY-MM-DD`.
23
+ attr_accessor :check_in
24
+
25
+ # New check-out date, `YYYY-MM-DD`. Must be after `check_in` when both are sent.
26
+ attr_accessor :check_out
27
+
28
+ # New guest count for the stay.
29
+ attr_accessor :number_of_guests
30
+
31
+ # New total for the whole stay, in the listing currency. Sent to Airbnb as the alteration's price override.
32
+ attr_accessor :total_price
33
+
34
+ # Move the reservation to this listing — a **listing transfer**. This is the **Repull** listing id (the `id` from `GET /v1/properties`), the same id every other Airbnb channel route takes; Repull verifies you own it, that it is active and connected to Airbnb, and translates it to the Airbnb listing id before sending it. Airbnb decides whether to honour the move.
35
+ attr_accessor :listing_id
36
+
37
+ # The transfer target as the **Airbnb** listing id, for callers who hold that instead of the Repull id. Prefer `listing_id`. Sending both is allowed only when they name the same listing.
38
+ attr_accessor :airbnb_listing_id
39
+
40
+ # Attribute mapping from ruby-style variable name to JSON key.
41
+ def self.attribute_map
42
+ {
43
+ :'confirmation_code' => :'confirmation_code',
44
+ :'check_in' => :'check_in',
45
+ :'check_out' => :'check_out',
46
+ :'number_of_guests' => :'number_of_guests',
47
+ :'total_price' => :'total_price',
48
+ :'listing_id' => :'listing_id',
49
+ :'airbnb_listing_id' => :'airbnb_listing_id'
50
+ }
51
+ end
52
+
53
+ # Returns attribute mapping this model knows about
54
+ def self.acceptable_attribute_map
55
+ attribute_map
56
+ end
57
+
58
+ # Returns all the JSON keys this model knows about
59
+ def self.acceptable_attributes
60
+ acceptable_attribute_map.values
61
+ end
62
+
63
+ # Attribute type mapping.
64
+ def self.openapi_types
65
+ {
66
+ :'confirmation_code' => :'String',
67
+ :'check_in' => :'Date',
68
+ :'check_out' => :'Date',
69
+ :'number_of_guests' => :'Integer',
70
+ :'total_price' => :'Float',
71
+ :'listing_id' => :'Integer',
72
+ :'airbnb_listing_id' => :'String'
73
+ }
74
+ end
75
+
76
+ # List of attributes with nullable: true
77
+ def self.openapi_nullable
78
+ Set.new([
79
+ ])
80
+ end
81
+
82
+ # Initializes the object
83
+ # @param [Hash] attributes Model attributes in the form of hash
84
+ def initialize(attributes = {})
85
+ if (!attributes.is_a?(Hash))
86
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Repull::AirbnbAlterationCreateRequest` initialize method"
87
+ end
88
+
89
+ # check to see if the attribute exists and convert string to symbol for hash key
90
+ acceptable_attribute_map = self.class.acceptable_attribute_map
91
+ attributes = attributes.each_with_object({}) { |(k, v), h|
92
+ if (!acceptable_attribute_map.key?(k.to_sym))
93
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Repull::AirbnbAlterationCreateRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
94
+ end
95
+ h[k.to_sym] = v
96
+ }
97
+
98
+ if attributes.key?(:'confirmation_code')
99
+ self.confirmation_code = attributes[:'confirmation_code']
100
+ else
101
+ self.confirmation_code = nil
102
+ end
103
+
104
+ if attributes.key?(:'check_in')
105
+ self.check_in = attributes[:'check_in']
106
+ end
107
+
108
+ if attributes.key?(:'check_out')
109
+ self.check_out = attributes[:'check_out']
110
+ end
111
+
112
+ if attributes.key?(:'number_of_guests')
113
+ self.number_of_guests = attributes[:'number_of_guests']
114
+ end
115
+
116
+ if attributes.key?(:'total_price')
117
+ self.total_price = attributes[:'total_price']
118
+ end
119
+
120
+ if attributes.key?(:'listing_id')
121
+ self.listing_id = attributes[:'listing_id']
122
+ end
123
+
124
+ if attributes.key?(:'airbnb_listing_id')
125
+ self.airbnb_listing_id = attributes[:'airbnb_listing_id']
126
+ end
127
+ end
128
+
129
+ # Show invalid properties with the reasons. Usually used together with valid?
130
+ # @return Array for valid properties with the reasons
131
+ def list_invalid_properties
132
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
133
+ invalid_properties = Array.new
134
+ if @confirmation_code.nil?
135
+ invalid_properties.push('invalid value for "confirmation_code", confirmation_code cannot be nil.')
136
+ end
137
+
138
+ if !@number_of_guests.nil? && @number_of_guests < 1
139
+ invalid_properties.push('invalid value for "number_of_guests", must be greater than or equal to 1.')
140
+ end
141
+
142
+ if !@total_price.nil? && @total_price < 0
143
+ invalid_properties.push('invalid value for "total_price", must be greater than or equal to 0.')
144
+ end
145
+
146
+ invalid_properties
147
+ end
148
+
149
+ # Check to see if the all the properties in the model are valid
150
+ # @return true if the model is valid
151
+ def valid?
152
+ warn '[DEPRECATED] the `valid?` method is obsolete'
153
+ return false if @confirmation_code.nil?
154
+ return false if !@number_of_guests.nil? && @number_of_guests < 1
155
+ return false if !@total_price.nil? && @total_price < 0
156
+ true
157
+ end
158
+
159
+ # Custom attribute writer method with validation
160
+ # @param [Object] confirmation_code Value to be assigned
161
+ def confirmation_code=(confirmation_code)
162
+ if confirmation_code.nil?
163
+ fail ArgumentError, 'confirmation_code cannot be nil'
164
+ end
165
+
166
+ @confirmation_code = confirmation_code
167
+ end
168
+
169
+ # Custom attribute writer method with validation
170
+ # @param [Object] number_of_guests Value to be assigned
171
+ def number_of_guests=(number_of_guests)
172
+ if number_of_guests.nil?
173
+ fail ArgumentError, 'number_of_guests cannot be nil'
174
+ end
175
+
176
+ if number_of_guests < 1
177
+ fail ArgumentError, 'invalid value for "number_of_guests", must be greater than or equal to 1.'
178
+ end
179
+
180
+ @number_of_guests = number_of_guests
181
+ end
182
+
183
+ # Custom attribute writer method with validation
184
+ # @param [Object] total_price Value to be assigned
185
+ def total_price=(total_price)
186
+ if total_price.nil?
187
+ fail ArgumentError, 'total_price cannot be nil'
188
+ end
189
+
190
+ if total_price < 0
191
+ fail ArgumentError, 'invalid value for "total_price", must be greater than or equal to 0.'
192
+ end
193
+
194
+ @total_price = total_price
195
+ end
196
+
197
+ # Checks equality by comparing each attribute.
198
+ # @param [Object] Object to be compared
199
+ def ==(o)
200
+ return true if self.equal?(o)
201
+ self.class == o.class &&
202
+ confirmation_code == o.confirmation_code &&
203
+ check_in == o.check_in &&
204
+ check_out == o.check_out &&
205
+ number_of_guests == o.number_of_guests &&
206
+ total_price == o.total_price &&
207
+ listing_id == o.listing_id &&
208
+ airbnb_listing_id == o.airbnb_listing_id
209
+ end
210
+
211
+ # @see the `==` method
212
+ # @param [Object] Object to be compared
213
+ def eql?(o)
214
+ self == o
215
+ end
216
+
217
+ # Calculates hash code according to all attributes.
218
+ # @return [Integer] Hash code
219
+ def hash
220
+ [confirmation_code, check_in, check_out, number_of_guests, total_price, listing_id, airbnb_listing_id].hash
221
+ end
222
+
223
+ # Builds the object from hash
224
+ # @param [Hash] attributes Model attributes in the form of hash
225
+ # @return [Object] Returns the model itself
226
+ def self.build_from_hash(attributes)
227
+ return nil unless attributes.is_a?(Hash)
228
+ attributes = attributes.transform_keys(&:to_sym)
229
+ transformed_hash = {}
230
+ openapi_types.each_pair do |key, type|
231
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
232
+ transformed_hash["#{key}"] = nil
233
+ elsif type =~ /\AArray<(.*)>/i
234
+ # check to ensure the input is an array given that the attribute
235
+ # is documented as an array but the input is not
236
+ if attributes[attribute_map[key]].is_a?(Array)
237
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
238
+ end
239
+ elsif !attributes[attribute_map[key]].nil?
240
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
241
+ end
242
+ end
243
+ new(transformed_hash)
244
+ end
245
+
246
+ # Returns the object in the form of hash
247
+ # @return [Hash] Returns the object in the form of hash
248
+ def to_hash
249
+ hash = {}
250
+ self.class.attribute_map.each_pair do |attr, param|
251
+ value = self.send(attr)
252
+ if value.nil?
253
+ is_nullable = self.class.openapi_nullable.include?(attr)
254
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
255
+ end
256
+
257
+ hash[param] = _to_hash(value)
258
+ end
259
+ hash
260
+ end
261
+
262
+ end
263
+
264
+ end
@@ -22,9 +22,18 @@ module Repull
22
22
  # Airbnb-side listing id
23
23
  attr_accessor :airbnb_id
24
24
 
25
- # Airbnb host user id
25
+ # Which connected Airbnb account this row belongs to — the Airbnb host id, as a string (they exceed 2^53). The same value `?account_id=` accepts and `GET /v1/connect/airbnb` returns as `accounts[].externalAccountId`.
26
+ attr_accessor :account_id
27
+
28
+ # Display name of that connected Airbnb account.
29
+ attr_accessor :account_name
30
+
31
+ # Alias of `accountId`, kept for compatibility — same Airbnb host id, same string.
26
32
  attr_accessor :host_id
27
33
 
34
+ # Alias of `accountName`, kept for compatibility.
35
+ attr_accessor :host_name
36
+
28
37
  attr_accessor :active
29
38
 
30
39
  attr_accessor :sync_enabled
@@ -34,8 +43,17 @@ module Repull
34
43
  # Decimal markup (e.g. \"1.10\" for +10%).
35
44
  attr_accessor :markup
36
45
 
46
+ # Airbnb's own API sync decision for THIS listing, as Airbnb reports it. Airbnb authorises sync one listing at a time, so a connected account can still contain listings it will not accept writes for. - `sync_all` — Repull manages content, rates and availability. - `sync_rates_and_availability` — Repull manages rates and availability; listing content is managed by the host on Airbnb. - `none` — the listing is **not** connected to Repull on Airbnb's side. Every write to it is refused with `403 listing_not_api_connected`; reconnecting the Airbnb account does not change this, the host must switch the listing on in Airbnb. `null` when the listing has not synced yet. Not to be confused with `syncEnabled`, which is a Repull-side flag and says nothing about what Airbnb accepts.
47
+ attr_accessor :sync_category
48
+
49
+ # Whether Repull will send a write for this listing to Airbnb. `false` exactly when `syncCategory` is `none` — such a write is refused with `403 listing_not_api_connected` before anything reaches Airbnb. Check this before a portfolio-wide push instead of discovering it one 403 at a time.
50
+ attr_accessor :writable
51
+
37
52
  attr_accessor :created_at
38
53
 
54
+ # Fields Airbnb will NOT let you change on this listing — `property_type_category`, `name`, `check_in_option`, `summary`, `space`, individual amenities, … Airbnb does not refuse a write to a locked field: it returns 200, reports the field as locked, and applies nothing. Check this before a content write; `[]` means nothing is known to be locked. Recorded at sync time, so a lock added on Airbnb since the last sync will show up on the write instead (as `blockedFields` in the response).
55
+ attr_accessor :locked_fields
56
+
39
57
  # Present only when `?include=amenities` is passed. Sourced from the local `listings_airbnb_amenities` cache (populated by the Airbnb sync worker). Returns `null` when the cache is empty for this connection — see the top-level `dataFreshness` envelope to disambiguate \"never synced\" vs \"host disconnected\" vs \"fresh and genuinely empty\".
40
58
  attr_accessor :amenities
41
59
 
@@ -47,12 +65,18 @@ module Repull
47
65
  {
48
66
  :'id' => :'id',
49
67
  :'airbnb_id' => :'airbnbId',
68
+ :'account_id' => :'accountId',
69
+ :'account_name' => :'accountName',
50
70
  :'host_id' => :'hostId',
71
+ :'host_name' => :'hostName',
51
72
  :'active' => :'active',
52
73
  :'sync_enabled' => :'syncEnabled',
53
74
  :'primary' => :'primary',
54
75
  :'markup' => :'markup',
76
+ :'sync_category' => :'syncCategory',
77
+ :'writable' => :'writable',
55
78
  :'created_at' => :'createdAt',
79
+ :'locked_fields' => :'lockedFields',
56
80
  :'amenities' => :'amenities',
57
81
  :'accessibility_amenities' => :'accessibility_amenities'
58
82
  }
@@ -73,12 +97,18 @@ module Repull
73
97
  {
74
98
  :'id' => :'String',
75
99
  :'airbnb_id' => :'String',
100
+ :'account_id' => :'String',
101
+ :'account_name' => :'String',
76
102
  :'host_id' => :'String',
103
+ :'host_name' => :'String',
77
104
  :'active' => :'Boolean',
78
105
  :'sync_enabled' => :'Boolean',
79
106
  :'primary' => :'Boolean',
80
107
  :'markup' => :'String',
108
+ :'sync_category' => :'String',
109
+ :'writable' => :'Boolean',
81
110
  :'created_at' => :'Time',
111
+ :'locked_fields' => :'Array<String>',
82
112
  :'amenities' => :'Array<AirbnbConnectionAmenitiesInner>',
83
113
  :'accessibility_amenities' => :'Array<AirbnbConnectionAccessibilityAmenitiesInner>'
84
114
  }
@@ -87,7 +117,12 @@ module Repull
87
117
  # List of attributes with nullable: true
88
118
  def self.openapi_nullable
89
119
  Set.new([
120
+ :'account_id',
121
+ :'account_name',
122
+ :'host_id',
123
+ :'host_name',
90
124
  :'markup',
125
+ :'sync_category',
91
126
  :'amenities',
92
127
  :'accessibility_amenities'
93
128
  ])
@@ -117,10 +152,22 @@ module Repull
117
152
  self.airbnb_id = attributes[:'airbnb_id']
118
153
  end
119
154
 
155
+ if attributes.key?(:'account_id')
156
+ self.account_id = attributes[:'account_id']
157
+ end
158
+
159
+ if attributes.key?(:'account_name')
160
+ self.account_name = attributes[:'account_name']
161
+ end
162
+
120
163
  if attributes.key?(:'host_id')
121
164
  self.host_id = attributes[:'host_id']
122
165
  end
123
166
 
167
+ if attributes.key?(:'host_name')
168
+ self.host_name = attributes[:'host_name']
169
+ end
170
+
124
171
  if attributes.key?(:'active')
125
172
  self.active = attributes[:'active']
126
173
  end
@@ -137,10 +184,24 @@ module Repull
137
184
  self.markup = attributes[:'markup']
138
185
  end
139
186
 
187
+ if attributes.key?(:'sync_category')
188
+ self.sync_category = attributes[:'sync_category']
189
+ end
190
+
191
+ if attributes.key?(:'writable')
192
+ self.writable = attributes[:'writable']
193
+ end
194
+
140
195
  if attributes.key?(:'created_at')
141
196
  self.created_at = attributes[:'created_at']
142
197
  end
143
198
 
199
+ if attributes.key?(:'locked_fields')
200
+ if (value = attributes[:'locked_fields']).is_a?(Array)
201
+ self.locked_fields = value
202
+ end
203
+ end
204
+
144
205
  if attributes.key?(:'amenities')
145
206
  if (value = attributes[:'amenities']).is_a?(Array)
146
207
  self.amenities = value
@@ -176,12 +237,18 @@ module Repull
176
237
  self.class == o.class &&
177
238
  id == o.id &&
178
239
  airbnb_id == o.airbnb_id &&
240
+ account_id == o.account_id &&
241
+ account_name == o.account_name &&
179
242
  host_id == o.host_id &&
243
+ host_name == o.host_name &&
180
244
  active == o.active &&
181
245
  sync_enabled == o.sync_enabled &&
182
246
  primary == o.primary &&
183
247
  markup == o.markup &&
248
+ sync_category == o.sync_category &&
249
+ writable == o.writable &&
184
250
  created_at == o.created_at &&
251
+ locked_fields == o.locked_fields &&
185
252
  amenities == o.amenities &&
186
253
  accessibility_amenities == o.accessibility_amenities
187
254
  end
@@ -195,7 +262,7 @@ module Repull
195
262
  # Calculates hash code according to all attributes.
196
263
  # @return [Integer] Hash code
197
264
  def hash
198
- [id, airbnb_id, host_id, active, sync_enabled, primary, markup, created_at, amenities, accessibility_amenities].hash
265
+ [id, airbnb_id, account_id, account_name, host_id, host_name, active, sync_enabled, primary, markup, sync_category, writable, created_at, locked_fields, amenities, accessibility_amenities].hash
199
266
  end
200
267
 
201
268
  # Builds the object from hash
@@ -24,7 +24,7 @@ module Repull
24
24
 
25
25
  attr_accessor :is_connected
26
26
 
27
- # When the host record was last touched (token refresh / activation / restriction). Closest available proxy for \"last successful sync\".
27
+ # When this account last COMPLETED an Airbnb import. `null` when it never has. A run that failed or was rate-limited does not move it, and neither does anything other than a sync.
28
28
  attr_accessor :last_synced_at
29
29
 
30
30
  # When the host was last marked inactive. Null on currently-connected hosts.