repull 0.2.24 → 0.2.26

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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/lib/repull/api/connect_api.rb +619 -2
  3. data/lib/repull/api/connections_api.rb +312 -0
  4. data/lib/repull/api/conversations_api.rb +154 -18
  5. data/lib/repull/api/health_api.rb +5 -5
  6. data/lib/repull/api/listings_api.rb +67 -4
  7. data/lib/repull/api/properties_api.rb +3 -0
  8. data/lib/repull/api/reservations_api.rb +3 -0
  9. data/lib/repull/api/reviews_api.rb +5 -2
  10. data/lib/repull/api/vrbo_api.rb +4 -4
  11. data/lib/repull/models/apply_connection_mappings200_response.rb +167 -0
  12. data/lib/repull/models/apply_connection_mappings200_response_results_inner.rb +184 -0
  13. data/lib/repull/models/apply_connection_mappings_request.rb +175 -0
  14. data/lib/repull/models/apply_connection_mappings_request_mappings_inner.rb +193 -0
  15. data/lib/repull/models/auto_map_connection_units200_response.rb +176 -0
  16. data/lib/repull/models/auto_map_connection_units_request.rb +156 -0
  17. data/lib/repull/models/channel_market_state_item.rb +15 -4
  18. data/lib/repull/models/connect_session_completed_event.rb +281 -0
  19. data/lib/repull/models/connect_session_completed_payload.rb +210 -0
  20. data/lib/repull/models/connect_status.rb +25 -5
  21. data/lib/repull/models/connect_status_accounts_inner.rb +71 -4
  22. data/lib/repull/models/conversation.rb +12 -1
  23. data/lib/repull/models/conversation_capabilities.rb +260 -0
  24. data/lib/repull/models/conversation_detail.rb +25 -5
  25. data/lib/repull/models/create_connect_session_request.rb +24 -2
  26. data/lib/repull/models/create_connection_request.rb +8 -8
  27. data/lib/repull/models/create_conversation_special_offer201_response.rb +127 -4
  28. data/lib/repull/models/create_conversation_special_offer201_response_fees_inner.rb +166 -0
  29. data/lib/repull/models/create_conversation_special_offer201_response_lines_inner.rb +157 -0
  30. data/lib/repull/models/create_conversation_special_offer_request.rb +91 -52
  31. data/lib/repull/models/create_conversation_special_offer_request_fees_inner.rb +199 -0
  32. data/lib/repull/models/get_booking_extranet_login_config200_response.rb +147 -0
  33. data/lib/repull/models/get_booking_extranet_login_status200_response.rb +192 -0
  34. data/lib/repull/models/get_channel_health200_response.rb +190 -0
  35. data/lib/repull/models/get_channel_health200_response_vrbo.rb +197 -0
  36. data/lib/repull/models/get_connect_write_policy200_response.rb +166 -0
  37. data/lib/repull/models/get_listing_calendar_sync200_response.rb +192 -0
  38. data/lib/repull/models/get_listing_calendar_sync200_response_channels_inner.rb +331 -0
  39. data/lib/repull/models/get_listing_calendar_sync200_response_channels_inner_problems_inner.rb +157 -0
  40. data/lib/repull/models/get_listing_calendar_sync200_response_channels_inner_queue.rb +212 -0
  41. data/lib/repull/models/get_listing_calendar_sync200_response_channels_inner_queue_last_push.rb +268 -0
  42. data/lib/repull/models/invite_booking_extranet_user200_response.rb +174 -0
  43. data/lib/repull/models/invite_booking_extranet_user_request.rb +173 -0
  44. data/lib/repull/models/list_connection_units200_response.rb +242 -0
  45. data/lib/repull/models/list_connection_units200_response_listing_options_inner.rb +165 -0
  46. data/lib/repull/models/list_connection_units200_response_units_inner.rb +194 -0
  47. data/lib/repull/models/listing_publish_status_connection.rb +34 -1
  48. data/lib/repull/models/pms_write_policy.rb +191 -0
  49. data/lib/repull/models/pms_write_policy_calendar.rb +219 -0
  50. data/lib/repull/models/pms_write_policy_reservations.rb +219 -0
  51. data/lib/repull/models/preapprove_conversation201_response.rb +47 -6
  52. data/lib/repull/models/preapprove_conversation_request.rb +34 -5
  53. data/lib/repull/models/preview_conversation_special_offer_request.rb +231 -0
  54. data/lib/repull/models/preview_conversation_special_offer_request_fees_inner.rb +199 -0
  55. data/lib/repull/models/preview_conversation_special_offer_request_guests.rb +250 -0
  56. data/lib/repull/models/property.rb +14 -2
  57. data/lib/repull/models/record_account.rb +170 -0
  58. data/lib/repull/models/reply_to_review_request.rb +33 -4
  59. data/lib/repull/models/reservation.rb +12 -1
  60. data/lib/repull/models/review.rb +12 -1
  61. data/lib/repull/models/search_connect_session_listing_options200_response.rb +158 -0
  62. data/lib/repull/models/search_connect_session_listing_options200_response_data_inner.rb +166 -0
  63. data/lib/repull/models/search_connection_listing_options200_response.rb +159 -0
  64. data/lib/repull/models/send_message_request.rb +1 -1
  65. data/lib/repull/models/start_booking_extranet_login200_response.rb +174 -0
  66. data/lib/repull/models/start_booking_extranet_login_request.rb +225 -0
  67. data/lib/repull/models/submit_cloudbeds_credentials200_response.rb +10 -1
  68. data/lib/repull/models/submit_cloudbeds_credentials_request.rb +11 -1
  69. data/lib/repull/models/submit_mews_credentials200_response.rb +10 -1
  70. data/lib/repull/models/submit_mews_credentials_request.rb +11 -1
  71. data/lib/repull/models/update_connect_write_policy_request.rb +157 -0
  72. data/lib/repull/models/update_connect_write_policy_request_calendar.rb +165 -0
  73. data/lib/repull/models/update_connect_write_policy_request_reservations.rb +165 -0
  74. data/lib/repull/models/vrbo_import_status.rb +249 -0
  75. data/lib/repull/models/vrbo_login200_response.rb +235 -0
  76. data/lib/repull/models/vrbo_login_request.rb +271 -0
  77. data/lib/repull/models/webhook_event.rb +2 -0
  78. data/lib/repull/models/webhook_event_type.rb +2 -1
  79. data/lib/repull/models/withdraw_conversation_preapproval200_response.rb +226 -0
  80. data/lib/repull/models/withdraw_conversation_special_offer200_response.rb +29 -1
  81. data/lib/repull/version.rb +1 -1
  82. data/lib/repull.rb +47 -0
  83. data/openapi/v1.json +2810 -74
  84. data/scripts/regen.sh +1 -1
  85. metadata +49 -2
@@ -19,8 +19,8 @@ module Repull
19
19
  def initialize(api_client = ApiClient.default)
20
20
  @api_client = api_client
21
21
  end
22
- # Send a special offer
23
- # Send the guest on this conversation an Airbnb special offer: your own dates, guest count and total price. The guest has 24 hours to book it. Use it to answer an inquiry with different terms, or to make a returning guest a custom price. To accept the guest’s own dates and price as they asked, pre-approve instead (`POST /v1/conversations/{id}/pre-approval`). `listingId` is optional: omit it to offer the listing the guest asked about. It is a **Repull** listing id; Repull sends Airbnb its own listing id, using the link that belongs to this conversation’s Airbnb account. `totalPrice` is the whole stay, in the listing’s Airbnb currency — Airbnb does not take a currency on an offer. **Airbnb only**, and only for listings connected to Airbnb directly; anything else is `422 channel_not_supported` and nothing is sent. The inquiry is marked `special_offer_sent`. An offer Airbnb refuses is never a `201`: dates that are taken, a price below Airbnb’s minimum, too many guests and the like are `422 airbnb_rejected` with Airbnb’s own reason in `message`. Send `Idempotency-Key`: a repeat with the same key replays the first response instead of acting twice (a `409 idempotency_key_in_use` while the first is still running). A 5xx, a `429 airbnb_rate_limited` or a `403 connection_reauth_required` is not stored — nothing was done — so retrying with the same key reaches Airbnb again. Without it, a retry after a timeout can send the guest two offers. Read or withdraw the offer with `GET` / `DELETE /v1/conversations/{id}/special-offers/{offerId}`.
22
+ # Send a special offer (Airbnb, VRBO)
23
+ # Send the guest on this conversation a special offer: your own dates, guest count and price. One endpoint for every channel that has offers — **Airbnb** (connected directly) and **VRBO** (its “Edit quote”). Use it to answer an inquiry with different terms. To accept the guest’s own dates and price as they asked, pre-approve instead (`POST /v1/conversations/{id}/pre-approval`). **How the price is set depends on the channel** — `GET /v1/conversations/{id}` → `capabilities.offerPrice` says which: - `total` (Airbnb): send `totalPrice`, the whole stay in the listing’s Airbnb currency, with `checkIn`, `checkOut` and `guests`. - `breakdown` (VRBO): send the price’s parts — `rentalAmount` (rent, excluding fees), `fees` by VRBO fee type, `damageDeposit` — and VRBO computes the guest total, adding its taxes and service fee. Dates and party are optional (omitted → the inquiry’s own). Only what you send is changed. Preview the result first with `POST /v1/conversations/{id}/special-offers/preview`. Sending the other kind is `422 offer_price_total_required` / `offer_price_breakdown_required` naming the field; nothing is sent. A channel without offers (Booking.com, direct, an Airbnb inquiry relayed by a PMS) is `422 channel_not_supported`. `listingId` (Airbnb) is optional: omit it to offer the listing the guest asked about. It is a **Repull** listing id. `message` (VRBO) is sent to the guest with the offer. An offer the channel refuses is never a `201`: dates that are taken, a price below the channel’s minimum and the like are `422` with the channel’s own reason in `message`. Send `Idempotency-Key`: a repeat with the same key replays the first response instead of acting twice (a `409 idempotency_key_in_use` while the first is still running). A 5xx, a `429 airbnb_rate_limited` or a `403 connection_reauth_required` is not stored — nothing was done — so retrying with the same key reaches Airbnb again. Without it, a retry after a timeout can send the guest two offers. Read or withdraw the offer with `GET` / `DELETE /v1/conversations/{id}/special-offers/{offerId}` (VRBO: `offerId` = `current`).
24
24
  # @param id [Integer] Repull conversation id (from `GET /v1/conversations` or `conversationId` on `GET /v1/inquiries`) — not the Airbnb thread id.
25
25
  # @param create_conversation_special_offer_request [CreateConversationSpecialOfferRequest]
26
26
  # @param [Hash] opts the optional parameters
@@ -31,8 +31,8 @@ module Repull
31
31
  data
32
32
  end
33
33
 
