repull 0.2.33 → 0.2.34

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/lib/repull/api/promotions_api.rb +574 -0
  3. data/lib/repull/models/listing_updated_payload.rb +2 -2
  4. data/lib/repull/models/promotion.rb +344 -0
  5. data/lib/repull/models/promotion_applies_to.rb +161 -0
  6. data/lib/repull/models/promotion_bulk_request.rb +236 -0
  7. data/lib/repull/models/promotion_bulk_response.rb +158 -0
  8. data/lib/repull/models/promotion_bulk_response_data_inner.rb +174 -0
  9. data/lib/repull/models/promotion_bulk_response_data_inner_error.rb +165 -0
  10. data/lib/repull/models/promotion_bulk_response_summary.rb +156 -0
  11. data/lib/repull/models/promotion_catalog.rb +158 -0
  12. data/lib/repull/models/promotion_catalog_channels_inner.rb +222 -0
  13. data/lib/repull/models/promotion_catalog_entry.rb +265 -0
  14. data/lib/repull/models/promotion_catalog_field.rb +205 -0
  15. data/lib/repull/models/promotion_catalog_field_options_inner.rb +156 -0
  16. data/lib/repull/models/promotion_catalog_response.rb +147 -0
  17. data/lib/repull/models/promotion_create_request.rb +258 -0
  18. data/lib/repull/models/promotion_delete_response.rb +147 -0
  19. data/lib/repull/models/promotion_delete_response_data.rb +156 -0
  20. data/lib/repull/models/promotion_discount.rb +191 -0
  21. data/lib/repull/models/promotion_input.rb +241 -0
  22. data/lib/repull/models/promotion_list_response.rb +170 -0
  23. data/lib/repull/models/promotion_refresh_response.rb +170 -0
  24. data/lib/repull/models/promotion_response.rb +147 -0
  25. data/lib/repull/models/promotion_rules.rb +290 -0
  26. data/lib/repull/models/promotion_rules_blackout_dates_quota.rb +156 -0
  27. data/lib/repull/models/promotion_rules_booking_window.rb +230 -0
  28. data/lib/repull/models/promotion_rules_last_minute.rb +218 -0
  29. data/lib/repull/models/promotion_rules_stay_window.rb +211 -0
  30. data/lib/repull/models/promotion_type.rb +47 -0
  31. data/lib/repull/models/promotion_update_request.rb +175 -0
  32. data/lib/repull/models/promotion_usage.rb +193 -0
  33. data/lib/repull/models/promotion_usage_revenue.rb +156 -0
  34. data/lib/repull/models/reservation_money_line.rb +14 -4
  35. data/lib/repull/version.rb +1 -1
  36. data/lib/repull.rb +31 -0
  37. data/openapi/v1.json +1061 -2
  38. data/scripts/regen.sh +1 -1
  39. metadata +32 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dcd09671d587b3a558ca474b37832304e42231f117d9b9e2b150fa552ce49838
4
- data.tar.gz: 18287ddb63189f862bd47555b1a7a401fc0c277e5017f7ec6c8b06c634cb4d52
3
+ metadata.gz: 6a248ac037a338371cfaa5c3460bc42fd061099795538f7a81aa66b4d21272be
4
+ data.tar.gz: 3a664de3e52c9602b1dd8d2513c3e401b6948a8bf069af0664c3bc27961546b7
5
5
  SHA512:
6
- metadata.gz: b12ac60809e465da6d06fb88a086e6dc8fe927f20c97ac89e4a0cbd96b930137d36a3542e1b783d389c724b5f392fe3eb16fcb72fd3f0eb841e2da55c29db978
7
- data.tar.gz: ac40bf824c0d645b5402b264b08f44a2014365ec9ba1aa17c171c672bd4ee6c341d91d6ffb64203efcb230d56088f3f9481d82d852e81c4fda203b34af0cc573
6
+ metadata.gz: 8c81c265d78915514dfa9e52b3e90e626c74682806bd8e2d820486a01dbedd5f50a2c466542272bb89da2a646a6cf4005574970628c793d9637d52b197e24c75
7
+ data.tar.gz: fd89562f25b577ee6716952ae8379c00cd3cad4e6a01ca1055b7e2d2311b82b4459ab098f6d31fda0a59a33269eba7d5aaa6041546709dc3ae5ab1a58a705347
@@ -0,0 +1,574 @@
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 'cgi'
14
+
15
+ module Repull
16
+ class PromotionsApi
17
+ attr_accessor :api_client
18
+
19
+ def initialize(api_client = ApiClient.default)
20
+ @api_client = api_client
21
+ end
22
+ # Add or remove a promotion on many listings
23
+ # Applies one promotion to up to 100 listings — `add` it, or `remove` the listing's running promotion of that channel and type. Each listing gets its own result with the channel's reason when refused, so one refusal doesn't stop the rest. Returns `403 listing_inactive` before doing anything when any listing is inactive.
24
+ # @param promotion_bulk_request [PromotionBulkRequest]
25
+ # @param [Hash] opts the optional parameters
26
+ # @return [PromotionBulkResponse]
27
+ def bulk_listing_promotions(promotion_bulk_request, opts = {})
28
+ data, _status_code, _headers = bulk_listing_promotions_with_http_info(promotion_bulk_request, opts)
29
+ data
30
+ end
31
+
32
+ # Add or remove a promotion on many listings
33
+ # Applies one promotion to up to 100 listings — `add` it, or `remove` the listing's running promotion of that channel and type. Each listing gets its own result with the channel's reason when refused, so one refusal doesn't stop the rest. Returns `403 listing_inactive` before doing anything when any listing is inactive.
34
+ # @param promotion_bulk_request [PromotionBulkRequest]
35
+ # @param [Hash] opts the optional parameters
36
+ # @return [Array<(PromotionBulkResponse, Integer, Hash)>] PromotionBulkResponse data, response status code and response headers
37
+ def bulk_listing_promotions_with_http_info(promotion_bulk_request, opts = {})
38
+ if @api_client.config.debugging
39
+ @api_client.config.logger.debug 'Calling API: PromotionsApi.bulk_listing_promotions ...'
40
+ end
41
+ # verify the required parameter 'promotion_bulk_request' is set
42
+ if @api_client.config.client_side_validation && promotion_bulk_request.nil?
43
+ fail ArgumentError, "Missing the required parameter 'promotion_bulk_request' when calling PromotionsApi.bulk_listing_promotions"
44
+ end
45
+ # resource path
46
+ local_var_path = '/v1/listings/promotions/bulk'
47
+
48
+ # query parameters
49
+ query_params = opts[:query_params] || {}
50
+
51
+ # header parameters
52
+ header_params = opts[:header_params] || {}
53
+ # HTTP header 'Accept' (if needed)
54
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
55
+ # HTTP header 'Content-Type'
56
+ content_type = @api_client.select_header_content_type(['application/json'])
57
+ if !content_type.nil?
58
+ header_params['Content-Type'] = content_type
59
+ end
60
+
61
+ # form parameters
62
+ form_params = opts[:form_params] || {}
63
+
64
+ # http body (model)
65
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(promotion_bulk_request)
66
+
67
+ # return_type
68
+ return_type = opts[:debug_return_type] || 'PromotionBulkResponse'
69
+
70
+ # auth_names
71
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
72
+
73
+ new_options = opts.merge(
74
+ :operation => :"PromotionsApi.bulk_listing_promotions",
75
+ :header_params => header_params,
76
+ :query_params => query_params,
77
+ :form_params => form_params,
78
+ :body => post_body,
79
+ :auth_names => auth_names,
80
+ :return_type => return_type
81
+ )
82
+
83
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
84
+ if @api_client.config.debugging
85
+ @api_client.config.logger.debug "API called: PromotionsApi#bulk_listing_promotions\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
86
+ end
87
+ return data, status_code, headers
88
+ end
89
+
90
+ # Add a promotion to a listing
91
+ # Adds an Airbnb or Booking.com promotion. Read `GET /v1/listings/{id}/promotions/catalog` first for the types and fields the listing's channels accept. **Airbnb:** send `channel` and `type` only (`top_rated_guests`, `mobile`, `new_listing`) — Airbnb sets the discount. **Booking.com:** a listing's promotion covers that listing's room; send `discountPercent` and the rules the type takes, and `hotelId` when the listing is on several properties. A request a channel can't take is refused with `422` and a `promotion_*` code; the message names the channel and the field and says what to do, and `channel` / `field` are set. Booking.com writes return once Booking.com shows the change (it lags its own writes by a few seconds). Returns `403 listing_inactive` when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
92
+ # @param id [Integer] Listing ID
93
+ # @param promotion_create_request [PromotionCreateRequest]
94
+ # @param [Hash] opts the optional parameters
95
+ # @return [PromotionResponse]
96
+ def create_listing_promotion(id, promotion_create_request, opts = {})
97
+ data, _status_code, _headers = create_listing_promotion_with_http_info(id, promotion_create_request, opts)
98
+ data
99
+ end
100
+
101
+ # Add a promotion to a listing
102
+ # Adds an Airbnb or Booking.com promotion. Read &#x60;GET /v1/listings/{id}/promotions/catalog&#x60; first for the types and fields the listing&#39;s channels accept. **Airbnb:** send &#x60;channel&#x60; and &#x60;type&#x60; only (&#x60;top_rated_guests&#x60;, &#x60;mobile&#x60;, &#x60;new_listing&#x60;) — Airbnb sets the discount. **Booking.com:** a listing&#39;s promotion covers that listing&#39;s room; send &#x60;discountPercent&#x60; and the rules the type takes, and &#x60;hotelId&#x60; when the listing is on several properties. A request a channel can&#39;t take is refused with &#x60;422&#x60; and a &#x60;promotion_*&#x60; code; the message names the channel and the field and says what to do, and &#x60;channel&#x60; / &#x60;field&#x60; are set. Booking.com writes return once Booking.com shows the change (it lags its own writes by a few seconds). Returns &#x60;403 listing_inactive&#x60; when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
103
+ # @param id [Integer] Listing ID
104
+ # @param promotion_create_request [PromotionCreateRequest]
105
+ # @param [Hash] opts the optional parameters
106
+ # @return [Array<(PromotionResponse, Integer, Hash)>] PromotionResponse data, response status code and response headers
107
+ def create_listing_promotion_with_http_info(id, promotion_create_request, opts = {})
108
+ if @api_client.config.debugging
109
+ @api_client.config.logger.debug 'Calling API: PromotionsApi.create_listing_promotion ...'
110
+ end
111
+ # verify the required parameter 'id' is set
112
+ if @api_client.config.client_side_validation && id.nil?
113
+ fail ArgumentError, "Missing the required parameter 'id' when calling PromotionsApi.create_listing_promotion"
114
+ end
115
+ # verify the required parameter 'promotion_create_request' is set
116
+ if @api_client.config.client_side_validation && promotion_create_request.nil?
117
+ fail ArgumentError, "Missing the required parameter 'promotion_create_request' when calling PromotionsApi.create_listing_promotion"
118
+ end
119
+ # resource path
120
+ local_var_path = '/v1/listings/{id}/promotions'.sub('{id}', CGI.escape(id.to_s))
121
+
122
+ # query parameters
123
+ query_params = opts[:query_params] || {}
124
+
125
+ # header parameters
126
+ header_params = opts[:header_params] || {}
127
+ # HTTP header 'Accept' (if needed)
128
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
129
+ # HTTP header 'Content-Type'
130
+ content_type = @api_client.select_header_content_type(['application/json'])
131
+ if !content_type.nil?
132
+ header_params['Content-Type'] = content_type
133
+ end
134
+
135
+ # form parameters
136
+ form_params = opts[:form_params] || {}
137
+
138
+ # http body (model)
139
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(promotion_create_request)
140
+
141
+ # return_type
142
+ return_type = opts[:debug_return_type] || 'PromotionResponse'
143
+
144
+ # auth_names
145
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
146
+
147
+ new_options = opts.merge(
148
+ :operation => :"PromotionsApi.create_listing_promotion",
149
+ :header_params => header_params,
150
+ :query_params => query_params,
151
+ :form_params => form_params,
152
+ :body => post_body,
153
+ :auth_names => auth_names,
154
+ :return_type => return_type
155
+ )
156
+
157
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
158
+ if @api_client.config.debugging
159
+ @api_client.config.logger.debug "API called: PromotionsApi#create_listing_promotion\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
160
+ end
161
+ return data, status_code, headers
162
+ end
163
+
164
+ # Remove a promotion from a listing
165
+ # Airbnb: ends the listing's enrolment. Booking.com: takes the listing's room off the promotion — it keeps running for any other rooms it covers, and is deactivated when none are left. Airbnb Custom promotions can only be ended in Airbnb. A request a channel can't take is refused with `422` and a `promotion_*` code; the message names the channel and the field and says what to do, and `channel` / `field` are set. Booking.com writes return once Booking.com shows the change (it lags its own writes by a few seconds). Returns `403 listing_inactive` when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
166
+ # @param id [Integer] Listing ID
167
+ # @param promotion_id [Integer] Promotion ID (from the list)
168
+ # @param [Hash] opts the optional parameters
169
+ # @return [PromotionDeleteResponse]
170
+ def delete_listing_promotion(id, promotion_id, opts = {})
171
+ data, _status_code, _headers = delete_listing_promotion_with_http_info(id, promotion_id, opts)
172
+ data
173
+ end
174
+
175
+ # Remove a promotion from a listing
176
+ # Airbnb: ends the listing&#39;s enrolment. Booking.com: takes the listing&#39;s room off the promotion — it keeps running for any other rooms it covers, and is deactivated when none are left. Airbnb Custom promotions can only be ended in Airbnb. A request a channel can&#39;t take is refused with &#x60;422&#x60; and a &#x60;promotion_*&#x60; code; the message names the channel and the field and says what to do, and &#x60;channel&#x60; / &#x60;field&#x60; are set. Booking.com writes return once Booking.com shows the change (it lags its own writes by a few seconds). Returns &#x60;403 listing_inactive&#x60; when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
177
+ # @param id [Integer] Listing ID
178
+ # @param promotion_id [Integer] Promotion ID (from the list)
179
+ # @param [Hash] opts the optional parameters
180
+ # @return [Array<(PromotionDeleteResponse, Integer, Hash)>] PromotionDeleteResponse data, response status code and response headers
181
+ def delete_listing_promotion_with_http_info(id, promotion_id, opts = {})
182
+ if @api_client.config.debugging
183
+ @api_client.config.logger.debug 'Calling API: PromotionsApi.delete_listing_promotion ...'
184
+ end
185
+ # verify the required parameter 'id' is set
186
+ if @api_client.config.client_side_validation && id.nil?
187
+ fail ArgumentError, "Missing the required parameter 'id' when calling PromotionsApi.delete_listing_promotion"
188
+ end
189
+ # verify the required parameter 'promotion_id' is set
190
+ if @api_client.config.client_side_validation && promotion_id.nil?
191
+ fail ArgumentError, "Missing the required parameter 'promotion_id' when calling PromotionsApi.delete_listing_promotion"
192
+ end
193
+ # resource path
194
+ local_var_path = '/v1/listings/{id}/promotions/{promotionId}'.sub('{id}', CGI.escape(id.to_s)).sub('{promotionId}', CGI.escape(promotion_id.to_s))
195
+
196
+ # query parameters
197
+ query_params = opts[:query_params] || {}
198
+
199
+ # header parameters
200
+ header_params = opts[:header_params] || {}
201
+ # HTTP header 'Accept' (if needed)
202
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
203
+
204
+ # form parameters
205
+ form_params = opts[:form_params] || {}
206
+
207
+ # http body (model)
208
+ post_body = opts[:debug_body]
209
+
210
+ # return_type
211
+ return_type = opts[:debug_return_type] || 'PromotionDeleteResponse'
212
+
213
+ # auth_names
214
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
215
+
216
+ new_options = opts.merge(
217
+ :operation => :"PromotionsApi.delete_listing_promotion",
218
+ :header_params => header_params,
219
+ :query_params => query_params,
220
+ :form_params => form_params,
221
+ :body => post_body,
222
+ :auth_names => auth_names,
223
+ :return_type => return_type
224
+ )
225
+
226
+ data, status_code, headers = @api_client.call_api(:DELETE, local_var_path, new_options)
227
+ if @api_client.config.debugging
228
+ @api_client.config.logger.debug "API called: PromotionsApi#delete_listing_promotion\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
229
+ end
230
+ return data, status_code, headers
231
+ end
232
+
233
+ # Get one promotion
234
+ # One promotion on the listing. Returns `403 listing_inactive` when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
235
+ # @param id [Integer] Listing ID
236
+ # @param promotion_id [Integer] Promotion ID (from the list)
237
+ # @param [Hash] opts the optional parameters
238
+ # @return [PromotionResponse]
239
+ def get_listing_promotion(id, promotion_id, opts = {})
240
+ data, _status_code, _headers = get_listing_promotion_with_http_info(id, promotion_id, opts)
241
+ data
242
+ end
243
+
244
+ # Get one promotion
245
+ # One promotion on the listing. Returns &#x60;403 listing_inactive&#x60; when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
246
+ # @param id [Integer] Listing ID
247
+ # @param promotion_id [Integer] Promotion ID (from the list)
248
+ # @param [Hash] opts the optional parameters
249
+ # @return [Array<(PromotionResponse, Integer, Hash)>] PromotionResponse data, response status code and response headers
250
+ def get_listing_promotion_with_http_info(id, promotion_id, opts = {})
251
+ if @api_client.config.debugging
252
+ @api_client.config.logger.debug 'Calling API: PromotionsApi.get_listing_promotion ...'
253
+ end
254
+ # verify the required parameter 'id' is set
255
+ if @api_client.config.client_side_validation && id.nil?
256
+ fail ArgumentError, "Missing the required parameter 'id' when calling PromotionsApi.get_listing_promotion"
257
+ end
258
+ # verify the required parameter 'promotion_id' is set
259
+ if @api_client.config.client_side_validation && promotion_id.nil?
260
+ fail ArgumentError, "Missing the required parameter 'promotion_id' when calling PromotionsApi.get_listing_promotion"
261
+ end
262
+ # resource path
263
+ local_var_path = '/v1/listings/{id}/promotions/{promotionId}'.sub('{id}', CGI.escape(id.to_s)).sub('{promotionId}', CGI.escape(promotion_id.to_s))
264
+
265
+ # query parameters
266
+ query_params = opts[:query_params] || {}
267
+
268
+ # header parameters
269
+ header_params = opts[:header_params] || {}
270
+ # HTTP header 'Accept' (if needed)
271
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
272
+
273
+ # form parameters
274
+ form_params = opts[:form_params] || {}
275
+
276
+ # http body (model)
277
+ post_body = opts[:debug_body]
278
+
279
+ # return_type
280
+ return_type = opts[:debug_return_type] || 'PromotionResponse'
281
+
282
+ # auth_names
283
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
284
+
285
+ new_options = opts.merge(
286
+ :operation => :"PromotionsApi.get_listing_promotion",
287
+ :header_params => header_params,
288
+ :query_params => query_params,
289
+ :form_params => form_params,
290
+ :body => post_body,
291
+ :auth_names => auth_names,
292
+ :return_type => return_type
293
+ )
294
+
295
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
296
+ if @api_client.config.debugging
297
+ @api_client.config.logger.debug "API called: PromotionsApi#get_listing_promotion\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
298
+ end
299
+ return data, status_code, headers
300
+ end
301
+
302
+ # Promotion types a listing can use
303
+ # Per channel: whether the listing is connected, and each promotion type with a short description for hosts, whether it is new, whether it is available to this listing (and why not), and every field — supported or not — with its limits and any value the channel fixes. Booking.com's types and limits come from the property itself; seasonal campaigns appear while Booking.com runs them. Airbnb asks partners to show newly available discounts with a “New” badge and to grey out fields a discount does not support rather than hide them; `isNew` and `fields` carry what that needs. Returns `403 listing_inactive` when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
304
+ # @param id [Integer] Listing ID
305
+ # @param [Hash] opts the optional parameters
306
+ # @return [PromotionCatalogResponse]
307
+ def get_listing_promotion_catalog(id, opts = {})
308
+ data, _status_code, _headers = get_listing_promotion_catalog_with_http_info(id, opts)
309
+ data
310
+ end
311
+
312
+ # Promotion types a listing can use
313
+ # Per channel: whether the listing is connected, and each promotion type with a short description for hosts, whether it is new, whether it is available to this listing (and why not), and every field — supported or not — with its limits and any value the channel fixes. Booking.com&#39;s types and limits come from the property itself; seasonal campaigns appear while Booking.com runs them. Airbnb asks partners to show newly available discounts with a “New” badge and to grey out fields a discount does not support rather than hide them; &#x60;isNew&#x60; and &#x60;fields&#x60; carry what that needs. Returns &#x60;403 listing_inactive&#x60; when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
314
+ # @param id [Integer] Listing ID
315
+ # @param [Hash] opts the optional parameters
316
+ # @return [Array<(PromotionCatalogResponse, Integer, Hash)>] PromotionCatalogResponse data, response status code and response headers
317
+ def get_listing_promotion_catalog_with_http_info(id, opts = {})
318
+ if @api_client.config.debugging
319
+ @api_client.config.logger.debug 'Calling API: PromotionsApi.get_listing_promotion_catalog ...'
320
+ end
321
+ # verify the required parameter 'id' is set
322
+ if @api_client.config.client_side_validation && id.nil?
323
+ fail ArgumentError, "Missing the required parameter 'id' when calling PromotionsApi.get_listing_promotion_catalog"
324
+ end
325
+ # resource path
326
+ local_var_path = '/v1/listings/{id}/promotions/catalog'.sub('{id}', CGI.escape(id.to_s))
327
+
328
+ # query parameters
329
+ query_params = opts[:query_params] || {}
330
+
331
+ # header parameters
332
+ header_params = opts[:header_params] || {}
333
+ # HTTP header 'Accept' (if needed)
334
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
335
+
336
+ # form parameters
337
+ form_params = opts[:form_params] || {}
338
+
339
+ # http body (model)
340
+ post_body = opts[:debug_body]
341
+
342
+ # return_type
343
+ return_type = opts[:debug_return_type] || 'PromotionCatalogResponse'
344
+
345
+ # auth_names
346
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
347
+
348
+ new_options = opts.merge(
349
+ :operation => :"PromotionsApi.get_listing_promotion_catalog",
350
+ :header_params => header_params,
351
+ :query_params => query_params,
352
+ :form_params => form_params,
353
+ :body => post_body,
354
+ :auth_names => auth_names,
355
+ :return_type => return_type
356
+ )
357
+
358
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
359
+ if @api_client.config.debugging
360
+ @api_client.config.logger.debug "API called: PromotionsApi#get_listing_promotion_catalog\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
361
+ end
362
+ return data, status_code, headers
363
+ end
364
+
365
+ # List a listing's promotions
366
+ # Airbnb and Booking.com promotions on the listing, in one model. Includes Airbnb promotions running or available (the new listing promotion shows as `eligible` when the listing qualifies), Airbnb Custom promotions seen on bookings (read-only — they override your prices on Airbnb), and Booking.com promotions covering the listing's room, including deactivated ones. Pass `refresh=true` to re-read the channels first; otherwise the stored copy is returned (kept current by Airbnb's notifications and a sync every 30 minutes). Returns `403 listing_inactive` when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
367
+ # @param id [Integer] Listing ID
368
+ # @param [Hash] opts the optional parameters
369
+ # @option opts [Boolean] :refresh Re-read Airbnb and Booking.com before answering.
370
+ # @return [PromotionListResponse]
371
+ def list_listing_promotions(id, opts = {})
372
+ data, _status_code, _headers = list_listing_promotions_with_http_info(id, opts)
373
+ data
374
+ end
375
+
376
+ # List a listing&#39;s promotions
377
+ # Airbnb and Booking.com promotions on the listing, in one model. Includes Airbnb promotions running or available (the new listing promotion shows as &#x60;eligible&#x60; when the listing qualifies), Airbnb Custom promotions seen on bookings (read-only — they override your prices on Airbnb), and Booking.com promotions covering the listing&#39;s room, including deactivated ones. Pass &#x60;refresh&#x3D;true&#x60; to re-read the channels first; otherwise the stored copy is returned (kept current by Airbnb&#39;s notifications and a sync every 30 minutes). Returns &#x60;403 listing_inactive&#x60; when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
378
+ # @param id [Integer] Listing ID
379
+ # @param [Hash] opts the optional parameters
380
+ # @option opts [Boolean] :refresh Re-read Airbnb and Booking.com before answering.
381
+ # @return [Array<(PromotionListResponse, Integer, Hash)>] PromotionListResponse data, response status code and response headers
382
+ def list_listing_promotions_with_http_info(id, opts = {})
383
+ if @api_client.config.debugging
384
+ @api_client.config.logger.debug 'Calling API: PromotionsApi.list_listing_promotions ...'
385
+ end
386
+ # verify the required parameter 'id' is set
387
+ if @api_client.config.client_side_validation && id.nil?
388
+ fail ArgumentError, "Missing the required parameter 'id' when calling PromotionsApi.list_listing_promotions"
389
+ end
390
+ # resource path
391
+ local_var_path = '/v1/listings/{id}/promotions'.sub('{id}', CGI.escape(id.to_s))
392
+
393
+ # query parameters
394
+ query_params = opts[:query_params] || {}
395
+ query_params[:'refresh'] = opts[:'refresh'] if !opts[:'refresh'].nil?
396
+
397
+ # header parameters
398
+ header_params = opts[:header_params] || {}
399
+ # HTTP header 'Accept' (if needed)
400
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
401
+
402
+ # form parameters
403
+ form_params = opts[:form_params] || {}
404
+
405
+ # http body (model)
406
+ post_body = opts[:debug_body]
407
+
408
+ # return_type
409
+ return_type = opts[:debug_return_type] || 'PromotionListResponse'
410
+
411
+ # auth_names
412
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
413
+
414
+ new_options = opts.merge(
415
+ :operation => :"PromotionsApi.list_listing_promotions",
416
+ :header_params => header_params,
417
+ :query_params => query_params,
418
+ :form_params => form_params,
419
+ :body => post_body,
420
+ :auth_names => auth_names,
421
+ :return_type => return_type
422
+ )
423
+
424
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
425
+ if @api_client.config.debugging
426
+ @api_client.config.logger.debug "API called: PromotionsApi#list_listing_promotions\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
427
+ end
428
+ return data, status_code, headers
429
+ end
430
+
431
+ # Re-read a listing's promotions now
432
+ # Reads the listing's promotions from Airbnb and Booking.com and returns them. Booking.com promotions belong to the property, so the property's other listings are refreshed too. `errors` lists any channel that could not be read. Returns `403 listing_inactive` when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
433
+ # @param id [Integer] Listing ID
434
+ # @param [Hash] opts the optional parameters
435
+ # @return [PromotionRefreshResponse]
436
+ def refresh_listing_promotions(id, opts = {})
437
+ data, _status_code, _headers = refresh_listing_promotions_with_http_info(id, opts)
438
+ data
439
+ end
440
+
441
+ # Re-read a listing&#39;s promotions now
442
+ # Reads the listing&#39;s promotions from Airbnb and Booking.com and returns them. Booking.com promotions belong to the property, so the property&#39;s other listings are refreshed too. &#x60;errors&#x60; lists any channel that could not be read. Returns &#x60;403 listing_inactive&#x60; when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
443
+ # @param id [Integer] Listing ID
444
+ # @param [Hash] opts the optional parameters
445
+ # @return [Array<(PromotionRefreshResponse, Integer, Hash)>] PromotionRefreshResponse data, response status code and response headers
446
+ def refresh_listing_promotions_with_http_info(id, opts = {})
447
+ if @api_client.config.debugging
448
+ @api_client.config.logger.debug 'Calling API: PromotionsApi.refresh_listing_promotions ...'
449
+ end
450
+ # verify the required parameter 'id' is set
451
+ if @api_client.config.client_side_validation && id.nil?
452
+ fail ArgumentError, "Missing the required parameter 'id' when calling PromotionsApi.refresh_listing_promotions"
453
+ end
454
+ # resource path
455
+ local_var_path = '/v1/listings/{id}/promotions/refresh'.sub('{id}', CGI.escape(id.to_s))
456
+
457
+ # query parameters
458
+ query_params = opts[:query_params] || {}
459
+
460
+ # header parameters
461
+ header_params = opts[:header_params] || {}
462
+ # HTTP header 'Accept' (if needed)
463
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
464
+
465
+ # form parameters
466
+ form_params = opts[:form_params] || {}
467
+
468
+ # http body (model)
469
+ post_body = opts[:debug_body]
470
+
471
+ # return_type
472
+ return_type = opts[:debug_return_type] || 'PromotionRefreshResponse'
473
+
474
+ # auth_names
475
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
476
+
477
+ new_options = opts.merge(
478
+ :operation => :"PromotionsApi.refresh_listing_promotions",
479
+ :header_params => header_params,
480
+ :query_params => query_params,
481
+ :form_params => form_params,
482
+ :body => post_body,
483
+ :auth_names => auth_names,
484
+ :return_type => return_type
485
+ )
486
+
487
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
488
+ if @api_client.config.debugging
489
+ @api_client.config.logger.debug "API called: PromotionsApi#refresh_listing_promotions\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
490
+ end
491
+ return data, status_code, headers
492
+ end
493
+
494
+ # Change a promotion
495
+ # Booking.com promotions only — Airbnb's have nothing to change. `rules`, when sent, replaces the promotion's rules whole. A promotion that also covers other listings' rooms changes for them too, so it needs `confirmShared: true` (otherwise `409 promotion_shared_promotion`). Promotions that come from the listing's weekly or monthly discount are changed in its pricing settings. A request a channel can't take is refused with `422` and a `promotion_*` code; the message names the channel and the field and says what to do, and `channel` / `field` are set. Booking.com writes return once Booking.com shows the change (it lags its own writes by a few seconds). Returns `403 listing_inactive` when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
496
+ # @param id [Integer] Listing ID
497
+ # @param promotion_id [Integer] Promotion ID (from the list)
498
+ # @param promotion_update_request [PromotionUpdateRequest]
499
+ # @param [Hash] opts the optional parameters
500
+ # @return [PromotionResponse]
501
+ def update_listing_promotion(id, promotion_id, promotion_update_request, opts = {})
502
+ data, _status_code, _headers = update_listing_promotion_with_http_info(id, promotion_id, promotion_update_request, opts)
503
+ data
504
+ end
505
+
506
+ # Change a promotion
507
+ # Booking.com promotions only — Airbnb&#39;s have nothing to change. &#x60;rules&#x60;, when sent, replaces the promotion&#39;s rules whole. A promotion that also covers other listings&#39; rooms changes for them too, so it needs &#x60;confirmShared: true&#x60; (otherwise &#x60;409 promotion_shared_promotion&#x60;). Promotions that come from the listing&#39;s weekly or monthly discount are changed in its pricing settings. A request a channel can&#39;t take is refused with &#x60;422&#x60; and a &#x60;promotion_*&#x60; code; the message names the channel and the field and says what to do, and &#x60;channel&#x60; / &#x60;field&#x60; are set. Booking.com writes return once Booking.com shows the change (it lags its own writes by a few seconds). Returns &#x60;403 listing_inactive&#x60; when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
508
+ # @param id [Integer] Listing ID
509
+ # @param promotion_id [Integer] Promotion ID (from the list)
510
+ # @param promotion_update_request [PromotionUpdateRequest]
511
+ # @param [Hash] opts the optional parameters
512
+ # @return [Array<(PromotionResponse, Integer, Hash)>] PromotionResponse data, response status code and response headers
513
+ def update_listing_promotion_with_http_info(id, promotion_id, promotion_update_request, opts = {})
514
+ if @api_client.config.debugging
515
+ @api_client.config.logger.debug 'Calling API: PromotionsApi.update_listing_promotion ...'
516
+ end
517
+ # verify the required parameter 'id' is set
518
+ if @api_client.config.client_side_validation && id.nil?
519
+ fail ArgumentError, "Missing the required parameter 'id' when calling PromotionsApi.update_listing_promotion"
520
+ end
521
+ # verify the required parameter 'promotion_id' is set
522
+ if @api_client.config.client_side_validation && promotion_id.nil?
523
+ fail ArgumentError, "Missing the required parameter 'promotion_id' when calling PromotionsApi.update_listing_promotion"
524
+ end
525
+ # verify the required parameter 'promotion_update_request' is set
526
+ if @api_client.config.client_side_validation && promotion_update_request.nil?
527
+ fail ArgumentError, "Missing the required parameter 'promotion_update_request' when calling PromotionsApi.update_listing_promotion"
528
+ end
529
+ # resource path
530
+ local_var_path = '/v1/listings/{id}/promotions/{promotionId}'.sub('{id}', CGI.escape(id.to_s)).sub('{promotionId}', CGI.escape(promotion_id.to_s))
531
+
532
+ # query parameters
533
+ query_params = opts[:query_params] || {}
534
+
535
+ # header parameters
536
+ header_params = opts[:header_params] || {}
537
+ # HTTP header 'Accept' (if needed)
538
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
539
+ # HTTP header 'Content-Type'
540
+ content_type = @api_client.select_header_content_type(['application/json'])
541
+ if !content_type.nil?
542
+ header_params['Content-Type'] = content_type
543
+ end
544
+
545
+ # form parameters
546
+ form_params = opts[:form_params] || {}
547
+
548
+ # http body (model)
549
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(promotion_update_request)
550
+
551
+ # return_type
552
+ return_type = opts[:debug_return_type] || 'PromotionResponse'
553
+
554
+ # auth_names
555
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
556
+
557
+ new_options = opts.merge(
558
+ :operation => :"PromotionsApi.update_listing_promotion",
559
+ :header_params => header_params,
560
+ :query_params => query_params,
561
+ :form_params => form_params,
562
+ :body => post_body,
563
+ :auth_names => auth_names,
564
+ :return_type => return_type
565
+ )
566
+
567
+ data, status_code, headers = @api_client.call_api(:PATCH, local_var_path, new_options)
568
+ if @api_client.config.debugging
569
+ @api_client.config.logger.debug "API called: PromotionsApi#update_listing_promotion\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
570
+ end
571
+ return data, status_code, headers
572
+ end
573
+ end
574
+ end
@@ -14,11 +14,11 @@ require 'date'
14
14
  require 'time'
15
15
 
16
16
  module Repull
17
- # Payload for `listing.updated`. Something about the listing changed on the channel — content, pricing, booking settings, house rules, availability or sync settings.
17
+ # Payload for `listing.updated`. Something about the listing changed on the channel — content, pricing, booking settings, house rules, availability, sync settings or promotions.
18
18
  class ListingUpdatedPayload < ApiModelBase
19
19
  attr_accessor :object
20
20
 
21
- # Which part moved. Airbnb sends one notification per area rather than a diff, so this is the signal for what to re-read.
21
+ # Which part moved. Airbnb sends one notification per area rather than a diff, so this is the signal for what to re-read. `promotions`: the listing’s Airbnb or Booking.com promotions changed — re-read `GET /v1/listings/{id}/promotions`.
22
22
  attr_accessor :area
23
23
 
24
24
  # Fields that changed and their prior values, when the source reports them.