34
- # Send a special offer
35
- # Send the guest on this conversation an Airbnb special offer: your own dates, guest count and total price. The guest has 24 hours to book it. Use it to answer an inquiry with different terms, or to make a returning guest a custom price. To accept the guest’s own dates and price as they asked, pre-approve instead (`POST /v1/conversations/{id}/pre-approval`). `listingId` is optional: omit it to offer the listing the guest asked about. It is a **Repull** listing id; Repull sends Airbnb its own listing id, using the link that belongs to this conversation’s Airbnb account. `totalPrice` is the whole stay, in the listing’s Airbnb currency — Airbnb does not take a currency on an offer. **Airbnb only**, and only for listings connected to Airbnb directly; anything else is `422 channel_not_supported` and nothing is sent. The inquiry is marked `special_offer_sent`. An offer Airbnb refuses is never a `201`: dates that are taken, a price below Airbnb’s minimum, too many guests and the like are `422 airbnb_rejected` with Airbnb’s own reason in `message`. Send `Idempotency-Key`: a repeat with the same key replays the first response instead of acting twice (a `409 idempotency_key_in_use` while the first is still running). A 5xx, a `429 airbnb_rate_limited` or a `403 connection_reauth_required` is not stored — nothing was done — so retrying with the same key reaches Airbnb again. Without it, a retry after a timeout can send the guest two offers. Read or withdraw the offer with `GET` / `DELETE /v1/conversations/{id}/special-offers/{offerId}`.
34
+ # Send a special offer (Airbnb, VRBO)
35
+ # Send the guest on this conversation a special offer: your own dates, guest count and price. One endpoint for every channel that has offers — **Airbnb** (connected directly) and **VRBO** (its “Edit quote”). Use it to answer an inquiry with different terms. To accept the guest’s own dates and price as they asked, pre-approve instead (`POST /v1/conversations/{id}/pre-approval`). **How the price is set depends on the channel** — `GET /v1/conversations/{id}` → `capabilities.offerPrice` says which: - `total` (Airbnb): send `totalPrice`, the whole stay in the listing’s Airbnb currency, with `checkIn`, `checkOut` and `guests`. - `breakdown` (VRBO): send the price’s parts — `rentalAmount` (rent, excluding fees), `fees` by VRBO fee type, `damageDeposit` — and VRBO computes the guest total, adding its taxes and service fee. Dates and party are optional (omitted → the inquiry’s own). Only what you send is changed. Preview the result first with `POST /v1/conversations/{id}/special-offers/preview`. Sending the other kind is `422 offer_price_total_required` / `offer_price_breakdown_required` naming the field; nothing is sent. A channel without offers (Booking.com, direct, an Airbnb inquiry relayed by a PMS) is `422 channel_not_supported`. `listingId` (Airbnb) is optional: omit it to offer the listing the guest asked about. It is a **Repull** listing id. `message` (VRBO) is sent to the guest with the offer. An offer the channel refuses is never a `201`: dates that are taken, a price below the channel’s minimum and the like are `422` with the channel’s own reason in `message`. Send `Idempotency-Key`: a repeat with the same key replays the first response instead of acting twice (a `409 idempotency_key_in_use` while the first is still running). A 5xx, a `429 airbnb_rate_limited` or a `403 connection_reauth_required` is not stored — nothing was done — so retrying with the same key reaches Airbnb again. Without it, a retry after a timeout can send the guest two offers. Read or withdraw the offer with `GET` / `DELETE /v1/conversations/{id}/special-offers/{offerId}` (VRBO: `offerId` = `current`).
36
36
  # @param id [Integer] Repull conversation id (from `GET /v1/conversations` or `conversationId` on `GET /v1/inquiries`) — not the Airbnb thread id.
37
37
  # @param create_conversation_special_offer_request [CreateConversationSpecialOfferRequest]
38
38
  # @param [Hash] opts the optional parameters
@@ -167,9 +167,9 @@ module Repull
167
167
  end
168
168
 
169
169
  # Get a special offer
170
- # Read a special offer on this conversation back from Airbnb — typically to check its `status` (`active` until the guest books it, it expires, or you withdraw it). Read live from Airbnb with the conversation’s own Airbnb account.
170
+ # Read a special offer on this conversation — typically to check its `status`. Airbnb: read live with the conversation’s own Airbnb account (`active` until the guest books it, it expires, or you withdraw it). VRBO (`offerId` = `current`): the live offer as last synced from VRBO, priced by its parts with VRBO’s total.
171
171
  # @param id [Integer] Repull conversation id (from `GET /v1/conversations` or `conversationId` on `GET /v1/inquiries`) — not the Airbnb thread id.
172
- # @param offer_id [String] The special offer’s `id`, as returned by `POST /v1/conversations/{id}/special-offers`.
172
+ # @param offer_id [String] The special offer’s `id`, as returned by `POST /v1/conversations/{id}/special-offers`. On VRBO, where a conversation has one live offer, `current`.
173
173
  # @param [Hash] opts the optional parameters
174
174
  # @return [CreateConversationSpecialOffer201Response]
175
175
  def get_conversation_special_offer(id, offer_id, opts = {})
@@ -178,9 +178,9 @@ module Repull
178
178
  end
179
179
 
180
180
  # Get a special offer
181
- # Read a special offer on this conversation back from Airbnb — typically to check its `status` (`active` until the guest books it, it expires, or you withdraw it). Read live from Airbnb with the conversation’s own Airbnb account.
181
+ # Read a special offer on this conversation — typically to check its `status`. Airbnb: read live with the conversation’s own Airbnb account (`active` until the guest books it, it expires, or you withdraw it). VRBO (`offerId` = `current`): the live offer as last synced from VRBO, priced by its parts with VRBO’s total.
182
182
  # @param id [Integer] Repull conversation id (from `GET /v1/conversations` or `conversationId` on `GET /v1/inquiries`) — not the Airbnb thread id.
183
- # @param offer_id [String] The special offer’s `id`, as returned by `POST /v1/conversations/{id}/special-offers`.
183
+ # @param offer_id [String] The special offer’s `id`, as returned by `POST /v1/conversations/{id}/special-offers`. On VRBO, where a conversation has one live offer, `current`.
184
184
  # @param [Hash] opts the optional parameters
185
185
  # @return [Array<(CreateConversationSpecialOffer201Response, Integer, Hash)>] CreateConversationSpecialOffer201Response data, response status code and response headers
186
186
  def get_conversation_special_offer_with_http_info(id, offer_id, opts = {})
@@ -336,6 +336,7 @@ module Repull
336
336
  # List conversations
337
337
  # Cursor-paginated list of message threads owned by the workspace. Use `pagination.nextCursor` from one response as the `cursor` query param of the next request. `?offset=` is also accepted as a first-class alias for shallow paging (0..10000) — see the `offset` parameter below. Mutually exclusive with `cursor`. Filters: `platform` (`airbnb`|`booking`|`vrbo`|`website`|`email`), `status` (`open`|`archived` — `archived` is a stable no-op until the bit lands on `message_threads`). **Inactive listings:** conversations that belong to an inactive listing (by the thread's listing or its reservation's listing) are left out of the page and of `pagination.total`. Inactive listings keep syncing; activate the listing to use it here.
338
338
  # @param [Hash] opts the optional parameters
339
+ # @option opts [String] :account Only the records of one connected account, as &#x60;provider:externalAccountId&#x60; — the pair from a webhook &#x60;account&#x60; block, &#x60;connect.session.completed&#x60;, or &#x60;GET /v1/connect/{provider}&#x60; → &#x60;accounts&#x60;. A record belongs to an account when it is on that account&#39;s listings and on its channel (a PMS account: came in through that PMS). An account with no listings returns an empty page.
339
340
  # @option opts [String] :x_schema Apply a custom or built-in schema to transform the response. Built-in: &#x60;native&#x60; (default), &#x60;calry&#x60;, &#x60;calry-v1&#x60;. Custom: any schema name created via &#x60;POST /v1/schema/custom&#x60;. Unknown / inactive schema names fall back to &#x60;native&#x60;.
340
341
  # @option opts [String] :cursor Opaque cursor returned in the previous response&#39;s &#x60;pagination.nextCursor&#x60;. Omit to fetch the first page.
341
342
  # @option opts [Integer] :offset First-class alias for cursor-based pagination. Mutually exclusive with &#x60;cursor&#x60; — passing both returns 422. Accepts integers in &#x60;[0, 10000]&#x60;; deeper walks must use &#x60;cursor&#x60; (constant per-page cost). The response always includes &#x60;pagination.nextCursor&#x60; so consumers can switch from offset → cursor mid-walk for deep pagination without re-keying. (default to 0)
@@ -351,6 +352,7 @@ module Repull
351
352
  # List conversations
352
353
  # Cursor-paginated list of message threads owned by the workspace. Use &#x60;pagination.nextCursor&#x60; from one response as the &#x60;cursor&#x60; query param of the next request. &#x60;?offset&#x3D;&#x60; is also accepted as a first-class alias for shallow paging (0..10000) — see the &#x60;offset&#x60; parameter below. Mutually exclusive with &#x60;cursor&#x60;. Filters: &#x60;platform&#x60; (&#x60;airbnb&#x60;|&#x60;booking&#x60;|&#x60;vrbo&#x60;|&#x60;website&#x60;|&#x60;email&#x60;), &#x60;status&#x60; (&#x60;open&#x60;|&#x60;archived&#x60; — &#x60;archived&#x60; is a stable no-op until the bit lands on &#x60;message_threads&#x60;). **Inactive listings:** conversations that belong to an inactive listing (by the thread&#39;s listing or its reservation&#39;s listing) are left out of the page and of &#x60;pagination.total&#x60;. Inactive listings keep syncing; activate the listing to use it here.
353
354
  # @param [Hash] opts the optional parameters
355
+ # @option opts [String] :account Only the records of one connected account, as &#x60;provider:externalAccountId&#x60; — the pair from a webhook &#x60;account&#x60; block, &#x60;connect.session.completed&#x60;, or &#x60;GET /v1/connect/{provider}&#x60; → &#x60;accounts&#x60;. A record belongs to an account when it is on that account&#39;s listings and on its channel (a PMS account: came in through that PMS). An account with no listings returns an empty page.
354
356
  # @option opts [String] :x_schema Apply a custom or built-in schema to transform the response. Built-in: &#x60;native&#x60; (default), &#x60;calry&#x60;, &#x60;calry-v1&#x60;. Custom: any schema name created via &#x60;POST /v1/schema/custom&#x60;. Unknown / inactive schema names fall back to &#x60;native&#x60;.
355
357
  # @option opts [String] :cursor Opaque cursor returned in the previous response&#39;s &#x60;pagination.nextCursor&#x60;. Omit to fetch the first page.
356
358
  # @option opts [Integer] :offset First-class alias for cursor-based pagination. Mutually exclusive with &#x60;cursor&#x60; — passing both returns 422. Accepts integers in &#x60;[0, 10000]&#x60;; deeper walks must use &#x60;cursor&#x60; (constant per-page cost). The response always includes &#x60;pagination.nextCursor&#x60; so consumers can switch from offset → cursor mid-walk for deep pagination without re-keying. (default to 0)
@@ -391,6 +393,7 @@ module Repull
391
393
 
392
394
  # query parameters
393
395
  query_params = opts[:query_params] || {}
396
+ query_params[:'account'] = opts[:'account'] if !opts[:'account'].nil?
394
397
  query_params[:'cursor'] = opts[:'cursor'] if !opts[:'cursor'].nil?
395
398
  query_params[:'offset'] = opts[:'offset'] if !opts[:'offset'].nil?
396
399
  query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil?
@@ -530,8 +533,8 @@ module Repull
530
533
  return data, status_code, headers
531
534
  end
532
535
 
533
- # Pre-approve an inquiry
534
- # Pre-approve the Airbnb inquiry on this conversation: the guest who asked about dates may now book them at the listed price, without waiting on you. To change the dates, guests or price, send a special offer instead (`POST /v1/conversations/{id}/special-offers`). Find inquiries that need an answer with `GET /v1/inquiries` (default `status=open`); each carries the `conversationId` to use here. **Airbnb only**, and only for listings connected to Airbnb directly. A Booking.com, VRBO or direct-booking conversation, or an Airbnb one relayed through a PMS (Hostaway, Guesty), returns `422 channel_not_supported` and nothing is sent. The inquiry is marked `pre_approved` everywhere, the same as pre-approving in Airbnb. An Airbnb refusal is never reported as a success: an inquiry that already moved on is `409 inquiry_no_longer_open`, an expired one `409 inquiry_expired`, a conversation that already has a booking `409 conversation_already_booked`. Send `Idempotency-Key`: a repeat with the same key replays the first response instead of acting twice (a `409 idempotency_key_in_use` while the first is still running). A 5xx, a `429 airbnb_rate_limited` or a `403 connection_reauth_required` is not stored — nothing was done — so retrying with the same key reaches Airbnb again.
536
+ # Pre-approve an inquiry (Airbnb, VRBO)
537
+ # Pre-approve the inquiry on this conversation: the guest who asked about dates may now book them at the listed price, without waiting on you. To change the dates, guests or price, send a special offer instead (`POST /v1/conversations/{id}/special-offers`). Find inquiries that need an answer with `GET /v1/inquiries` (default `status=open`); each carries the `conversationId` to use here. One endpoint for every channel with pre-approvals: **Airbnb** (listings connected directly) and **VRBO**. A Booking.com or direct-booking conversation, or an Airbnb one relayed through a PMS (Hostaway, Guesty), returns `422 channel_not_supported` and nothing is sent — `GET /v1/conversations/{id}` → `capabilities.canPreApprove` says where it works. `blockInstantBooking` is Airbnb only (VRBO has no such switch: `422 invalid_params`). `message` is sent to the guest with a VRBO pre-approval (a friendly default otherwise). The inquiry is marked `pre_approved` everywhere, the same as pre-approving on the channel. Withdraw it with `DELETE /v1/conversations/{id}/pre-approval` (VRBO). A channel’s refusal is never reported as a success: an inquiry that already moved on is `409 inquiry_no_longer_open`, an expired one `409 inquiry_expired`, a conversation that already has a booking `409 conversation_already_booked`. Send `Idempotency-Key`: a repeat with the same key replays the first response instead of acting twice (a `409 idempotency_key_in_use` while the first is still running). A 5xx, a `429 airbnb_rate_limited` or a `403 connection_reauth_required` is not stored — nothing was done — so retrying with the same key reaches Airbnb again.
535
538
  # @param id [Integer] Repull conversation id (from &#x60;GET /v1/conversations&#x60; or &#x60;conversationId&#x60; on &#x60;GET /v1/inquiries&#x60;) — not the Airbnb thread id.
536
539
  # @param [Hash] opts the optional parameters
537
540
  # @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged &#x60;Idempotency-Status: cached&#x60; — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → &#x60;409 idempotency_key_in_use&#x60;. - Same key with a DIFFERENT payload → &#x60;422 idempotency_key_reused&#x60;. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status &gt;&#x3D; 500, &#x60;408&#x60;, &#x60;425&#x60; and &#x60;429&#x60;, and the refusals that happen before anything is done and tell you to fix something outside the request first — &#x60;connection_reauth_required&#x60;, &#x60;listing_inactive&#x60;, and the rate/daily limits. Every other answer, including a final refusal such as &#x60;422 airbnb_rejected&#x60;, is stored and replayed.
@@ -542,8 +545,8 @@ module Repull
542
545
  data
543
546
  end
544
547
 
545
- # Pre-approve an inquiry
546
- # Pre-approve the Airbnb inquiry on this conversation: the guest who asked about dates may now book them at the listed price, without waiting on you. To change the dates, guests or price, send a special offer instead (&#x60;POST /v1/conversations/{id}/special-offers&#x60;). Find inquiries that need an answer with &#x60;GET /v1/inquiries&#x60; (default &#x60;status&#x3D;open&#x60;); each carries the &#x60;conversationId&#x60; to use here. **Airbnb only**, and only for listings connected to Airbnb directly. A Booking.com, VRBO or direct-booking conversation, or an Airbnb one relayed through a PMS (Hostaway, Guesty), returns &#x60;422 channel_not_supported&#x60; and nothing is sent. The inquiry is marked &#x60;pre_approved&#x60; everywhere, the same as pre-approving in Airbnb. An Airbnb refusal is never reported as a success: an inquiry that already moved on is &#x60;409 inquiry_no_longer_open&#x60;, an expired one &#x60;409 inquiry_expired&#x60;, a conversation that already has a booking &#x60;409 conversation_already_booked&#x60;. Send &#x60;Idempotency-Key&#x60;: a repeat with the same key replays the first response instead of acting twice (a &#x60;409 idempotency_key_in_use&#x60; while the first is still running). A 5xx, a &#x60;429 airbnb_rate_limited&#x60; or a &#x60;403 connection_reauth_required&#x60; is not stored — nothing was done — so retrying with the same key reaches Airbnb again.
548
+ # Pre-approve an inquiry (Airbnb, VRBO)
549
+ # Pre-approve the inquiry on this conversation: the guest who asked about dates may now book them at the listed price, without waiting on you. To change the dates, guests or price, send a special offer instead (&#x60;POST /v1/conversations/{id}/special-offers&#x60;). Find inquiries that need an answer with &#x60;GET /v1/inquiries&#x60; (default &#x60;status&#x3D;open&#x60;); each carries the &#x60;conversationId&#x60; to use here. One endpoint for every channel with pre-approvals: **Airbnb** (listings connected directly) and **VRBO**. A Booking.com or direct-booking conversation, or an Airbnb one relayed through a PMS (Hostaway, Guesty), returns &#x60;422 channel_not_supported&#x60; and nothing is sent — &#x60;GET /v1/conversations/{id}&#x60; → &#x60;capabilities.canPreApprove&#x60; says where it works. &#x60;blockInstantBooking&#x60; is Airbnb only (VRBO has no such switch: &#x60;422 invalid_params&#x60;). &#x60;message&#x60; is sent to the guest with a VRBO pre-approval (a friendly default otherwise). The inquiry is marked &#x60;pre_approved&#x60; everywhere, the same as pre-approving on the channel. Withdraw it with &#x60;DELETE /v1/conversations/{id}/pre-approval&#x60; (VRBO). A channel’s refusal is never reported as a success: an inquiry that already moved on is &#x60;409 inquiry_no_longer_open&#x60;, an expired one &#x60;409 inquiry_expired&#x60;, a conversation that already has a booking &#x60;409 conversation_already_booked&#x60;. Send &#x60;Idempotency-Key&#x60;: a repeat with the same key replays the first response instead of acting twice (a &#x60;409 idempotency_key_in_use&#x60; while the first is still running). A 5xx, a &#x60;429 airbnb_rate_limited&#x60; or a &#x60;403 connection_reauth_required&#x60; is not stored — nothing was done — so retrying with the same key reaches Airbnb again.
547
550
  # @param id [Integer] Repull conversation id (from &#x60;GET /v1/conversations&#x60; or &#x60;conversationId&#x60; on &#x60;GET /v1/inquiries&#x60;) — not the Airbnb thread id.
548
551
  # @param [Hash] opts the optional parameters
549
552
  # @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged &#x60;Idempotency-Status: cached&#x60; — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → &#x60;409 idempotency_key_in_use&#x60;. - Same key with a DIFFERENT payload → &#x60;422 idempotency_key_reused&#x60;. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status &gt;&#x3D; 500, &#x60;408&#x60;, &#x60;425&#x60; and &#x60;429&#x60;, and the refusals that happen before anything is done and tell you to fix something outside the request first — &#x60;connection_reauth_required&#x60;, &#x60;listing_inactive&#x60;, and the rate/daily limits. Every other answer, including a final refusal such as &#x60;422 airbnb_rejected&#x60;, is stored and replayed.
@@ -607,8 +610,78 @@ module Repull
607
610
  return data, status_code, headers
608
611
  end
609
612
 
613
+ # Preview a special offer
614
+ # See what a special offer would be — as the channel itself recalculates it, with its taxes, service fee and guest total — **without sending anything** to the guest. Same body as `POST /v1/conversations/{id}/special-offers`; the price may be omitted to see only a date or party change, and `{}` shows the current offer recalculated. **VRBO** (its “Edit quote” recalculation). A channel without a preview — Airbnb takes your total as it is — returns `422 preview_not_supported`; `GET /v1/conversations/{id}` → `capabilities.canPreviewOffer` says which. Read-only: safe to call as often as you need while a user edits an offer.
615
+ # @param id [Integer] Repull conversation id (from &#x60;GET /v1/conversations&#x60; or &#x60;conversationId&#x60; on &#x60;GET /v1/inquiries&#x60;) — not the Airbnb thread id.
616
+ # @param [Hash] opts the optional parameters
617
+ # @option opts [PreviewConversationSpecialOfferRequest] :preview_conversation_special_offer_request
618
+ # @return [CreateConversationSpecialOffer201Response]
619
+ def preview_conversation_special_offer(id, opts = {})
620
+ data, _status_code, _headers = preview_conversation_special_offer_with_http_info(id, opts)
621
+ data
622
+ end
623
+
624
+ # Preview a special offer
625
+ # See what a special offer would be — as the channel itself recalculates it, with its taxes, service fee and guest total — **without sending anything** to the guest. Same body as &#x60;POST /v1/conversations/{id}/special-offers&#x60;; the price may be omitted to see only a date or party change, and &#x60;{}&#x60; shows the current offer recalculated. **VRBO** (its “Edit quote” recalculation). A channel without a preview — Airbnb takes your total as it is — returns &#x60;422 preview_not_supported&#x60;; &#x60;GET /v1/conversations/{id}&#x60; → &#x60;capabilities.canPreviewOffer&#x60; says which. Read-only: safe to call as often as you need while a user edits an offer.
626
+ # @param id [Integer] Repull conversation id (from &#x60;GET /v1/conversations&#x60; or &#x60;conversationId&#x60; on &#x60;GET /v1/inquiries&#x60;) — not the Airbnb thread id.
627
+ # @param [Hash] opts the optional parameters
628
+ # @option opts [PreviewConversationSpecialOfferRequest] :preview_conversation_special_offer_request
629
+ # @return [Array<(CreateConversationSpecialOffer201Response, Integer, Hash)>] CreateConversationSpecialOffer201Response data, response status code and response headers
630
+ def preview_conversation_special_offer_with_http_info(id, opts = {})
631
+ if @api_client.config.debugging
632
+ @api_client.config.logger.debug 'Calling API: ConversationsApi.preview_conversation_special_offer ...'
633
+ end
634
+ # verify the required parameter 'id' is set
635
+ if @api_client.config.client_side_validation && id.nil?
636
+ fail ArgumentError, "Missing the required parameter 'id' when calling ConversationsApi.preview_conversation_special_offer"
637
+ end
638
+ # resource path
639
+ local_var_path = '/v1/conversations/{id}/special-offers/preview'.sub('{id}', CGI.escape(id.to_s))
640
+
641
+ # query parameters
642
+ query_params = opts[:query_params] || {}
643
+
644
+ # header parameters
645
+ header_params = opts[:header_params] || {}
646
+ # HTTP header 'Accept' (if needed)
647
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
648
+ # HTTP header 'Content-Type'
649
+ content_type = @api_client.select_header_content_type(['application/json'])
650
+ if !content_type.nil?
651
+ header_params['Content-Type'] = content_type
652
+ end
653
+
654
+ # form parameters
655
+ form_params = opts[:form_params] || {}
656
+
657
+ # http body (model)
658
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(opts[:'preview_conversation_special_offer_request'])
659
+
660
+ # return_type
661
+ return_type = opts[:debug_return_type] || 'CreateConversationSpecialOffer201Response'
662
+
663
+ # auth_names
664
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
665
+
666
+ new_options = opts.merge(
667
+ :operation => :"ConversationsApi.preview_conversation_special_offer",
668
+ :header_params => header_params,
669
+ :query_params => query_params,
670
+ :form_params => form_params,
671
+ :body => post_body,
672
+ :auth_names => auth_names,
673
+ :return_type => return_type
674
+ )
675
+
676
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
677
+ if @api_client.config.debugging
678
+ @api_client.config.logger.debug "API called: ConversationsApi#preview_conversation_special_offer\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
679
+ end
680
+ return data, status_code, headers
681
+ end
682
+
610
683
  # Send a message to the guest
611
- # Sends a message to the guest on this conversation and records it in the thread. Omit `channel` and the message goes out on whichever channel the conversation already uses (Airbnb, Booking.com, SMS, email or the direct-booking site) — that is the right default. Pass `channel` only to force a specific one. The message is attributed to the API: it is recorded with `aiGenerated` false so an API send is never counted as an automated reply. ### Airbnb rewrites links — check `contentRewritten` Airbnb rejects guest messages containing a link, an email address or a phone number, and names the offending text. When that happens the offending fragment is stripped and the remainder is re-sent once, which means **the guest receives a message that is not the one you wrote**. Reporting that as a plain success would be a lie, so every response carries `contentRewritten`; when it is `true`, `deliveredContent` is the text that actually reached the guest. Check it before assuming your message went out verbatim. When the text cannot be salvaged (the link is most of the message) nothing is delivered and the call returns `422 message_not_sent` with the channel's verbatim refusal in `statusReason`. Send `Idempotency-Key` — without it, retrying after a network timeout sends the guest the same message twice. ### Attachments Send files with `attachments: [{ url, contentType?, filename? }]` — public `https://` URLs, up to 5 per request, 10 MB each. `message` may be omitted when there are attachments (except on Booking.com). Repull downloads each file, reads its real type from the bytes, keeps a durable copy and delivers it through the channel's own file flow. **Every file is checked before anything is sent**: if one is unreachable, too large or of a type the channel refuses, the call returns 422 naming the file (`index`) and the guest receives nothing. | Channel | Accepted types | Text | How it arrives | |---|---|---|---| | Airbnb | JPEG, PNG, GIF, WebP (converted to JPEG), MP4, QuickTime | optional | each file as its own message, then the text as a separate message | | Booking.com | JPEG, PNG | **required** | one message carrying the text and every file | | SMS, email, direct-booking site chat | — | — | `422 attachments_not_supported`, nothing sent | Airbnb does not allow files in pre-booking (inquiry) conversations; that refusal comes back as `422 message_not_sent`. Because Airbnb delivers files one message at a time, a later file can be refused after earlier ones arrived — that returns `422 message_partially_sent` with `parts` saying exactly which messages reached the guest; resend only the rest. The response's `attachments` lists each file's durable `url`, and `parts` lists every channel message the send produced. Read-back (`GET /v1/conversations/{id}/messages`) shows the same files in each message's `attachments`. **Inactive listings:** a conversation that belongs to an inactive listing returns `403 listing_inactive` and no message is sent. Activate the listing first.
684
+ # Sends a message to the guest on this conversation and records it in the thread. Omit `channel` and the message goes out on whichever channel the conversation already uses (Airbnb, Booking.com, VRBO, SMS, email or the direct-booking site) — that is the right default. Pass `channel` only to force a specific one. The message is attributed to the API: it is recorded with `aiGenerated` false so an API send is never counted as an automated reply. ### Airbnb rewrites links — check `contentRewritten` Airbnb rejects guest messages containing a link, an email address or a phone number, and names the offending text. When that happens the offending fragment is stripped and the remainder is re-sent once, which means **the guest receives a message that is not the one you wrote**. Reporting that as a plain success would be a lie, so every response carries `contentRewritten`; when it is `true`, `deliveredContent` is the text that actually reached the guest. Check it before assuming your message went out verbatim. When the text cannot be salvaged (the link is most of the message) nothing is delivered and the call returns `422 message_not_sent` with the channel's verbatim refusal in `statusReason`. Send `Idempotency-Key` — without it, retrying after a network timeout sends the guest the same message twice. ### Attachments Send files with `attachments: [{ url, contentType?, filename? }]` — public `https://` URLs, up to 5 per request, 10 MB each. `message` may be omitted when there are attachments (except on Booking.com). Repull downloads each file, reads its real type from the bytes, keeps a durable copy and delivers it through the channel's own file flow. **Every file is checked before anything is sent**: if one is unreachable, too large or of a type the channel refuses, the call returns 422 naming the file (`index`) and the guest receives nothing. | Channel | Accepted types | Text | How it arrives | |---|---|---|---| | Airbnb | JPEG, PNG, GIF, WebP (converted to JPEG), MP4, QuickTime | optional | each file as its own message, then the text as a separate message | | Booking.com | JPEG, PNG | **required** | one message carrying the text and every file | | VRBO, SMS, email, direct-booking site chat | — | — | `422 attachments_not_supported`, nothing sent | Airbnb does not allow files in pre-booking (inquiry) conversations; that refusal comes back as `422 message_not_sent`. Because Airbnb delivers files one message at a time, a later file can be refused after earlier ones arrived — that returns `422 message_partially_sent` with `parts` saying exactly which messages reached the guest; resend only the rest. The response's `attachments` lists each file's durable `url`, and `parts` lists every channel message the send produced. Read-back (`GET /v1/conversations/{id}/messages`) shows the same files in each message's `attachments`. **Inactive listings:** a conversation that belongs to an inactive listing returns `403 listing_inactive` and no message is sent. Activate the listing first.
612
685
  # @param id [Integer] Internal Repull thread id.
613
686
  # @param send_message_request [SendMessageRequest]
614
687
  # @param [Hash] opts the optional parameters
@@ -620,7 +693,7 @@ module Repull
620
693
  end
621
694
 
622
695
  # Send a message to the guest
623
- # Sends a message to the guest on this conversation and records it in the thread. Omit &#x60;channel&#x60; and the message goes out on whichever channel the conversation already uses (Airbnb, Booking.com, SMS, email or the direct-booking site) — that is the right default. Pass &#x60;channel&#x60; only to force a specific one. The message is attributed to the API: it is recorded with &#x60;aiGenerated&#x60; false so an API send is never counted as an automated reply. ### Airbnb rewrites links — check &#x60;contentRewritten&#x60; Airbnb rejects guest messages containing a link, an email address or a phone number, and names the offending text. When that happens the offending fragment is stripped and the remainder is re-sent once, which means **the guest receives a message that is not the one you wrote**. Reporting that as a plain success would be a lie, so every response carries &#x60;contentRewritten&#x60;; when it is &#x60;true&#x60;, &#x60;deliveredContent&#x60; is the text that actually reached the guest. Check it before assuming your message went out verbatim. When the text cannot be salvaged (the link is most of the message) nothing is delivered and the call returns &#x60;422 message_not_sent&#x60; with the channel&#39;s verbatim refusal in &#x60;statusReason&#x60;. Send &#x60;Idempotency-Key&#x60; — without it, retrying after a network timeout sends the guest the same message twice. ### Attachments Send files with &#x60;attachments: [{ url, contentType?, filename? }]&#x60; — public &#x60;https://&#x60; URLs, up to 5 per request, 10 MB each. &#x60;message&#x60; may be omitted when there are attachments (except on Booking.com). Repull downloads each file, reads its real type from the bytes, keeps a durable copy and delivers it through the channel&#39;s own file flow. **Every file is checked before anything is sent**: if one is unreachable, too large or of a type the channel refuses, the call returns 422 naming the file (&#x60;index&#x60;) and the guest receives nothing. | Channel | Accepted types | Text | How it arrives | |---|---|---|---| | Airbnb | JPEG, PNG, GIF, WebP (converted to JPEG), MP4, QuickTime | optional | each file as its own message, then the text as a separate message | | Booking.com | JPEG, PNG | **required** | one message carrying the text and every file | | SMS, email, direct-booking site chat | — | — | &#x60;422 attachments_not_supported&#x60;, nothing sent | Airbnb does not allow files in pre-booking (inquiry) conversations; that refusal comes back as &#x60;422 message_not_sent&#x60;. Because Airbnb delivers files one message at a time, a later file can be refused after earlier ones arrived — that returns &#x60;422 message_partially_sent&#x60; with &#x60;parts&#x60; saying exactly which messages reached the guest; resend only the rest. The response&#39;s &#x60;attachments&#x60; lists each file&#39;s durable &#x60;url&#x60;, and &#x60;parts&#x60; lists every channel message the send produced. Read-back (&#x60;GET /v1/conversations/{id}/messages&#x60;) shows the same files in each message&#39;s &#x60;attachments&#x60;. **Inactive listings:** a conversation that belongs to an inactive listing returns &#x60;403 listing_inactive&#x60; and no message is sent. Activate the listing first.
696
+ # Sends a message to the guest on this conversation and records it in the thread. Omit &#x60;channel&#x60; and the message goes out on whichever channel the conversation already uses (Airbnb, Booking.com, VRBO, SMS, email or the direct-booking site) — that is the right default. Pass &#x60;channel&#x60; only to force a specific one. The message is attributed to the API: it is recorded with &#x60;aiGenerated&#x60; false so an API send is never counted as an automated reply. ### Airbnb rewrites links — check &#x60;contentRewritten&#x60; Airbnb rejects guest messages containing a link, an email address or a phone number, and names the offending text. When that happens the offending fragment is stripped and the remainder is re-sent once, which means **the guest receives a message that is not the one you wrote**. Reporting that as a plain success would be a lie, so every response carries &#x60;contentRewritten&#x60;; when it is &#x60;true&#x60;, &#x60;deliveredContent&#x60; is the text that actually reached the guest. Check it before assuming your message went out verbatim. When the text cannot be salvaged (the link is most of the message) nothing is delivered and the call returns &#x60;422 message_not_sent&#x60; with the channel&#39;s verbatim refusal in &#x60;statusReason&#x60;. Send &#x60;Idempotency-Key&#x60; — without it, retrying after a network timeout sends the guest the same message twice. ### Attachments Send files with &#x60;attachments: [{ url, contentType?, filename? }]&#x60; — public &#x60;https://&#x60; URLs, up to 5 per request, 10 MB each. &#x60;message&#x60; may be omitted when there are attachments (except on Booking.com). Repull downloads each file, reads its real type from the bytes, keeps a durable copy and delivers it through the channel&#39;s own file flow. **Every file is checked before anything is sent**: if one is unreachable, too large or of a type the channel refuses, the call returns 422 naming the file (&#x60;index&#x60;) and the guest receives nothing. | Channel | Accepted types | Text | How it arrives | |---|---|---|---| | Airbnb | JPEG, PNG, GIF, WebP (converted to JPEG), MP4, QuickTime | optional | each file as its own message, then the text as a separate message | | Booking.com | JPEG, PNG | **required** | one message carrying the text and every file | | VRBO, SMS, email, direct-booking site chat | — | — | &#x60;422 attachments_not_supported&#x60;, nothing sent | Airbnb does not allow files in pre-booking (inquiry) conversations; that refusal comes back as &#x60;422 message_not_sent&#x60;. Because Airbnb delivers files one message at a time, a later file can be refused after earlier ones arrived — that returns &#x60;422 message_partially_sent&#x60; with &#x60;parts&#x60; saying exactly which messages reached the guest; resend only the rest. The response&#39;s &#x60;attachments&#x60; lists each file&#39;s durable &#x60;url&#x60;, and &#x60;parts&#x60; lists every channel message the send produced. Read-back (&#x60;GET /v1/conversations/{id}/messages&#x60;) shows the same files in each message&#39;s &#x60;attachments&#x60;. **Inactive listings:** a conversation that belongs to an inactive listing returns &#x60;403 listing_inactive&#x60; and no message is sent. Activate the listing first.
624
697
  # @param id [Integer] Internal Repull thread id.
625
698
  # @param send_message_request [SendMessageRequest]
626
699
  # @param [Hash] opts the optional parameters
@@ -688,10 +761,73 @@ module Repull
688
761
  return data, status_code, headers
689
762
  end
690
763
 
764
+ # Withdraw a pre-approval
765
+ # Withdraw the live pre-approval (or offer) on this conversation: the guest can no longer book on it, and the inquiry is open again. **VRBO**. On Airbnb a pre-approval is a special offer — withdraw it with `DELETE /v1/conversations/{id}/special-offers/{offerId}`; here it is `422 channel_not_supported`. `GET /v1/conversations/{id}` → `capabilities.canWithdraw` says whether there is something to withdraw.
766
+ # @param id [Integer] Repull conversation id (from &#x60;GET /v1/conversations&#x60; or &#x60;conversationId&#x60; on &#x60;GET /v1/inquiries&#x60;) — not the Airbnb thread id.
767
+ # @param [Hash] opts the optional parameters
768
+ # @return [WithdrawConversationPreapproval200Response]
769
+ def withdraw_conversation_preapproval(id, opts = {})
770
+ data, _status_code, _headers = withdraw_conversation_preapproval_with_http_info(id, opts)
771
+ data
772
+ end
773
+
774
+ # Withdraw a pre-approval
775
+ # Withdraw the live pre-approval (or offer) on this conversation: the guest can no longer book on it, and the inquiry is open again. **VRBO**. On Airbnb a pre-approval is a special offer — withdraw it with &#x60;DELETE /v1/conversations/{id}/special-offers/{offerId}&#x60;; here it is &#x60;422 channel_not_supported&#x60;. &#x60;GET /v1/conversations/{id}&#x60; → &#x60;capabilities.canWithdraw&#x60; says whether there is something to withdraw.
776
+ # @param id [Integer] Repull conversation id (from &#x60;GET /v1/conversations&#x60; or &#x60;conversationId&#x60; on &#x60;GET /v1/inquiries&#x60;) — not the Airbnb thread id.
777
+ # @param [Hash] opts the optional parameters
778
+ # @return [Array<(WithdrawConversationPreapproval200Response, Integer, Hash)>] WithdrawConversationPreapproval200Response data, response status code and response headers
779
+ def withdraw_conversation_preapproval_with_http_info(id, opts = {})
780
+ if @api_client.config.debugging
781
+ @api_client.config.logger.debug 'Calling API: ConversationsApi.withdraw_conversation_preapproval ...'
782
+ end
783
+ # verify the required parameter 'id' is set
784
+ if @api_client.config.client_side_validation && id.nil?
785
+ fail ArgumentError, "Missing the required parameter 'id' when calling ConversationsApi.withdraw_conversation_preapproval"
786
+ end
787
+ # resource path
788
+ local_var_path = '/v1/conversations/{id}/pre-approval'.sub('{id}', CGI.escape(id.to_s))
789
+
790
+ # query parameters
791
+ query_params = opts[:query_params] || {}
792
+
793
+ # header parameters
794
+ header_params = opts[:header_params] || {}
795
+ # HTTP header 'Accept' (if needed)
796
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
797
+
798
+ # form parameters
799
+ form_params = opts[:form_params] || {}
800
+
801
+ # http body (model)
802
+ post_body = opts[:debug_body]
803
+
804
+ # return_type
805
+ return_type = opts[:debug_return_type] || 'WithdrawConversationPreapproval200Response'
806
+
807
+ # auth_names
808
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
809
+
810
+ new_options = opts.merge(
811
+ :operation => :"ConversationsApi.withdraw_conversation_preapproval",
812
+ :header_params => header_params,
813
+ :query_params => query_params,
814
+ :form_params => form_params,
815
+ :body => post_body,
816
+ :auth_names => auth_names,
817
+ :return_type => return_type
818
+ )
819
+
820
+ data, status_code, headers = @api_client.call_api(:DELETE, local_var_path, new_options)
821
+ if @api_client.config.debugging
822
+ @api_client.config.logger.debug "API called: ConversationsApi#withdraw_conversation_preapproval\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
823
+ end
824
+ return data, status_code, headers
825
+ end
826
+
691
827
  # Withdraw a special offer
692
- # Withdraw a special offer the guest has not booked yet, so it can no longer be booked. An offer the guest already booked cannot be withdrawn — Airbnb refuses with `409 inquiry_no_longer_open`; cancel the booking instead.
828
+ # Withdraw a special offer the guest has not booked yet, so it can no longer be booked (VRBO: `offerId` = `current`, the same as `DELETE /v1/conversations/{id}/pre-approval`). An offer the guest already booked cannot be withdrawn — the channel refuses with `409 inquiry_no_longer_open`; cancel the booking instead.
693
829
  # @param id [Integer] Repull conversation id (from &#x60;GET /v1/conversations&#x60; or &#x60;conversationId&#x60; on &#x60;GET /v1/inquiries&#x60;) — not the Airbnb thread id.
694
- # @param offer_id [String] The special offer’s &#x60;id&#x60;, as returned by &#x60;POST /v1/conversations/{id}/special-offers&#x60;.
830
+ # @param offer_id [String] The special offer’s &#x60;id&#x60;, as returned by &#x60;POST /v1/conversations/{id}/special-offers&#x60;. On VRBO, where a conversation has one live offer, &#x60;current&#x60;.
695
831
  # @param [Hash] opts the optional parameters
696
832
  # @return [WithdrawConversationSpecialOffer200Response]
697
833
  def withdraw_conversation_special_offer(id, offer_id, opts = {})
@@ -700,9 +836,9 @@ module Repull
700
836
  end
701
837
 
702
838
  # Withdraw a special offer
703
- # Withdraw a special offer the guest has not booked yet, so it can no longer be booked. An offer the guest already booked cannot be withdrawn — Airbnb refuses with &#x60;409 inquiry_no_longer_open&#x60;; cancel the booking instead.
839
+ # Withdraw a special offer the guest has not booked yet, so it can no longer be booked (VRBO: &#x60;offerId&#x60; &#x3D; &#x60;current&#x60;, the same as &#x60;DELETE /v1/conversations/{id}/pre-approval&#x60;). An offer the guest already booked cannot be withdrawn — the channel refuses with &#x60;409 inquiry_no_longer_open&#x60;; cancel the booking instead.
704
840
  # @param id [Integer] Repull conversation id (from &#x60;GET /v1/conversations&#x60; or &#x60;conversationId&#x60; on &#x60;GET /v1/inquiries&#x60;) — not the Airbnb thread id.
705
- # @param offer_id [String] The special offer’s &#x60;id&#x60;, as returned by &#x60;POST /v1/conversations/{id}/special-offers&#x60;.
841
+ # @param offer_id [String] The special offer’s &#x60;id&#x60;, as returned by &#x60;POST /v1/conversations/{id}/special-offers&#x60;. On VRBO, where a conversation has one live offer, &#x60;current&#x60;.
706
842
  # @param [Hash] opts the optional parameters
707
843
  # @return [Array<(WithdrawConversationSpecialOffer200Response, Integer, Hash)>] WithdrawConversationSpecialOffer200Response data, response status code and response headers
708
844
  def withdraw_conversation_special_offer_with_http_info(id, offer_id, opts = {})
@@ -77,20 +77,20 @@ module Repull
77
77
  end
78
78
 
79
79
  # Per-channel connectivity health
80
- # Reports reachability and auth state for one channel (`airbnb`, `booking`, `vrbo`, `plumguide`). Use it to tell \"the channel is down\" apart from \"this workspace's connection expired\".
80
+ # Reports reachability and auth state for one channel (`airbnb`, `booking`, `vrbo`, `plumguide`). Use it to tell \"the channel is down\" apart from \"this workspace's connection expired\". `200` when `status` is `ok`, `503` when `degraded` or `down` (the body's `status` and `message` say which and why). **`vrbo`** reports the connector's own signals in a `vrbo` block: connected accounts, accounts VRBO signed out (their bookings, messages and calendar stop until reconnected — `down`), accounts whose inbox sync is late (`degraded`), and the calendar push queue backlog and its oldest wait (`degraded` past 3 hours). Its rate is failed calendar pushes over finished ones in the last 3 hours (`vrbo.window_hours`; `refresh_attempts_24h` / `refresh_rejections_24h` count that window for VRBO), judged only once at least 50 pushes finished and at least 5 failed — VRBO pushes run in bursts, so a day-long window would keep reporting a problem already fixed.
81
81
  # @param channel [String]
82
82
  # @param [Hash] opts the optional parameters
83
- # @return [Hash<String, Object>]
83
+ # @return [GetChannelHealth200Response]
84
84
  def get_channel_health(channel, opts = {})
85
85
  data, _status_code, _headers = get_channel_health_with_http_info(channel, opts)
86
86
  data
87
87
  end
88
88
 
89
89
  # Per-channel connectivity health
90
- # Reports reachability and auth state for one channel (&#x60;airbnb&#x60;, &#x60;booking&#x60;, &#x60;vrbo&#x60;, &#x60;plumguide&#x60;). Use it to tell \&quot;the channel is down\&quot; apart from \&quot;this workspace&#39;s connection expired\&quot;.
90
+ # Reports reachability and auth state for one channel (&#x60;airbnb&#x60;, &#x60;booking&#x60;, &#x60;vrbo&#x60;, &#x60;plumguide&#x60;). Use it to tell \&quot;the channel is down\&quot; apart from \&quot;this workspace&#39;s connection expired\&quot;. &#x60;200&#x60; when &#x60;status&#x60; is &#x60;ok&#x60;, &#x60;503&#x60; when &#x60;degraded&#x60; or &#x60;down&#x60; (the body&#39;s &#x60;status&#x60; and &#x60;message&#x60; say which and why). **&#x60;vrbo&#x60;** reports the connector&#39;s own signals in a &#x60;vrbo&#x60; block: connected accounts, accounts VRBO signed out (their bookings, messages and calendar stop until reconnected — &#x60;down&#x60;), accounts whose inbox sync is late (&#x60;degraded&#x60;), and the calendar push queue backlog and its oldest wait (&#x60;degraded&#x60; past 3 hours). Its rate is failed calendar pushes over finished ones in the last 3 hours (&#x60;vrbo.window_hours&#x60;; &#x60;refresh_attempts_24h&#x60; / &#x60;refresh_rejections_24h&#x60; count that window for VRBO), judged only once at least 50 pushes finished and at least 5 failed — VRBO pushes run in bursts, so a day-long window would keep reporting a problem already fixed.
91
91
  # @param channel [String]
92
92
  # @param [Hash] opts the optional parameters
93
- # @return [Array<(Hash<String, Object>, Integer, Hash)>] Hash<String, Object> data, response status code and response headers
93
+ # @return [Array<(GetChannelHealth200Response, Integer, Hash)>] GetChannelHealth200Response data, response status code and response headers
94
94
  def get_channel_health_with_http_info(channel, opts = {})
95
95
  if @api_client.config.debugging
96
96
  @api_client.config.logger.debug 'Calling API: HealthApi.get_channel_health ...'
@@ -122,7 +122,7 @@ module Repull
122
122
  post_body = opts[:debug_body]
123
123
 
124
124
  # return_type
125
- return_type = opts[:debug_return_type] || 'Hash<String, Object>'
125
+ return_type = opts[:debug_return_type] || 'GetChannelHealth200Response'
126
126
 
127
127
  # auth_names
128
128
  auth_names = opts[:debug_auth_names] || []
@@ -437,6 +437,69 @@ module Repull
437
437
  return data, status_code, headers
438
438
  end
439
439
 
440
+ # Calendar sync status per channel
441
+ # Is this listing's calendar — prices, minimum stays, availability — actually on every channel it is connected to, and if not, which nights and why. One shape for every channel. Every push records each night's outcome per channel; a night the channel does not show as sent is listed in `problems` with the channel's own reason (a price the channel still shows differently, a block it refused, a unit that is not live, a night held by a booking or an imported calendar). A later successful push clears it. **VRBO** pushes run through a paced queue — VRBO accepts about 90 calendar writes a minute per account, and only what differs on VRBO is sent — so the `vrbo` entry adds `queue`: whether a push is waiting or running now, and what the last one did (prices and minimum stays changed, blocks, calls, nights still differing). Future nights only. `problems` lists up to 100 nights per channel; `nightsWithProblems` is always the full count. Returns `403 listing_inactive` for an inactive listing.
442
+ # @param id [Integer] Repull listing id.
443
+ # @param [Hash] opts the optional parameters
444
+ # @return [GetListingCalendarSync200Response]
445
+ def get_listing_calendar_sync(id, opts = {})
446
+ data, _status_code, _headers = get_listing_calendar_sync_with_http_info(id, opts)
447
+ data
448
+ end
449
+
450
+ # Calendar sync status per channel
451
+ # Is this listing&#39;s calendar — prices, minimum stays, availability — actually on every channel it is connected to, and if not, which nights and why. One shape for every channel. Every push records each night&#39;s outcome per channel; a night the channel does not show as sent is listed in &#x60;problems&#x60; with the channel&#39;s own reason (a price the channel still shows differently, a block it refused, a unit that is not live, a night held by a booking or an imported calendar). A later successful push clears it. **VRBO** pushes run through a paced queue — VRBO accepts about 90 calendar writes a minute per account, and only what differs on VRBO is sent — so the &#x60;vrbo&#x60; entry adds &#x60;queue&#x60;: whether a push is waiting or running now, and what the last one did (prices and minimum stays changed, blocks, calls, nights still differing). Future nights only. &#x60;problems&#x60; lists up to 100 nights per channel; &#x60;nightsWithProblems&#x60; is always the full count. Returns &#x60;403 listing_inactive&#x60; for an inactive listing.
452
+ # @param id [Integer] Repull listing id.
453
+ # @param [Hash] opts the optional parameters
454
+ # @return [Array<(GetListingCalendarSync200Response, Integer, Hash)>] GetListingCalendarSync200Response data, response status code and response headers
455
+ def get_listing_calendar_sync_with_http_info(id, opts = {})
456
+ if @api_client.config.debugging
457
+ @api_client.config.logger.debug 'Calling API: ListingsApi.get_listing_calendar_sync ...'
458
+ end
459
+ # verify the required parameter 'id' is set
460
+ if @api_client.config.client_side_validation && id.nil?
461
+ fail ArgumentError, "Missing the required parameter 'id' when calling ListingsApi.get_listing_calendar_sync"
462
+ end
463
+ # resource path
464
+ local_var_path = '/v1/listings/{id}/calendar-sync'.sub('{id}', CGI.escape(id.to_s))
465
+
466
+ # query parameters
467
+ query_params = opts[:query_params] || {}
468
+
469
+ # header parameters
470
+ header_params = opts[:header_params] || {}
471
+ # HTTP header 'Accept' (if needed)
472
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
473
+
474
+ # form parameters
475
+ form_params = opts[:form_params] || {}
476
+
477
+ # http body (model)
478
+ post_body = opts[:debug_body]
479
+
480
+ # return_type
481
+ return_type = opts[:debug_return_type] || 'GetListingCalendarSync200Response'
482
+
483
+ # auth_names
484
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
485
+
486
+ new_options = opts.merge(
487
+ :operation => :"ListingsApi.get_listing_calendar_sync",
488
+ :header_params => header_params,
489
+ :query_params => query_params,
490
+ :form_params => form_params,
491
+ :body => post_body,
492
+ :auth_names => auth_names,
493
+ :return_type => return_type
494
+ )
495
+
496
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
497
+ if @api_client.config.debugging
498
+ @api_client.config.logger.debug "API called: ListingsApi#get_listing_calendar_sync\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
499
+ end
500
+ return data, status_code, headers
501
+ end
502
+
440
503
  # Get a listing's channel markups
441
504
  # The markup each channel adds to this listing's price. A listing's price on a channel is its own nightly price plus the channel's markup: a $200 night with a 35% Airbnb markup is sent to Airbnb as $270. The calendar keeps the listing's own price (`GET /v1/availability/{propertyId}` returns it); the markup is added only when a price is sent to the channel. - **Airbnb** — one markup per listing. - **Booking.com** — one markup per **property**, shared by every listing priced through it (`listingIds` names them). Returns `404 not_found` for a listing that does not exist or is not in this workspace, and `403 listing_inactive` for an inactive one.
442
505
  # @param id [String] Repull listing id.
@@ -1153,7 +1216,7 @@ module Repull
1153
1216
  end
1154
1217
 
1155
1218
  # Take a listing off the market
1156
- # Stop this listing being sold, on every channel it is connected to, in one call. What that means differs per channel and you do not have to know which is which. On **Airbnb** the live listing is deactivated with a valid deactivation reason and then READ BACK — Airbnb accepts some deactivations and leaves the listing up, so \"we sent the request\" is never reported as success. On **Booking.com** there is no unlist at all; the equivalent is closing the room's availability across the whole forward window, which is what happens. **This is not the same as deactivating the listing in Repull.** The two get confused because both sound like removal, and they have opposite consequences: | | Take offline (this endpoint) | Deactivate in Repull (`PATCH /v1/listings/{id}` `{\"active\": false}`) | |---|---|---| | The guest-facing listing | **Stops taking bookings** | Stays live and keeps taking bookings | | Billing and plan limits | Unchanged | No longer billed, no longer counts toward the cap | | API access to the listing | Unchanged — you can still read and write it | `403 listing_inactive` until reactivated | | Reverse it with | `POST /v1/listings/{id}/online` | `PATCH /v1/listings/{id}` `{\"active\": true}` | | Data kept | Yes | Yes, and it keeps syncing | Neither one deletes anything, on either side. **The answer is per channel item.** A listing can sit on several Airbnb connections and a Booking.com property at once; they fail independently and a partial result is the ordinary outcome, so every item reports its own `state`, `code` and `message` and there is no top-level success flag to mislead you. Nothing is rolled back — re-send the same request to retry the items that did not land. **Booking.com ambiguity is reported, not fanned out.** A listing mapped to more than one active Booking.com property comes back with that item refused (`ambiguous_booking_mapping`) while the Airbnb items still run: closing the wrong property's availability takes real inventory off sale, and taking a listing off Airbnb is not less urgent because its Booking.com mapping is untidy. Name the property with `hotelId` and send it again. 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.
1219
+ # Stop this listing being sold, on every channel it is connected to, in one call. What that means differs per channel and you do not have to know which is which. On **Airbnb** the live listing is deactivated with a valid deactivation reason and then READ BACK — Airbnb accepts some deactivations and leaves the listing up, so \"we sent the request\" is never reported as success. On **Booking.com** there is no unlist at all; the equivalent is closing the room's availability across the whole forward window, which is what happens. On **VRBO** each mapped unit is hidden (VRBO's own \"Hide listing\") and read back — a hidden unit is out of VRBO search and cannot be booked; its item carries the VRBO listing number as `platformId`. **This is not the same as deactivating the listing in Repull.** The two get confused because both sound like removal, and they have opposite consequences: | | Take offline (this endpoint) | Deactivate in Repull (`PATCH /v1/listings/{id}` `{\"active\": false}`) | |---|---|---| | The guest-facing listing | **Stops taking bookings** | Stays live and keeps taking bookings | | Billing and plan limits | Unchanged | No longer billed, no longer counts toward the cap | | API access to the listing | Unchanged — you can still read and write it | `403 listing_inactive` until reactivated | | Reverse it with | `POST /v1/listings/{id}/online` | `PATCH /v1/listings/{id}` `{\"active\": true}` | | Data kept | Yes | Yes, and it keeps syncing | Neither one deletes anything, on either side. **The answer is per channel item.** A listing can sit on several Airbnb connections and a Booking.com property at once; they fail independently and a partial result is the ordinary outcome, so every item reports its own `state`, `code` and `message` and there is no top-level success flag to mislead you. Nothing is rolled back — re-send the same request to retry the items that did not land. **Booking.com ambiguity is reported, not fanned out.** A listing mapped to more than one active Booking.com property comes back with that item refused (`ambiguous_booking_mapping`) while the Airbnb items still run: closing the wrong property's availability takes real inventory off sale, and taking a listing off Airbnb is not less urgent because its Booking.com mapping is untidy. Name the property with `hotelId` and send it again. 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.
1157
1220
  # @param id [Integer] Repull listing id.
1158
1221
  # @param [Hash] opts the optional parameters
1159
1222
  # @option opts [String] :hotel_id Booking.com property to act on, for a listing mapped to more than one. The query-string spelling of the body&#39;s &#x60;hotelId&#x60;; the body wins when both are sent.
@@ -1166,7 +1229,7 @@ module Repull
1166
1229
  end
1167
1230
 
1168
1231
  # Take a listing off the market
1169
- # Stop this listing being sold, on every channel it is connected to, in one call. What that means differs per channel and you do not have to know which is which. On **Airbnb** the live listing is deactivated with a valid deactivation reason and then READ BACK — Airbnb accepts some deactivations and leaves the listing up, so \&quot;we sent the request\&quot; is never reported as success. On **Booking.com** there is no unlist at all; the equivalent is closing the room&#39;s availability across the whole forward window, which is what happens. **This is not the same as deactivating the listing in Repull.** The two get confused because both sound like removal, and they have opposite consequences: | | Take offline (this endpoint) | Deactivate in Repull (&#x60;PATCH /v1/listings/{id}&#x60; &#x60;{\&quot;active\&quot;: false}&#x60;) | |---|---|---| | The guest-facing listing | **Stops taking bookings** | Stays live and keeps taking bookings | | Billing and plan limits | Unchanged | No longer billed, no longer counts toward the cap | | API access to the listing | Unchanged — you can still read and write it | &#x60;403 listing_inactive&#x60; until reactivated | | Reverse it with | &#x60;POST /v1/listings/{id}/online&#x60; | &#x60;PATCH /v1/listings/{id}&#x60; &#x60;{\&quot;active\&quot;: true}&#x60; | | Data kept | Yes | Yes, and it keeps syncing | Neither one deletes anything, on either side. **The answer is per channel item.** A listing can sit on several Airbnb connections and a Booking.com property at once; they fail independently and a partial result is the ordinary outcome, so every item reports its own &#x60;state&#x60;, &#x60;code&#x60; and &#x60;message&#x60; and there is no top-level success flag to mislead you. Nothing is rolled back — re-send the same request to retry the items that did not land. **Booking.com ambiguity is reported, not fanned out.** A listing mapped to more than one active Booking.com property comes back with that item refused (&#x60;ambiguous_booking_mapping&#x60;) while the Airbnb items still run: closing the wrong property&#39;s availability takes real inventory off sale, and taking a listing off Airbnb is not less urgent because its Booking.com mapping is untidy. Name the property with &#x60;hotelId&#x60; and send it again. 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.
1232
+ # Stop this listing being sold, on every channel it is connected to, in one call. What that means differs per channel and you do not have to know which is which. On **Airbnb** the live listing is deactivated with a valid deactivation reason and then READ BACK — Airbnb accepts some deactivations and leaves the listing up, so \&quot;we sent the request\&quot; is never reported as success. On **Booking.com** there is no unlist at all; the equivalent is closing the room&#39;s availability across the whole forward window, which is what happens. On **VRBO** each mapped unit is hidden (VRBO&#39;s own \&quot;Hide listing\&quot;) and read back — a hidden unit is out of VRBO search and cannot be booked; its item carries the VRBO listing number as &#x60;platformId&#x60;. **This is not the same as deactivating the listing in Repull.** The two get confused because both sound like removal, and they have opposite consequences: | | Take offline (this endpoint) | Deactivate in Repull (&#x60;PATCH /v1/listings/{id}&#x60; &#x60;{\&quot;active\&quot;: false}&#x60;) | |---|---|---| | The guest-facing listing | **Stops taking bookings** | Stays live and keeps taking bookings | | Billing and plan limits | Unchanged | No longer billed, no longer counts toward the cap | | API access to the listing | Unchanged — you can still read and write it | &#x60;403 listing_inactive&#x60; until reactivated | | Reverse it with | &#x60;POST /v1/listings/{id}/online&#x60; | &#x60;PATCH /v1/listings/{id}&#x60; &#x60;{\&quot;active\&quot;: true}&#x60; | | Data kept | Yes | Yes, and it keeps syncing | Neither one deletes anything, on either side. **The answer is per channel item.** A listing can sit on several Airbnb connections and a Booking.com property at once; they fail independently and a partial result is the ordinary outcome, so every item reports its own &#x60;state&#x60;, &#x60;code&#x60; and &#x60;message&#x60; and there is no top-level success flag to mislead you. Nothing is rolled back — re-send the same request to retry the items that did not land. **Booking.com ambiguity is reported, not fanned out.** A listing mapped to more than one active Booking.com property comes back with that item refused (&#x60;ambiguous_booking_mapping&#x60;) while the Airbnb items still run: closing the wrong property&#39;s availability takes real inventory off sale, and taking a listing off Airbnb is not less urgent because its Booking.com mapping is untidy. Name the property with &#x60;hotelId&#x60; and send it again. 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.
1170
1233
  # @param id [Integer] Repull listing id.
1171
1234
  # @param [Hash] opts the optional parameters
1172
1235
  # @option opts [String] :hotel_id Booking.com property to act on, for a listing mapped to more than one. The query-string spelling of the body&#39;s &#x60;hotelId&#x60;; the body wins when both are sent.
@@ -1233,7 +1296,7 @@ module Repull
1233
1296
  end
1234
1297
 
1235
1298
  # Put a listing back on the market
1236
- # Put this listing back on sale, on every channel it is connected to. The counterpart of `POST /v1/listings/{id}/offline`, which documents the per-item response and the difference between this and deactivating a listing in Repull. **It does not push content.** On **Airbnb** it re-enables sync and makes the listing available again; anything that changed while the listing was down is still unpublished, so follow with `POST /v1/listings/{id}/publish/airbnb` if the content moved. On **Booking.com** it re-syncs the true calendar rather than opening everything: dates that are genuinely blocked — a reservation, an owner stay — stay blocked, and only the closure `offline` wrote lifts. The two directions are not mirror images, and that is deliberate. **One asymmetry worth planning for.** Taking a listing down passes no billing gate; putting it back up goes through the channel-publish gate. So on a workspace whose subscription has lapsed, `offline` still works and this endpoint answers `402 payment_required` — a listing can be left off the market until billing is sorted out. That refusal is reported as a billing refusal with the action that fixes it, never as a channel error: retrying, or reconnecting the channel, does nothing for it. 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.
1299
+ # Put this listing back on sale, on every channel it is connected to. The counterpart of `POST /v1/listings/{id}/offline`, which documents the per-item response and the difference between this and deactivating a listing in Repull. **It does not push content.** On **Airbnb** it re-enables sync and makes the listing available again; anything that changed while the listing was down is still unpublished, so follow with `POST /v1/listings/{id}/publish/airbnb` if the content moved. On **Booking.com** it re-syncs the true calendar rather than opening everything: dates that are genuinely blocked — a reservation, an owner stay — stay blocked, and only the closure `offline` wrote lifts. On **VRBO** each hidden unit is reactivated (VRBO's own \"Reactivate\") and read back; VRBO can refuse a reactivation (e.g. while it is verifying the property), which comes back as that item's `message`. The two directions are not mirror images, and that is deliberate. **One asymmetry worth planning for.** Taking a listing down passes no billing gate; putting it back up goes through the channel-publish gate. So on a workspace whose subscription has lapsed, `offline` still works and this endpoint answers `402 payment_required` — a listing can be left off the market until billing is sorted out. That refusal is reported as a billing refusal with the action that fixes it, never as a channel error: retrying, or reconnecting the channel, does nothing for it. 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.
1237
1300
  # @param id [Integer] Repull listing id.
1238
1301
  # @param [Hash] opts the optional parameters
1239
1302
  # @option opts [String] :hotel_id Booking.com property to act on, for a listing mapped to more than one. The query-string spelling of the body&#39;s &#x60;hotelId&#x60;; the body wins when both are sent.
@@ -1246,7 +1309,7 @@ module Repull
1246
1309
  end
1247
1310
 
1248
1311
  # Put a listing back on the market
1249
- # Put this listing back on sale, on every channel it is connected to. The counterpart of &#x60;POST /v1/listings/{id}/offline&#x60;, which documents the per-item response and the difference between this and deactivating a listing in Repull. **It does not push content.** On **Airbnb** it re-enables sync and makes the listing available again; anything that changed while the listing was down is still unpublished, so follow with &#x60;POST /v1/listings/{id}/publish/airbnb&#x60; if the content moved. On **Booking.com** it re-syncs the true calendar rather than opening everything: dates that are genuinely blocked — a reservation, an owner stay — stay blocked, and only the closure &#x60;offline&#x60; wrote lifts. The two directions are not mirror images, and that is deliberate. **One asymmetry worth planning for.** Taking a listing down passes no billing gate; putting it back up goes through the channel-publish gate. So on a workspace whose subscription has lapsed, &#x60;offline&#x60; still works and this endpoint answers &#x60;402 payment_required&#x60; — a listing can be left off the market until billing is sorted out. That refusal is reported as a billing refusal with the action that fixes it, never as a channel error: retrying, or reconnecting the channel, does nothing for it. 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.
1312
+ # Put this listing back on sale, on every channel it is connected to. The counterpart of &#x60;POST /v1/listings/{id}/offline&#x60;, which documents the per-item response and the difference between this and deactivating a listing in Repull. **It does not push content.** On **Airbnb** it re-enables sync and makes the listing available again; anything that changed while the listing was down is still unpublished, so follow with &#x60;POST /v1/listings/{id}/publish/airbnb&#x60; if the content moved. On **Booking.com** it re-syncs the true calendar rather than opening everything: dates that are genuinely blocked — a reservation, an owner stay — stay blocked, and only the closure &#x60;offline&#x60; wrote lifts. On **VRBO** each hidden unit is reactivated (VRBO&#39;s own \&quot;Reactivate\&quot;) and read back; VRBO can refuse a reactivation (e.g. while it is verifying the property), which comes back as that item&#39;s &#x60;message&#x60;. The two directions are not mirror images, and that is deliberate. **One asymmetry worth planning for.** Taking a listing down passes no billing gate; putting it back up goes through the channel-publish gate. So on a workspace whose subscription has lapsed, &#x60;offline&#x60; still works and this endpoint answers &#x60;402 payment_required&#x60; — a listing can be left off the market until billing is sorted out. That refusal is reported as a billing refusal with the action that fixes it, never as a channel error: retrying, or reconnecting the channel, does nothing for it. 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.
1250
1313
  # @param id [Integer] Repull listing id.
1251
1314
  # @param [Hash] opts the optional parameters
1252
1315
  # @option opts [String] :hotel_id Booking.com property to act on, for a listing mapped to more than one. The query-string spelling of the body&#39;s &#x60;hotelId&#x60;; the body wins when both are sent.
@@ -92,6 +92,7 @@ module Repull
92
92
  # List properties (older name for /v1/listings)
93
93
  # **`/v1/properties` is the older name for `/v1/listings`** — the same listings, the same ids. It stays for existing integrations; new code should use `/v1/listings`, which is where create, content, publishing and markups live. Cursor-paginated list of properties for the authenticated workspace. Walk pages with `?cursor=<pagination.nextCursor>`; stop when `pagination.hasMore` is `false`. Cursor is opaque base64 — do not parse it. `?offset=` is also accepted as a first-class alias for shallow paging (0..10000) — see the `offset` parameter below. Mutually exclusive with `cursor`. Filters: `q` (substring on name/street/city), `status` (active|inactive|all), `lifecycle_status` (exact match on the listing's lifecycle state). Other unknown params (e.g. `?search=` or `?propertyId=`) are rejected with 422 — no silent unfiltered results. **Incremental sync (only changes since last poll):** pass `?updated_since=<ISO8601>` to receive only properties changed at or after that instant. Each property carries `updatedAt` — the last row of the final page is your next watermark. `updated_since` changes the page ordering to `updatedAt ASC, id ASC` (and the cursor with it); see the parameter description. `GET /v1/listings` does NOT yet accept `updated_since` — use this endpoint for property-side incremental sync. **Inactive properties:** an inactive property keeps syncing, but cannot be read or changed through the API until it is activated. They are only listed when `status` asks for them, and then with `id`, `name`, `status`, `lifecycleStatus`, `channels` and `updatedAt` only — enough to choose what to activate with `PATCH /v1/listings/{id}`.
94
94
  # @param [Hash] opts the optional parameters
95
+ # @option opts [String] :account Only the records of one connected account, as &#x60;provider:externalAccountId&#x60; — the pair from a webhook &#x60;account&#x60; block, &#x60;connect.session.completed&#x60;, or &#x60;GET /v1/connect/{provider}&#x60; → &#x60;accounts&#x60;. A record belongs to an account when it is on that account&#39;s listings and on its channel (a PMS account: came in through that PMS). An account with no listings returns an empty page.
95
96
  # @option opts [Integer] :limit Page size (max 100). Requests over the cap return 422. (default to 50)
96
97
  # @option opts [String] :cursor Opaque cursor returned in the previous response&#39;s &#x60;pagination.nextCursor&#x60;. Omit to fetch the first page.
97
98
  # @option opts [Integer] :offset First-class alias for cursor-based pagination. Mutually exclusive with &#x60;cursor&#x60; — passing both returns 422. Accepts integers in &#x60;[0, 10000]&#x60;; deeper walks must use &#x60;cursor&#x60; (constant per-page cost). The response always includes &#x60;pagination.nextCursor&#x60; so consumers can switch from offset → cursor mid-walk for deep pagination without re-keying. (default to 0)
@@ -110,6 +111,7 @@ module Repull
110
111
  # List properties (older name for /v1/listings)
111
112
  # **&#x60;/v1/properties&#x60; is the older name for &#x60;/v1/listings&#x60;** — the same listings, the same ids. It stays for existing integrations; new code should use &#x60;/v1/listings&#x60;, which is where create, content, publishing and markups live. Cursor-paginated list of properties for the authenticated workspace. Walk pages with &#x60;?cursor&#x3D;&lt;pagination.nextCursor&gt;&#x60;; stop when &#x60;pagination.hasMore&#x60; is &#x60;false&#x60;. Cursor is opaque base64 — do not parse it. &#x60;?offset&#x3D;&#x60; is also accepted as a first-class alias for shallow paging (0..10000) — see the &#x60;offset&#x60; parameter below. Mutually exclusive with &#x60;cursor&#x60;. Filters: &#x60;q&#x60; (substring on name/street/city), &#x60;status&#x60; (active|inactive|all), &#x60;lifecycle_status&#x60; (exact match on the listing&#39;s lifecycle state). Other unknown params (e.g. &#x60;?search&#x3D;&#x60; or &#x60;?propertyId&#x3D;&#x60;) are rejected with 422 — no silent unfiltered results. **Incremental sync (only changes since last poll):** pass &#x60;?updated_since&#x3D;&lt;ISO8601&gt;&#x60; to receive only properties changed at or after that instant. Each property carries &#x60;updatedAt&#x60; — the last row of the final page is your next watermark. &#x60;updated_since&#x60; changes the page ordering to &#x60;updatedAt ASC, id ASC&#x60; (and the cursor with it); see the parameter description. &#x60;GET /v1/listings&#x60; does NOT yet accept &#x60;updated_since&#x60; — use this endpoint for property-side incremental sync. **Inactive properties:** an inactive property keeps syncing, but cannot be read or changed through the API until it is activated. They are only listed when &#x60;status&#x60; asks for them, and then with &#x60;id&#x60;, &#x60;name&#x60;, &#x60;status&#x60;, &#x60;lifecycleStatus&#x60;, &#x60;channels&#x60; and &#x60;updatedAt&#x60; only — enough to choose what to activate with &#x60;PATCH /v1/listings/{id}&#x60;.
112
113
  # @param [Hash] opts the optional parameters
114
+ # @option opts [String] :account Only the records of one connected account, as &#x60;provider:externalAccountId&#x60; — the pair from a webhook &#x60;account&#x60; block, &#x60;connect.session.completed&#x60;, or &#x60;GET /v1/connect/{provider}&#x60; → &#x60;accounts&#x60;. A record belongs to an account when it is on that account&#39;s listings and on its channel (a PMS account: came in through that PMS). An account with no listings returns an empty page.
113
115
  # @option opts [Integer] :limit Page size (max 100). Requests over the cap return 422. (default to 50)
114
116
  # @option opts [String] :cursor Opaque cursor returned in the previous response&#39;s &#x60;pagination.nextCursor&#x60;. Omit to fetch the first page.
115
117
  # @option opts [Integer] :offset First-class alias for cursor-based pagination. Mutually exclusive with &#x60;cursor&#x60; — passing both returns 422. Accepts integers in &#x60;[0, 10000]&#x60;; deeper walks must use &#x60;cursor&#x60; (constant per-page cost). The response always includes &#x60;pagination.nextCursor&#x60; so consumers can switch from offset → cursor mid-walk for deep pagination without re-keying. (default to 0)
@@ -153,6 +155,7 @@ module Repull
153
155
 
154
156
  # query parameters
155
157
  query_params = opts[:query_params] || {}
158
+ query_params[:'account'] = opts[:'account'] if !opts[:'account'].nil?
156
159
  query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil?
157
160
  query_params[:'cursor'] = opts[:'cursor'] if !opts[:'cursor'].nil?
158
161
  query_params[:'offset'] = opts[:'offset'] if !opts[:'offset'].nil?
@@ -384,6 +384,7 @@ module Repull
384
384
  # List reservations
385
385
  # Cursor-paginated list of reservations across all connected PMS platforms. Filter by platform, status, listing, or check-in date range. **Pagination:** Walk pages with `?cursor=` — pass `pagination.nextCursor` from one response back as `?cursor=` on the next request. Stop when `pagination.hasMore` is `false`. `limit` defaults to 50, max 100; requesting more returns 422 (no silent truncation). `?offset=` is also accepted as a first-class alias for shallow paging (0..10000) — see the `offset` parameter below. Mutually exclusive with `cursor`. For deep pagination cursor remains O(1) per page; offset > 10000 returns 422 with a docs link. **Incremental sync (only changes since last poll):** pass `?updated_since=<ISO8601>` to receive only reservations amended, cancelled, or created at or after that instant — no full re-walk. Each row carries `updatedAt`; the last row of the final page is your next watermark. Note that `updated_since` changes the page ordering to `updatedAt ASC, id ASC` (and the cursor with it) so mid-walk amendments cannot be skipped — see the parameter description for the full contract. Reservations on inactive listings are left out (counts and cursors included); they keep syncing and reappear once the listing is activated. Filtering by an inactive listing (`listing_id`) returns `403 listing_inactive`.
386
386
  # @param [Hash] opts the optional parameters
387
+ # @option opts [String] :account Only the records of one connected account, as &#x60;provider:externalAccountId&#x60; — the pair from a webhook &#x60;account&#x60; block, &#x60;connect.session.completed&#x60;, or &#x60;GET /v1/connect/{provider}&#x60; → &#x60;accounts&#x60;. A record belongs to an account when it is on that account&#39;s listings and on its channel (a PMS account: came in through that PMS). An account with no listings returns an empty page.
387
388
  # @option opts [String] :x_schema Apply a custom or built-in schema to transform the response. Built-in: &#x60;native&#x60; (default), &#x60;calry&#x60;, &#x60;calry-v1&#x60;. Custom: any schema name created via &#x60;POST /v1/schema/custom&#x60;. Unknown / inactive schema names fall back to &#x60;native&#x60;.
388
389
  # @option opts [Integer] :limit Page size (max 100). Requests over the cap return 422. (default to 50)
389
390
  # @option opts [String] :cursor Opaque cursor returned in the previous response&#39;s &#x60;pagination.nextCursor&#x60;. Omit to fetch the first page.
@@ -412,6 +413,7 @@ module Repull
412
413
  # List reservations
413
414
  # Cursor-paginated list of reservations across all connected PMS platforms. Filter by platform, status, listing, or check-in date range. **Pagination:** Walk pages with &#x60;?cursor&#x3D;&#x60; — pass &#x60;pagination.nextCursor&#x60; from one response back as &#x60;?cursor&#x3D;&#x60; on the next request. Stop when &#x60;pagination.hasMore&#x60; is &#x60;false&#x60;. &#x60;limit&#x60; defaults to 50, max 100; requesting more returns 422 (no silent truncation). &#x60;?offset&#x3D;&#x60; is also accepted as a first-class alias for shallow paging (0..10000) — see the &#x60;offset&#x60; parameter below. Mutually exclusive with &#x60;cursor&#x60;. For deep pagination cursor remains O(1) per page; offset &gt; 10000 returns 422 with a docs link. **Incremental sync (only changes since last poll):** pass &#x60;?updated_since&#x3D;&lt;ISO8601&gt;&#x60; to receive only reservations amended, cancelled, or created at or after that instant — no full re-walk. Each row carries &#x60;updatedAt&#x60;; the last row of the final page is your next watermark. Note that &#x60;updated_since&#x60; changes the page ordering to &#x60;updatedAt ASC, id ASC&#x60; (and the cursor with it) so mid-walk amendments cannot be skipped — see the parameter description for the full contract. Reservations on inactive listings are left out (counts and cursors included); they keep syncing and reappear once the listing is activated. Filtering by an inactive listing (&#x60;listing_id&#x60;) returns &#x60;403 listing_inactive&#x60;.
414
415
  # @param [Hash] opts the optional parameters
416
+ # @option opts [String] :account Only the records of one connected account, as &#x60;provider:externalAccountId&#x60; — the pair from a webhook &#x60;account&#x60; block, &#x60;connect.session.completed&#x60;, or &#x60;GET /v1/connect/{provider}&#x60; → &#x60;accounts&#x60;. A record belongs to an account when it is on that account&#39;s listings and on its channel (a PMS account: came in through that PMS). An account with no listings returns an empty page.
415
417
  # @option opts [String] :x_schema Apply a custom or built-in schema to transform the response. Built-in: &#x60;native&#x60; (default), &#x60;calry&#x60;, &#x60;calry-v1&#x60;. Custom: any schema name created via &#x60;POST /v1/schema/custom&#x60;. Unknown / inactive schema names fall back to &#x60;native&#x60;.
416
418
  # @option opts [Integer] :limit Page size (max 100). Requests over the cap return 422. (default to 50)
417
419
  # @option opts [String] :cursor Opaque cursor returned in the previous response&#39;s &#x60;pagination.nextCursor&#x60;. Omit to fetch the first page.
@@ -461,6 +463,7 @@ module Repull
461
463
 
462
464
  # query parameters
463
465
  query_params = opts[:query_params] || {}
466
+ query_params[:'account'] = opts[:'account'] if !opts[:'account'].nil?
464
467
  query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil?
465
468
  query_params[:'cursor'] = opts[:'cursor'] if !opts[:'cursor'].nil?
466
469
  query_params[:'offset'] = opts[:'offset'] if !opts[:'offset'].nil?