repull 0.2.10 → 0.2.14

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 (376) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/repull/api/airbnb_api.rb +332 -99
  4. data/lib/repull/api/atlas_api.rb +5 -5
  5. data/lib/repull/api/availability_api.rb +145 -3
  6. data/lib/repull/api/billing_api.rb +7 -7
  7. data/lib/repull/api/booking_com_api.rb +210 -54
  8. data/lib/repull/api/connect_api.rb +761 -8
  9. data/lib/repull/api/conversations_api.rb +92 -11
  10. data/lib/repull/api/guests_api.rb +82 -7
  11. data/lib/repull/api/health_api.rb +318 -0
  12. data/lib/repull/api/kv_api.rb +1 -1
  13. data/lib/repull/api/listings_api.rb +303 -24
  14. data/lib/repull/api/markets_api.rb +3 -3
  15. data/lib/repull/api/plumguide_api.rb +19 -11
  16. data/lib/repull/api/pricing_api.rb +15 -15
  17. data/lib/repull/api/properties_api.rb +12 -9
  18. data/lib/repull/api/quotes_api.rb +109 -0
  19. data/lib/repull/api/reservations_api.rb +166 -7
  20. data/lib/repull/api/reviews_api.rb +81 -7
  21. data/lib/repull/api/schema_api.rb +1 -1
  22. data/lib/repull/api/system_api.rb +1 -1
  23. data/lib/repull/api/vrbo_api.rb +10 -10
  24. data/lib/repull/api/webhooks_api.rb +11 -9
  25. data/lib/repull/api_client.rb +1 -1
  26. data/lib/repull/api_error.rb +1 -1
  27. data/lib/repull/api_model_base.rb +1 -1
  28. data/lib/repull/configuration.rb +1 -1
  29. data/lib/repull/models/account_created_event.rb +1 -1
  30. data/lib/repull/models/account_created_payload.rb +1 -1
  31. data/lib/repull/models/account_disconnected_event.rb +1 -1
  32. data/lib/repull/models/account_disconnected_payload.rb +1 -1
  33. data/lib/repull/models/acknowledge_booking_reservations_request.rb +1 -1
  34. data/lib/repull/models/ai_operation.rb +1 -1
  35. data/lib/repull/models/ai_operation_completed_event.rb +1 -1
  36. data/lib/repull/models/ai_operation_completed_payload.rb +1 -1
  37. data/lib/repull/models/ai_operation_failed_event.rb +1 -1
  38. data/lib/repull/models/ai_operation_failed_payload.rb +1 -1
  39. data/lib/repull/models/ai_operation_failed_payload_error.rb +1 -1
  40. data/lib/repull/models/airbnb_alteration.rb +154 -10
  41. data/lib/repull/models/airbnb_amenity.rb +1 -1
  42. data/lib/repull/models/airbnb_availability_write_request.rb +20 -1
  43. data/lib/repull/models/airbnb_calendar_operation.rb +97 -8
  44. data/lib/repull/models/airbnb_connection.rb +4 -4
  45. data/lib/repull/models/airbnb_connection_accessibility_amenities_inner.rb +1 -1
  46. data/lib/repull/models/airbnb_connection_amenities_inner.rb +1 -1
  47. data/lib/repull/models/airbnb_connection_host.rb +1 -1
  48. data/lib/repull/models/airbnb_connection_response.rb +1 -1
  49. data/lib/repull/models/airbnb_connection_summary.rb +1 -1
  50. data/lib/repull/models/airbnb_data_freshness.rb +3 -3
  51. data/lib/repull/models/airbnb_listing.rb +2 -2
  52. data/lib/repull/models/airbnb_listing_action_request.rb +1 -1
  53. data/lib/repull/models/airbnb_listing_list_response.rb +2 -2
  54. data/lib/repull/models/airbnb_pricing_write_request.rb +54 -3
  55. data/lib/repull/models/airbnb_pricing_write_request_records_inner.rb +236 -0
  56. data/lib/repull/models/airbnb_reservation.rb +1 -1
  57. data/lib/repull/models/airbnb_reservation_list_response.rb +2 -2
  58. data/lib/repull/models/airbnb_review.rb +1 -1
  59. data/lib/repull/models/airbnb_review_list_response.rb +1 -1
  60. data/lib/repull/models/airbnb_thread.rb +1 -1
  61. data/lib/repull/models/airbnb_thread_list_response.rb +1 -1
  62. data/lib/repull/models/airbnb_transaction.rb +502 -0
  63. data/lib/repull/models/airbnb_transaction_guest_breakdown.rb +171 -0
  64. data/lib/repull/models/airbnb_transaction_host_breakdown.rb +246 -0
  65. data/lib/repull/models/airbnb_transaction_payout.rb +175 -0
  66. data/lib/repull/models/{booking_conversation_list_response.rb → alteration_change.rb} +22 -19
  67. data/lib/repull/models/alteration_webhook_object.rb +296 -0
  68. data/lib/repull/models/availability_batch_write_request.rb +296 -0
  69. data/lib/repull/models/availability_write_request.rb +259 -0
  70. data/lib/repull/models/availability_write_result.rb +178 -0
  71. data/lib/repull/models/availability_write_result_synced.rb +176 -0
  72. data/lib/repull/models/availability_write_settings.rb +215 -0
  73. data/lib/repull/models/booking_availability_state_response.rb +149 -0
  74. data/lib/repull/models/booking_availability_update.rb +1 -1
  75. data/lib/repull/models/booking_availability_update_request.rb +1 -1
  76. data/lib/repull/models/booking_availability_update_request_property_id.rb +1 -1
  77. data/lib/repull/models/booking_availability_update_request_updates_inner.rb +1 -1
  78. data/lib/repull/models/booking_connect_listing_option.rb +1 -1
  79. data/lib/repull/models/booking_connect_room.rb +1 -1
  80. data/lib/repull/models/booking_connect_rooms_response.rb +39 -5
  81. data/lib/repull/models/booking_conversation.rb +1 -1
  82. data/lib/repull/models/booking_pricing_rate_update.rb +1 -1
  83. data/lib/repull/models/booking_pricing_rate_update_date_range.rb +1 -1
  84. data/lib/repull/models/booking_pricing_rate_update_restrictions.rb +1 -1
  85. data/lib/repull/models/booking_pricing_response.rb +1 -1
  86. data/lib/repull/models/booking_pricing_update_request.rb +1 -1
  87. data/lib/repull/models/booking_pricing_update_response.rb +1 -1
  88. data/lib/repull/models/booking_property.rb +1 -1
  89. data/lib/repull/models/booking_reservation.rb +277 -0
  90. data/lib/repull/models/booking_reservation_room.rb +271 -0
  91. data/lib/repull/models/booking_room_mapping.rb +18 -8
  92. data/lib/repull/models/booking_rooms_rates_response.rb +170 -0
  93. data/lib/repull/models/booking_rooms_rates_response_rooms_inner.rb +170 -0
  94. data/lib/repull/models/booking_rooms_rates_response_rooms_inner_rates_inner.rb +212 -0
  95. data/lib/repull/models/booking_setup_request.rb +1 -1
  96. data/lib/repull/models/booking_verify_hotel_request.rb +1 -1
  97. data/lib/repull/models/booking_verify_hotel_response.rb +40 -6
  98. data/lib/repull/models/bulk_pricing_failure.rb +1 -1
  99. data/lib/repull/models/bulk_pricing_item.rb +1 -1
  100. data/lib/repull/models/bulk_pricing_request.rb +1 -1
  101. data/lib/repull/models/bulk_pricing_response.rb +1 -1
  102. data/lib/repull/models/calendar_day.rb +1 -1
  103. data/lib/repull/models/calendar_response.rb +1 -1
  104. data/lib/repull/models/calendar_updated_event.rb +1 -1
  105. data/lib/repull/models/calendar_updated_payload.rb +1 -1
  106. data/lib/repull/models/calendar_updated_payload_range.rb +1 -1
  107. data/lib/repull/models/clear_kv200_response.rb +1 -1
  108. data/lib/repull/models/connect_host.rb +1 -1
  109. data/lib/repull/models/connect_provider.rb +1 -1
  110. data/lib/repull/models/connect_provider_list_response.rb +1 -1
  111. data/lib/repull/models/connect_session.rb +1 -1
  112. data/lib/repull/models/connect_status.rb +18 -6
  113. data/lib/repull/models/connect_status_accounts_inner.rb +188 -0
  114. data/lib/repull/models/connection.rb +1 -1
  115. data/lib/repull/models/connection_list_response.rb +1 -1
  116. data/lib/repull/models/conversation.rb +13 -2
  117. data/lib/repull/models/conversation_detail.rb +13 -2
  118. data/lib/repull/models/conversation_guest.rb +1 -1
  119. data/lib/repull/models/conversation_guest_contact.rb +1 -1
  120. data/lib/repull/models/conversation_host.rb +1 -1
  121. data/lib/repull/models/conversation_list_response.rb +1 -1
  122. data/lib/repull/models/conversation_message_attachment.rb +1 -1
  123. data/lib/repull/models/create_airbnb_alteration_request.rb +1 -1
  124. data/lib/repull/models/create_airbnb_offer_request.rb +1 -1
  125. data/lib/repull/models/create_billing_checkout_request.rb +1 -1
  126. data/lib/repull/models/create_booking_webhook_request.rb +1 -1
  127. data/lib/repull/models/create_connect_session_request.rb +1 -1
  128. data/lib/repull/models/create_connection_request.rb +2 -2
  129. data/lib/repull/models/create_webhook_request.rb +1 -1
  130. data/lib/repull/models/custom_schema.rb +1 -1
  131. data/lib/repull/models/custom_schema_create.rb +1 -1
  132. data/lib/repull/models/custom_schema_create_response.rb +1 -1
  133. data/lib/repull/models/custom_schema_delete_response.rb +1 -1
  134. data/lib/repull/models/custom_schema_list_response.rb +1 -1
  135. data/lib/repull/models/custom_schema_summary.rb +1 -1
  136. data/lib/repull/models/custom_schema_update.rb +1 -1
  137. data/lib/repull/models/delete_airbnb_listing_photo200_response.rb +1 -1
  138. data/lib/repull/models/delete_connection200_response.rb +234 -0
  139. data/lib/repull/models/delete_kv200_response.rb +1 -1
  140. data/lib/repull/models/error.rb +1 -1
  141. data/lib/repull/models/error_error.rb +14 -2
  142. data/lib/repull/models/error_error_support.rb +1 -1
  143. data/lib/repull/models/get_airbnb_alteration200_response.rb +2 -2
  144. data/lib/repull/models/get_airbnb_checkin_guide200_response.rb +192 -0
  145. data/lib/repull/models/get_airbnb_listing_quality200_response.rb +2 -2
  146. data/lib/repull/models/get_airbnb_listing_settings200_response.rb +2 -2
  147. data/lib/repull/models/get_airbnb_thread200_response.rb +2 -2
  148. data/lib/repull/models/get_health200_response.rb +1 -1
  149. data/lib/repull/models/get_usage_logs200_response.rb +1 -1
  150. data/lib/repull/models/get_usage_logs200_response_data_inner.rb +1 -1
  151. data/lib/repull/models/get_usage_logs200_response_pagination.rb +3 -3
  152. data/lib/repull/models/get_usage_summary200_response.rb +2 -2
  153. data/lib/repull/models/get_usage_summary200_response_breakdown_inner.rb +1 -1
  154. data/lib/repull/models/get_usage_summary200_response_limits.rb +3 -3
  155. data/lib/repull/models/get_usage_summary200_response_remaining.rb +2 -2
  156. data/lib/repull/models/get_usage_summary200_response_status_distribution.rb +1 -1
  157. data/lib/repull/models/get_usage_summary200_response_timeline_inner.rb +1 -1
  158. data/lib/repull/models/get_usage_summary200_response_totals.rb +1 -1
  159. data/lib/repull/models/get_usage_summary200_response_used.rb +2 -2
  160. data/lib/repull/models/get_usage_tier200_response.rb +2 -2
  161. data/lib/repull/models/get_usage_tier200_response_limits.rb +4 -4
  162. data/lib/repull/models/get_usage_tier200_response_remaining.rb +3 -3
  163. data/lib/repull/models/get_usage_tier200_response_used.rb +3 -3
  164. data/lib/repull/models/guest.rb +1 -1
  165. data/lib/repull/models/guest_contact.rb +1 -1
  166. data/lib/repull/models/guest_create_request.rb +250 -0
  167. data/lib/repull/models/guest_create_response.rb +227 -0
  168. data/lib/repull/models/guest_create_response_contacts_inner.rb +199 -0
  169. data/lib/repull/models/guest_flag.rb +1 -1
  170. data/lib/repull/models/guest_list_response.rb +1 -1
  171. data/lib/repull/models/guest_note.rb +1 -1
  172. data/lib/repull/models/guest_profile.rb +1 -1
  173. data/lib/repull/models/guest_reservations_summary.rb +1 -1
  174. data/lib/repull/models/list_airbnb_alterations200_response.rb +2 -2
  175. data/lib/repull/models/list_airbnb_listing_amenities200_response.rb +2 -2
  176. data/lib/repull/models/list_airbnb_listing_amenities200_response_data.rb +1 -1
  177. data/lib/repull/models/list_airbnb_transactions200_response.rb +3 -3
  178. data/lib/repull/models/list_booking_reservations200_response.rb +104 -0
  179. data/lib/repull/models/list_kv200_response.rb +1 -1
  180. data/lib/repull/models/list_kv200_response_data_inner.rb +1 -1
  181. data/lib/repull/models/list_kv200_response_pagination.rb +2 -2
  182. data/lib/repull/models/listing.rb +2 -2
  183. data/lib/repull/models/listing_active_request.rb +2 -2
  184. data/lib/repull/models/listing_active_response.rb +1 -1
  185. data/lib/repull/models/listing_address.rb +1 -1
  186. data/lib/repull/models/listing_amenity.rb +1 -1
  187. data/lib/repull/models/listing_channel.rb +1 -1
  188. data/lib/repull/models/listing_comp.rb +1 -1
  189. data/lib/repull/models/listing_comp_nightly.rb +1 -1
  190. data/lib/repull/models/listing_comp_ratings.rb +1 -1
  191. data/lib/repull/models/listing_comps_response.rb +1 -1
  192. data/lib/repull/models/listing_content.rb +1 -1
  193. data/lib/repull/models/listing_content_update_request.rb +1 -1
  194. data/lib/repull/models/listing_content_update_request_address.rb +1 -1
  195. data/lib/repull/models/listing_content_update_request_amenities.rb +1 -1
  196. data/lib/repull/models/listing_content_update_request_amenities_one_of_inner.rb +1 -1
  197. data/lib/repull/models/listing_content_update_request_occupancy.rb +1 -1
  198. data/lib/repull/models/listing_content_update_request_photos_inner.rb +1 -1
  199. data/lib/repull/models/listing_content_update_request_photos_inner_one_of.rb +1 -1
  200. data/lib/repull/models/listing_content_update_request_policies.rb +1 -1
  201. data/lib/repull/models/listing_content_update_response.rb +1 -1
  202. data/lib/repull/models/listing_create_request.rb +1 -1
  203. data/lib/repull/models/listing_create_response.rb +1 -1
  204. data/lib/repull/models/listing_created_event.rb +1 -1
  205. data/lib/repull/models/listing_created_payload.rb +1 -1
  206. data/lib/repull/models/listing_created_payload_address.rb +1 -1
  207. data/lib/repull/models/listing_deleted_event.rb +1 -1
  208. data/lib/repull/models/listing_deleted_payload.rb +1 -1
  209. data/lib/repull/models/listing_details.rb +1 -1
  210. data/lib/repull/models/listing_generate_content_request.rb +1 -1
  211. data/lib/repull/models/listing_generate_content_response.rb +1 -1
  212. data/lib/repull/models/listing_list_response.rb +1 -1
  213. data/lib/repull/models/{studio_file.rb → listing_photo.rb} +23 -34
  214. data/lib/repull/models/listing_photo_delete_request.rb +165 -0
  215. data/lib/repull/models/{studio_error.rb → listing_photo_delete_response.rb} +20 -12
  216. data/lib/repull/models/listing_photo_upload_url_request.rb +203 -0
  217. data/lib/repull/models/listing_photo_upload_url_response.rb +198 -0
  218. data/lib/repull/models/{vrbo_listing_list_response.rb → listing_photos_response.rb} +19 -19
  219. data/lib/repull/models/listing_pricing_apply_request.rb +1 -1
  220. data/lib/repull/models/listing_pricing_apply_response.rb +1 -1
  221. data/lib/repull/models/listing_pricing_history_entry.rb +2 -2
  222. data/lib/repull/models/listing_pricing_history_response.rb +1 -1
  223. data/lib/repull/models/listing_pricing_recommendation.rb +1 -1
  224. data/lib/repull/models/listing_pricing_response.rb +1 -1
  225. data/lib/repull/models/listing_pricing_response_comp_summary.rb +1 -1
  226. data/lib/repull/models/listing_pricing_response_date_range.rb +1 -1
  227. data/lib/repull/models/listing_pricing_response_listing.rb +1 -1
  228. data/lib/repull/models/listing_pricing_strategy.rb +1 -1
  229. data/lib/repull/models/listing_pricing_strategy_input.rb +1 -1
  230. data/lib/repull/models/listing_publish_airbnb_request.rb +1 -1
  231. data/lib/repull/models/listing_publish_response.rb +1 -1
  232. data/lib/repull/models/listing_publish_status_channel.rb +1 -1
  233. data/lib/repull/models/listing_publish_status_connection.rb +1 -1
  234. data/lib/repull/models/listing_publish_status_response.rb +1 -1
  235. data/lib/repull/models/listing_quality_tier.rb +1 -1
  236. data/lib/repull/models/listing_segment.rb +1 -1
  237. data/lib/repull/models/listing_segment_recommendation.rb +1 -1
  238. data/lib/repull/models/listing_segments_response.rb +1 -1
  239. data/lib/repull/models/listing_segments_response_scope.rb +1 -1
  240. data/lib/repull/models/listing_status_batch_request.rb +212 -0
  241. data/lib/repull/models/listing_status_batch_response.rb +223 -0
  242. data/lib/repull/models/listing_updated_event.rb +1 -1
  243. data/lib/repull/models/listing_updated_payload.rb +1 -1
  244. data/lib/repull/models/map_airbnb_listing_request.rb +1 -1
  245. data/lib/repull/models/map_airbnb_listing_response.rb +1 -1
  246. data/lib/repull/models/map_connect_booking_rooms_request.rb +1 -1
  247. data/lib/repull/models/map_connect_booking_rooms_response.rb +16 -5
  248. data/lib/repull/models/market_browse_category.rb +1 -1
  249. data/lib/repull/models/market_browse_entry.rb +1 -1
  250. data/lib/repull/models/market_browse_featured.rb +1 -1
  251. data/lib/repull/models/market_browse_response.rb +1 -1
  252. data/lib/repull/models/market_calendar_day.rb +1 -1
  253. data/lib/repull/models/market_calendar_day_events_inner.rb +1 -1
  254. data/lib/repull/models/market_calendar_response.rb +1 -1
  255. data/lib/repull/models/market_detail_response.rb +1 -1
  256. data/lib/repull/models/market_detail_response_price_distribution_inner.rb +1 -1
  257. data/lib/repull/models/market_detail_response_property_type_mix_inner.rb +1 -1
  258. data/lib/repull/models/market_detail_response_supply_trend_inner.rb +1 -1
  259. data/lib/repull/models/market_detail_response_top_comps.rb +1 -1
  260. data/lib/repull/models/market_event.rb +1 -1
  261. data/lib/repull/models/market_my_listing.rb +1 -1
  262. data/lib/repull/models/market_summary.rb +1 -1
  263. data/lib/repull/models/market_top_comp.rb +1 -1
  264. data/lib/repull/models/markets_overview_response.rb +1 -1
  265. data/lib/repull/models/markets_overview_response_browse.rb +1 -1
  266. data/lib/repull/models/markets_overview_response_subscriptions.rb +1 -1
  267. data/lib/repull/models/markets_overview_response_totals.rb +1 -1
  268. data/lib/repull/models/message.rb +1 -1
  269. data/lib/repull/models/message_list_response.rb +1 -1
  270. data/lib/repull/models/pagination.rb +1 -1
  271. data/lib/repull/models/payment_completed_event.rb +1 -1
  272. data/lib/repull/models/payment_completed_payload.rb +1 -1
  273. data/lib/repull/models/payment_refunded_event.rb +1 -1
  274. data/lib/repull/models/payment_refunded_payload.rb +1 -1
  275. data/lib/repull/models/plumguide_listing.rb +1 -1
  276. data/lib/repull/models/plumguide_listing_list_response.rb +1 -1
  277. data/lib/repull/models/property.rb +17 -7
  278. data/lib/repull/models/property_availability.rb +33 -7
  279. data/lib/repull/models/property_availability_coverage.rb +222 -0
  280. data/lib/repull/models/property_availability_day.rb +4 -4
  281. data/lib/repull/models/property_list_response.rb +1 -1
  282. data/lib/repull/models/quote.rb +240 -0
  283. data/lib/repull/models/quote_pricing.rb +218 -0
  284. data/lib/repull/models/reply_booking_review200_response.rb +1 -1
  285. data/lib/repull/models/reply_booking_review_request.rb +1 -1
  286. data/lib/repull/models/reply_to_review201_response.rb +165 -0
  287. data/lib/repull/models/reply_to_review_request.rb +165 -0
  288. data/lib/repull/models/repull_ping_event.rb +1 -1
  289. data/lib/repull/models/repull_ping_payload.rb +1 -1
  290. data/lib/repull/models/reservation.rb +1 -1
  291. data/lib/repull/models/{studio_deployment.rb → reservation_alteration_created_event.rb} +67 -57
  292. data/lib/repull/models/reservation_alteration_created_payload.rb +177 -0
  293. data/lib/repull/models/reservation_alteration_responded_event.rb +217 -0
  294. data/lib/repull/models/reservation_alteration_responded_payload.rb +175 -0
  295. data/lib/repull/models/reservation_cancelled_event.rb +1 -1
  296. data/lib/repull/models/reservation_cancelled_payload.rb +1 -1
  297. data/lib/repull/models/reservation_create_request.rb +403 -0
  298. data/lib/repull/models/reservation_create_response.rb +233 -0
  299. data/lib/repull/models/reservation_created_event.rb +1 -1
  300. data/lib/repull/models/reservation_created_payload.rb +1 -1
  301. data/lib/repull/models/reservation_financials.rb +36 -8
  302. data/lib/repull/models/reservation_guest_financials.rb +173 -0
  303. data/lib/repull/models/reservation_guest_input.rb +193 -0
  304. data/lib/repull/models/reservation_host_financials.rb +207 -0
  305. data/lib/repull/models/reservation_list_response.rb +1 -1
  306. data/lib/repull/models/reservation_message_received_event.rb +1 -1
  307. data/lib/repull/models/reservation_message_received_payload.rb +1 -1
  308. data/lib/repull/models/reservation_message_received_payload_from.rb +1 -1
  309. data/lib/repull/models/reservation_money_line.rb +216 -0
  310. data/lib/repull/models/reservation_occupancy.rb +1 -1
  311. data/lib/repull/models/reservation_primary_guest.rb +1 -1
  312. data/lib/repull/models/reservation_update_request.rb +255 -0
  313. data/lib/repull/models/reservation_update_response.rb +240 -0
  314. data/lib/repull/models/reservation_updated_event.rb +1 -1
  315. data/lib/repull/models/reservation_updated_payload.rb +1 -1
  316. data/lib/repull/models/reservation_webhook_object.rb +1 -1
  317. data/lib/repull/models/respond_airbnb_review_request.rb +1 -1
  318. data/lib/repull/models/review.rb +14 -3
  319. data/lib/repull/models/review_category.rb +1 -1
  320. data/lib/repull/models/{sandbox_reset_result.rb → review_created_event.rb} +59 -59
  321. data/lib/repull/models/review_created_payload.rb +165 -0
  322. data/lib/repull/models/review_list_response.rb +1 -1
  323. data/lib/repull/models/review_responded_event.rb +217 -0
  324. data/lib/repull/models/review_responded_payload.rb +175 -0
  325. data/lib/repull/models/review_response.rb +1 -1
  326. data/lib/repull/models/review_webhook_object.rb +277 -0
  327. data/lib/repull/models/rotate_webhook_secret200_response.rb +1 -1
  328. data/lib/repull/models/select_connect_provider_request.rb +1 -1
  329. data/lib/repull/models/select_provider_response.rb +1 -1
  330. data/lib/repull/models/send_airbnb_message_request.rb +187 -0
  331. data/lib/repull/models/{sandbox_reset_result_deleted.rb → send_booking_message_request.rb} +53 -50
  332. data/lib/repull/models/{studio_error_error.rb → send_message_request.rb} +31 -50
  333. data/lib/repull/models/send_message_response.rb +241 -0
  334. data/lib/repull/models/set_kv_request.rb +1 -1
  335. data/lib/repull/models/{booking_property_list_response.rb → submit_beds24_credentials200_response.rb} +19 -19
  336. data/lib/repull/models/submit_beds24_credentials_request.rb +177 -0
  337. data/lib/repull/models/submit_bookingsync_credentials_request.rb +177 -0
  338. data/lib/repull/models/submit_guesty_credentials_request.rb +177 -0
  339. data/lib/repull/models/submit_hospitable_credentials_request.rb +177 -0
  340. data/lib/repull/models/submit_hostaway_credentials_request.rb +177 -0
  341. data/lib/repull/models/submit_igms_credentials_request.rb +177 -0
  342. data/lib/repull/models/submit_lodgify_credentials_request.rb +177 -0
  343. data/lib/repull/models/submit_ownerrez_credentials_request.rb +177 -0
  344. data/lib/repull/models/submit_smoobu_credentials_request.rb +177 -0
  345. data/lib/repull/models/submit_vrbo_credentials_request.rb +177 -0
  346. data/lib/repull/models/{sandbox_fixture_ref.rb → sync_airbnb_transactions200_response.rb} +36 -38
  347. data/lib/repull/models/sync_airbnb_transactions_request.rb +201 -0
  348. data/lib/repull/models/test_webhook_request.rb +1 -1
  349. data/lib/repull/models/update_airbnb_message_request.rb +1 -1
  350. data/lib/repull/models/update_booking_charges_request.rb +1 -1
  351. data/lib/repull/models/update_listing_pricing_strategy200_response.rb +1 -1
  352. data/lib/repull/models/update_webhook_request.rb +1 -1
  353. data/lib/repull/models/vrbo_listing.rb +1 -1
  354. data/lib/repull/models/vrbo_reservation.rb +1 -1
  355. data/lib/repull/models/vrbo_reservation_list_response.rb +1 -1
  356. data/lib/repull/models/webhook_delivery.rb +1 -1
  357. data/lib/repull/models/webhook_delivery_detail.rb +1 -1
  358. data/lib/repull/models/webhook_delivery_list_response.rb +1 -1
  359. data/lib/repull/models/webhook_event.rb +12 -4
  360. data/lib/repull/models/webhook_event_catalog.rb +1 -1
  361. data/lib/repull/models/webhook_event_catalog_domains_inner.rb +1 -1
  362. data/lib/repull/models/webhook_event_catalog_entry.rb +1 -1
  363. data/lib/repull/models/webhook_event_type.rb +6 -2
  364. data/lib/repull/models/webhook_list_response.rb +1 -1
  365. data/lib/repull/models/webhook_subscription.rb +1 -1
  366. data/lib/repull/version.rb +2 -2
  367. data/lib/repull.rb +75 -15
  368. data/openapi/v1.json +6119 -2021
  369. data/scripts/check-spec-freshness.py +399 -0
  370. data/scripts/regen.sh +32 -3
  371. metadata +77 -18
  372. data/lib/repull/api/sandbox_api.rb +0 -136
  373. data/lib/repull/models/sandbox_seed_result.rb +0 -278
  374. data/lib/repull/models/studio_generation.rb +0 -215
  375. data/lib/repull/models/studio_project.rb +0 -241
  376. data/spec/api/ai_api_spec.rb +0 -47
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
  #Repull API
3
3
 
4
- #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_test_YOUR_API_KEY ``` Sandbox keys start with `sk_test_`, production with `sk_live_`. ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resets_at` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | 50 | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
4
+ #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_live_YOUR_API_KEY ``` ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resetsAt` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | 50 | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
5
 
6
6
  The version of the OpenAPI document: 1.0.0
7
7
  Contact: ivan@vanio.ai
@@ -87,8 +87,82 @@ module Repull
87
87
  return data, status_code, headers
88
88
  end
89
89
 
90
+ # Mint a direct-to-storage photo upload URL
91
+ # Mints a short-lived signed upload URL + token for a listing photo. **The client PUTs the raw file bytes directly to the returned `uploadUrl` — the file bytes never pass through the Repull API or main vanio.** This endpoint only mints the URL; do not POST the file itself here, it will not be accepted. Flow: (1) POST here with `fileName`/`fileType`/optional `fileSize` to get `{ uploadUrl, token, path, publicUrl, expiresIn }`; (2) PUT the raw file bytes to `uploadUrl` from the client; (3) `publicUrl` is the durable URL for the uploaded photo — attach it to the listing via `PUT /v1/listings/{id}/content` (`photos` field) or list it back via `GET /v1/listings/{id}/photos`. Returns `403 listing_inactive` when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
92
+ # @param id [Integer] Repull listing id
93
+ # @param listing_photo_upload_url_request [ListingPhotoUploadUrlRequest]
94
+ # @param [Hash] opts the optional parameters
95
+ # @return [ListingPhotoUploadUrlResponse]
96
+ def create_listing_photo_upload_url(id, listing_photo_upload_url_request, opts = {})
97
+ data, _status_code, _headers = create_listing_photo_upload_url_with_http_info(id, listing_photo_upload_url_request, opts)
98
+ data
99
+ end
100
+
101
+ # Mint a direct-to-storage photo upload URL
102
+ # Mints a short-lived signed upload URL + token for a listing photo. **The client PUTs the raw file bytes directly to the returned `uploadUrl` — the file bytes never pass through the Repull API or main vanio.** This endpoint only mints the URL; do not POST the file itself here, it will not be accepted. Flow: (1) POST here with `fileName`/`fileType`/optional `fileSize` to get `{ uploadUrl, token, path, publicUrl, expiresIn }`; (2) PUT the raw file bytes to `uploadUrl` from the client; (3) `publicUrl` is the durable URL for the uploaded photo — attach it to the listing via `PUT /v1/listings/{id}/content` (`photos` field) or list it back via `GET /v1/listings/{id}/photos`. 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.
103
+ # @param id [Integer] Repull listing id
104
+ # @param listing_photo_upload_url_request [ListingPhotoUploadUrlRequest]
105
+ # @param [Hash] opts the optional parameters
106
+ # @return [Array<(ListingPhotoUploadUrlResponse, Integer, Hash)>] ListingPhotoUploadUrlResponse data, response status code and response headers
107
+ def create_listing_photo_upload_url_with_http_info(id, listing_photo_upload_url_request, opts = {})
108
+ if @api_client.config.debugging
109
+ @api_client.config.logger.debug 'Calling API: ListingsApi.create_listing_photo_upload_url ...'
110
+ end
111
+ # verify the required parameter 'id' is set
112
+ if @api_client.config.client_side_validation && id.nil?
113
+ fail ArgumentError, "Missing the required parameter 'id' when calling ListingsApi.create_listing_photo_upload_url"
114
+ end
115
+ # verify the required parameter 'listing_photo_upload_url_request' is set
116
+ if @api_client.config.client_side_validation && listing_photo_upload_url_request.nil?
117
+ fail ArgumentError, "Missing the required parameter 'listing_photo_upload_url_request' when calling ListingsApi.create_listing_photo_upload_url"
118
+ end
119
+ # resource path
120
+ local_var_path = '/v1/listings/{id}/photos/upload-url'.sub('{id}', CGI.escape(id.to_s))
121
+
122
+ # query parameters
123
+ query_params = opts[:query_params] || {}
124
+
125
+ # header parameters
126
+ header_params = opts[:header_params] || {}
127
+ # HTTP header 'Accept' (if needed)
128
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
129
+ # HTTP header 'Content-Type'
130
+ content_type = @api_client.select_header_content_type(['application/json'])
131
+ if !content_type.nil?
132
+ header_params['Content-Type'] = content_type
133
+ end
134
+
135
+ # form parameters
136
+ form_params = opts[:form_params] || {}
137
+
138
+ # http body (model)
139
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(listing_photo_upload_url_request)
140
+
141
+ # return_type
142
+ return_type = opts[:debug_return_type] || 'ListingPhotoUploadUrlResponse'
143
+
144
+ # auth_names
145
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
146
+
147
+ new_options = opts.merge(
148
+ :operation => :"ListingsApi.create_listing_photo_upload_url",
149
+ :header_params => header_params,
150
+ :query_params => query_params,
151
+ :form_params => form_params,
152
+ :body => post_body,
153
+ :auth_names => auth_names,
154
+ :return_type => return_type
155
+ )
156
+
157
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
158
+ if @api_client.config.debugging
159
+ @api_client.config.logger.debug "API called: ListingsApi#create_listing_photo_upload_url\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
160
+ end
161
+ return data, status_code, headers
162
+ end
163
+
90
164
  # Deactivate (exclude) a listing
91
- # Deactivate a listing — sets it inactive and excludes it from Repull. This is a **soft** operation: the listing row is KEPT (never hard-deleted) and the upstream channel (Airbnb / Hospitable / Booking.com) is NEVER touched. Repull only mutates its own copy. Equivalent to `PATCH /v1/listings/{id}` with `{ \"active\": false }`. This is the primary self-serve way for a free-tier customer to trim back under the plan-listings cap — `DELETE` is served even when the account is over the cap (a 402-locked account can still call it). To bring a listing back, use `PATCH` with `{ \"active\": true }`. Idempotent: deactivating an already-inactive listing returns 200.
165
+ # Deactivate a listing — sets it inactive and excludes it from Repull. This is a **soft** operation: the listing row is KEPT (never hard-deleted) and the upstream channel (Airbnb / Hospitable / Booking.com) is NEVER touched. Repull only mutates its own copy. Equivalent to `PATCH /v1/listings/{id}` with `{ \"active\": false }`. This is the primary self-serve way for a free-tier customer to trim back under the plan-listings cap — `DELETE` is served even when the account is over the cap (a 402-locked account can still call it). To bring a listing back, use `PATCH` with `{ \"active\": true }`. Idempotent: deactivating an already-inactive listing returns 200. To deactivate many listings at once, use `POST /v1/listings/status` with `{ \"active\": false }`.
92
166
  # @param id [Integer] Repull listing id
93
167
  # @param [Hash] opts the optional parameters
94
168
  # @return [ListingActiveResponse]
@@ -98,7 +172,7 @@ module Repull
98
172
  end
99
173
 
100
174
  # Deactivate (exclude) a listing
101
- # Deactivate a listing — sets it inactive and excludes it from Repull. This is a **soft** operation: the listing row is KEPT (never hard-deleted) and the upstream channel (Airbnb / Hospitable / Booking.com) is NEVER touched. Repull only mutates its own copy. Equivalent to &#x60;PATCH /v1/listings/{id}&#x60; with &#x60;{ \&quot;active\&quot;: false }&#x60;. This is the primary self-serve way for a free-tier customer to trim back under the plan-listings cap — &#x60;DELETE&#x60; is served even when the account is over the cap (a 402-locked account can still call it). To bring a listing back, use &#x60;PATCH&#x60; with &#x60;{ \&quot;active\&quot;: true }&#x60;. Idempotent: deactivating an already-inactive listing returns 200.
175
+ # Deactivate a listing — sets it inactive and excludes it from Repull. This is a **soft** operation: the listing row is KEPT (never hard-deleted) and the upstream channel (Airbnb / Hospitable / Booking.com) is NEVER touched. Repull only mutates its own copy. Equivalent to &#x60;PATCH /v1/listings/{id}&#x60; with &#x60;{ \&quot;active\&quot;: false }&#x60;. This is the primary self-serve way for a free-tier customer to trim back under the plan-listings cap — &#x60;DELETE&#x60; is served even when the account is over the cap (a 402-locked account can still call it). To bring a listing back, use &#x60;PATCH&#x60; with &#x60;{ \&quot;active\&quot;: true }&#x60;. Idempotent: deactivating an already-inactive listing returns 200. To deactivate many listings at once, use &#x60;POST /v1/listings/status&#x60; with &#x60;{ \&quot;active\&quot;: false }&#x60;.
102
176
  # @param id [Integer] Repull listing id
103
177
  # @param [Hash] opts the optional parameters
104
178
  # @return [Array<(ListingActiveResponse, Integer, Hash)>] ListingActiveResponse data, response status code and response headers
@@ -150,8 +224,82 @@ module Repull
150
224
  return data, status_code, headers
151
225
  end
152
226
 
227
+ # Delete a stored listing photo
228
+ # Deletes a single stored photo by its storage `path` (as returned by `GET /v1/listings/{id}/photos` or `POST /v1/listings/{id}/photos/upload-url`). 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.
229
+ # @param id [Integer] Repull listing id
230
+ # @param listing_photo_delete_request [ListingPhotoDeleteRequest]
231
+ # @param [Hash] opts the optional parameters
232
+ # @return [ListingPhotoDeleteResponse]
233
+ def delete_listing_photo(id, listing_photo_delete_request, opts = {})
234
+ data, _status_code, _headers = delete_listing_photo_with_http_info(id, listing_photo_delete_request, opts)
235
+ data
236
+ end
237
+
238
+ # Delete a stored listing photo
239
+ # Deletes a single stored photo by its storage &#x60;path&#x60; (as returned by &#x60;GET /v1/listings/{id}/photos&#x60; or &#x60;POST /v1/listings/{id}/photos/upload-url&#x60;). 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.
240
+ # @param id [Integer] Repull listing id
241
+ # @param listing_photo_delete_request [ListingPhotoDeleteRequest]
242
+ # @param [Hash] opts the optional parameters
243
+ # @return [Array<(ListingPhotoDeleteResponse, Integer, Hash)>] ListingPhotoDeleteResponse data, response status code and response headers
244
+ def delete_listing_photo_with_http_info(id, listing_photo_delete_request, opts = {})
245
+ if @api_client.config.debugging
246
+ @api_client.config.logger.debug 'Calling API: ListingsApi.delete_listing_photo ...'
247
+ end
248
+ # verify the required parameter 'id' is set
249
+ if @api_client.config.client_side_validation && id.nil?
250
+ fail ArgumentError, "Missing the required parameter 'id' when calling ListingsApi.delete_listing_photo"
251
+ end
252
+ # verify the required parameter 'listing_photo_delete_request' is set
253
+ if @api_client.config.client_side_validation && listing_photo_delete_request.nil?
254
+ fail ArgumentError, "Missing the required parameter 'listing_photo_delete_request' when calling ListingsApi.delete_listing_photo"
255
+ end
256
+ # resource path
257
+ local_var_path = '/v1/listings/{id}/photos'.sub('{id}', CGI.escape(id.to_s))
258
+
259
+ # query parameters
260
+ query_params = opts[:query_params] || {}
261
+
262
+ # header parameters
263
+ header_params = opts[:header_params] || {}
264
+ # HTTP header 'Accept' (if needed)
265
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
266
+ # HTTP header 'Content-Type'
267
+ content_type = @api_client.select_header_content_type(['application/json'])
268
+ if !content_type.nil?
269
+ header_params['Content-Type'] = content_type
270
+ end
271
+
272
+ # form parameters
273
+ form_params = opts[:form_params] || {}
274
+
275
+ # http body (model)
276
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(listing_photo_delete_request)
277
+
278
+ # return_type
279
+ return_type = opts[:debug_return_type] || 'ListingPhotoDeleteResponse'
280
+
281
+ # auth_names
282
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
283
+
284
+ new_options = opts.merge(
285
+ :operation => :"ListingsApi.delete_listing_photo",
286
+ :header_params => header_params,
287
+ :query_params => query_params,
288
+ :form_params => form_params,
289
+ :body => post_body,
290
+ :auth_names => auth_names,
291
+ :return_type => return_type
292
+ )
293
+
294
+ data, status_code, headers = @api_client.call_api(:DELETE, local_var_path, new_options)
295
+ if @api_client.config.debugging
296
+ @api_client.config.logger.debug "API called: ListingsApi#delete_listing_photo\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
297
+ end
298
+ return data, status_code, headers
299
+ end
300
+
153
301
  # AI-generate listing content
154
- # Generate guest-facing copy (title, summary, description, amenities, etc.) for a listing using Repull AI. When `photos` are provided the vision model is used for photo-grounded copy. Persists into the listing by default.
302
+ # Generate guest-facing copy (title, summary, description, amenities, etc.) for a listing using Repull AI. When `photos` are provided the vision model is used for photo-grounded copy. Persists into the listing by default. 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.
155
303
  # @param id [Integer]
156
304
  # @param [Hash] opts the optional parameters
157
305
  # @option opts [ListingGenerateContentRequest] :listing_generate_content_request
@@ -162,7 +310,7 @@ module Repull
162
310
  end
163
311
 
164
312
  # AI-generate listing content
165
- # Generate guest-facing copy (title, summary, description, amenities, etc.) for a listing using Repull AI. When &#x60;photos&#x60; are provided the vision model is used for photo-grounded copy. Persists into the listing by default.
313
+ # Generate guest-facing copy (title, summary, description, amenities, etc.) for a listing using Repull AI. When &#x60;photos&#x60; are provided the vision model is used for photo-grounded copy. Persists into the listing by default. 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.
166
314
  # @param id [Integer]
167
315
  # @param [Hash] opts the optional parameters
168
316
  # @option opts [ListingGenerateContentRequest] :listing_generate_content_request
@@ -221,7 +369,7 @@ module Repull
221
369
  end
222
370
 
223
371
  # Get a listing
224
- # Fetch a single listing by id. Returns the same shape as one element of the `GET /v1/listings` response, so you can bind the result to the same model. Cross-tenant access (a listing that belongs to a different workspace) returns 404 — never 403, never reveals the listing's existence. **Optional expansions:** Pass `?include=amenities` to enrich the response with the listing's amenity rows (`[]` when the listing has none). Pass `?include=content` for the rich content slab (summary, description, space, house rules, etc. — sourced from `listings_descriptions` for the `en` locale; `null` when no row is stored). Pass `?include=details` for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.; `null` when no row is stored). Combine comma-separated, e.g. `?include=amenities,content,details`. The default response stays lean; consumers must opt in.
372
+ # Fetch a single listing by id. Returns the same shape as one element of the `GET /v1/listings` response, so you can bind the result to the same model. Cross-tenant access (a listing that belongs to a different workspace) returns 404 — never 403, never reveals the listing's existence. **Optional expansions:** Pass `?include=amenities` to enrich the response with the listing's amenity rows (`[]` when the listing has none). Pass `?include=content` for the rich content slab (summary, description, space, house rules, etc. — sourced from `listings_descriptions` for the `en` locale; `null` when no row is stored). Pass `?include=details` for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.; `null` when no row is stored). Combine comma-separated, e.g. `?include=amenities,content,details`. The default response stays lean; consumers must opt in. 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.
225
373
  # @param id [Integer] Repull listing id
226
374
  # @param [Hash] opts the optional parameters
227
375
  # @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;.
@@ -233,7 +381,7 @@ module Repull
233
381
  end
234
382
 
235
383
  # Get a listing
236
- # Fetch a single listing by id. Returns the same shape as one element of the &#x60;GET /v1/listings&#x60; response, so you can bind the result to the same model. Cross-tenant access (a listing that belongs to a different workspace) returns 404 — never 403, never reveals the listing&#39;s existence. **Optional expansions:** Pass &#x60;?include&#x3D;amenities&#x60; to enrich the response with the listing&#39;s amenity rows (&#x60;[]&#x60; when the listing has none). Pass &#x60;?include&#x3D;content&#x60; for the rich content slab (summary, description, space, house rules, etc. — sourced from &#x60;listings_descriptions&#x60; for the &#x60;en&#x60; locale; &#x60;null&#x60; when no row is stored). Pass &#x60;?include&#x3D;details&#x60; for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.; &#x60;null&#x60; when no row is stored). Combine comma-separated, e.g. &#x60;?include&#x3D;amenities,content,details&#x60;. The default response stays lean; consumers must opt in.
384
+ # Fetch a single listing by id. Returns the same shape as one element of the &#x60;GET /v1/listings&#x60; response, so you can bind the result to the same model. Cross-tenant access (a listing that belongs to a different workspace) returns 404 — never 403, never reveals the listing&#39;s existence. **Optional expansions:** Pass &#x60;?include&#x3D;amenities&#x60; to enrich the response with the listing&#39;s amenity rows (&#x60;[]&#x60; when the listing has none). Pass &#x60;?include&#x3D;content&#x60; for the rich content slab (summary, description, space, house rules, etc. — sourced from &#x60;listings_descriptions&#x60; for the &#x60;en&#x60; locale; &#x60;null&#x60; when no row is stored). Pass &#x60;?include&#x3D;details&#x60; for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.; &#x60;null&#x60; when no row is stored). Combine comma-separated, e.g. &#x60;?include&#x3D;amenities,content,details&#x60;. The default response stays lean; consumers must opt in. 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.
237
385
  # @param id [Integer] Repull listing id
238
386
  # @param [Hash] opts the optional parameters
239
387
  # @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;.
@@ -290,7 +438,7 @@ module Repull
290
438
  end
291
439
 
292
440
  # Per-channel publish status
293
- # Returns connection state and sync activity per channel. `channels` is sync activity (empty until first push). `connections` is connection state (populated as soon as a channel is linked). Recommended polling cadence: at most once per 30s per listing — for bulk views, prefer `GET /v1/listings` and filter client-side.
441
+ # Returns connection state and sync activity per channel. `channels` is sync activity (empty until first push). `connections` is connection state (populated as soon as a channel is linked). Recommended polling cadence: at most once per 30s per listing — for bulk views, prefer `GET /v1/listings` and filter client-side. 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.
294
442
  # @param id [Integer]
295
443
  # @param [Hash] opts the optional parameters
296
444
  # @return [ListingPublishStatusResponse]
@@ -300,7 +448,7 @@ module Repull
300
448
  end
301
449
 
302
450
  # Per-channel publish status
303
- # Returns connection state and sync activity per channel. &#x60;channels&#x60; is sync activity (empty until first push). &#x60;connections&#x60; is connection state (populated as soon as a channel is linked). Recommended polling cadence: at most once per 30s per listing — for bulk views, prefer &#x60;GET /v1/listings&#x60; and filter client-side.
451
+ # Returns connection state and sync activity per channel. &#x60;channels&#x60; is sync activity (empty until first push). &#x60;connections&#x60; is connection state (populated as soon as a channel is linked). Recommended polling cadence: at most once per 30s per listing — for bulk views, prefer &#x60;GET /v1/listings&#x60; and filter client-side. 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.
304
452
  # @param id [Integer]
305
453
  # @param [Hash] opts the optional parameters
306
454
  # @return [Array<(ListingPublishStatusResponse, Integer, Hash)>] ListingPublishStatusResponse data, response status code and response headers
@@ -352,15 +500,78 @@ module Repull
352
500
  return data, status_code, headers
353
501
  end
354
502
 
503
+ # List a listing's stored photos
504
+ # Returns the photo set currently stored for this listing. Returns `403 listing_inactive` when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
505
+ # @param id [Integer] Repull listing id
506
+ # @param [Hash] opts the optional parameters
507
+ # @return [ListingPhotosResponse]
508
+ def list_listing_photos(id, opts = {})
509
+ data, _status_code, _headers = list_listing_photos_with_http_info(id, opts)
510
+ data
511
+ end
512
+
513
+ # List a listing&#39;s stored photos
514
+ # Returns the photo set currently stored for this listing. Returns &#x60;403 listing_inactive&#x60; when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
515
+ # @param id [Integer] Repull listing id
516
+ # @param [Hash] opts the optional parameters
517
+ # @return [Array<(ListingPhotosResponse, Integer, Hash)>] ListingPhotosResponse data, response status code and response headers
518
+ def list_listing_photos_with_http_info(id, opts = {})
519
+ if @api_client.config.debugging
520
+ @api_client.config.logger.debug 'Calling API: ListingsApi.list_listing_photos ...'
521
+ end
522
+ # verify the required parameter 'id' is set
523
+ if @api_client.config.client_side_validation && id.nil?
524
+ fail ArgumentError, "Missing the required parameter 'id' when calling ListingsApi.list_listing_photos"
525
+ end
526
+ # resource path
527
+ local_var_path = '/v1/listings/{id}/photos'.sub('{id}', CGI.escape(id.to_s))
528
+
529
+ # query parameters
530
+ query_params = opts[:query_params] || {}
531
+
532
+ # header parameters
533
+ header_params = opts[:header_params] || {}
534
+ # HTTP header 'Accept' (if needed)
535
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
536
+
537
+ # form parameters
538
+ form_params = opts[:form_params] || {}
539
+
540
+ # http body (model)
541
+ post_body = opts[:debug_body]
542
+
543
+ # return_type
544
+ return_type = opts[:debug_return_type] || 'ListingPhotosResponse'
545
+
546
+ # auth_names
547
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
548
+
549
+ new_options = opts.merge(
550
+ :operation => :"ListingsApi.list_listing_photos",
551
+ :header_params => header_params,
552
+ :query_params => query_params,
553
+ :form_params => form_params,
554
+ :body => post_body,
555
+ :auth_names => auth_names,
556
+ :return_type => return_type
557
+ )
558
+
559
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
560
+ if @api_client.config.debugging
561
+ @api_client.config.logger.debug "API called: ListingsApi#list_listing_photos\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
562
+ end
563
+ return data, status_code, headers
564
+ end
565
+
355
566
  # List listings
356
- # Cursor-paginated list of listings owned by the authenticated workspace. Use `pagination.nextCursor` from one response as the `cursor` query param of the next request to walk the full set. `?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`, `channel`. **Optional expansions:** Pass `?include=content` to enrich each row with the rich content slab (summary, description, space, house rules, etc. — sourced from `listings_descriptions` for the `en` locale). Pass `?include=details` for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.). Both default to `null` per row when the underlying `listings_descriptions` / `listings_details` row is missing — distinct from the field being absent (which signals the expansion was not requested). Combine comma-separated, e.g. `?include=content,details`. The default response stays lean; consumers must opt in.
567
+ # Cursor-paginated list of listings owned by the authenticated workspace. Use `pagination.nextCursor` from one response as the `cursor` query param of the next request to walk the full set. `?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`, `channel`. **Optional expansions:** Pass `?include=content` to enrich each row with the rich content slab (summary, description, space, house rules, etc. — sourced from `listings_descriptions` for the `en` locale). Pass `?include=details` for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.). Both default to `null` per row when the underlying `listings_descriptions` / `listings_details` row is missing — distinct from the field being absent (which signals the expansion was not requested). Combine comma-separated, e.g. `?include=content,details`. The default response stays lean; consumers must opt in. **Inactive listings:** by default only active listings are returned. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated, so when `status` asks for inactive ones they carry only `id`, `name`, `status` and `channels` — enough to choose what to activate with `PATCH /v1/listings/{id}`. `?include=` expansions are not applied to them.
357
568
  # @param [Hash] opts the optional parameters
358
569
  # @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;.
359
570
  # @option opts [String] :cursor Opaque cursor returned in the previous response&#39;s &#x60;pagination.nextCursor&#x60;. Omit to fetch the first page.
360
- # @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.next_cursor&#x60; so consumers can switch from offset → cursor mid-walk for deep pagination without re-keying. (default to 0)
571
+ # @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)
361
572
  # @option opts [Integer] :limit Max items per page. Hard cap is 100. (default to 20)
362
573
  # @option opts [String] :q Case-insensitive substring search on name, street, or city.
363
- # @option opts [String] :status Filter by listing status.
574
+ # @option opts [String] :status Filter by listing status. Defaults to &#x60;active&#x60;. Pass &#x60;inactive&#x60; to list the listings you can activate, &#x60;archived&#x60; for archived ones, or &#x60;all&#x60; for every status. Inactive listings are returned with identity fields only — &#x60;id&#x60;, &#x60;name&#x60;, &#x60;status&#x60; and &#x60;channels&#x60; — and never with &#x60;address&#x60;, &#x60;thumbnailUrl&#x60;, &#x60;content&#x60; or &#x60;details&#x60;; activate one to see the rest. (default to 'active')
364
575
  # @option opts [String] :channel Restrict to listings published on the given channel (&#x60;airbnb&#x60;, &#x60;booking&#x60;, &#x60;vrbo&#x60;, etc.). Joins through &#x60;listing_platform_links&#x60; and matches active links only.
365
576
  # @option opts [String] :include Comma-separated optional expansions. Currently supported: &#x60;content&#x60;, &#x60;details&#x60;. Unknown values return 422 with a &#x60;valid_values&#x60; envelope. (Note: &#x60;amenities&#x60; is not yet supported on the list endpoint — use the detail endpoint to fetch amenity rows for a single listing.)
366
577
  # @return [ListingListResponse]
@@ -370,14 +581,14 @@ module Repull
370
581
  end
371
582
 
372
583
  # List listings
373
- # Cursor-paginated list of listings owned by the authenticated workspace. Use &#x60;pagination.nextCursor&#x60; from one response as the &#x60;cursor&#x60; query param of the next request to walk the full set. &#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;, &#x60;channel&#x60;. **Optional expansions:** Pass &#x60;?include&#x3D;content&#x60; to enrich each row with the rich content slab (summary, description, space, house rules, etc. — sourced from &#x60;listings_descriptions&#x60; for the &#x60;en&#x60; locale). Pass &#x60;?include&#x3D;details&#x60; for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.). Both default to &#x60;null&#x60; per row when the underlying &#x60;listings_descriptions&#x60; / &#x60;listings_details&#x60; row is missing — distinct from the field being absent (which signals the expansion was not requested). Combine comma-separated, e.g. &#x60;?include&#x3D;content,details&#x60;. The default response stays lean; consumers must opt in.
584
+ # Cursor-paginated list of listings owned by the authenticated workspace. Use &#x60;pagination.nextCursor&#x60; from one response as the &#x60;cursor&#x60; query param of the next request to walk the full set. &#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;, &#x60;channel&#x60;. **Optional expansions:** Pass &#x60;?include&#x3D;content&#x60; to enrich each row with the rich content slab (summary, description, space, house rules, etc. — sourced from &#x60;listings_descriptions&#x60; for the &#x60;en&#x60; locale). Pass &#x60;?include&#x3D;details&#x60; for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.). Both default to &#x60;null&#x60; per row when the underlying &#x60;listings_descriptions&#x60; / &#x60;listings_details&#x60; row is missing — distinct from the field being absent (which signals the expansion was not requested). Combine comma-separated, e.g. &#x60;?include&#x3D;content,details&#x60;. The default response stays lean; consumers must opt in. **Inactive listings:** by default only active listings are returned. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated, so when &#x60;status&#x60; asks for inactive ones they carry only &#x60;id&#x60;, &#x60;name&#x60;, &#x60;status&#x60; and &#x60;channels&#x60; — enough to choose what to activate with &#x60;PATCH /v1/listings/{id}&#x60;. &#x60;?include&#x3D;&#x60; expansions are not applied to them.
374
585
  # @param [Hash] opts the optional parameters
375
586
  # @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;.
376
587
  # @option opts [String] :cursor Opaque cursor returned in the previous response&#39;s &#x60;pagination.nextCursor&#x60;. Omit to fetch the first page.
377
- # @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.next_cursor&#x60; so consumers can switch from offset → cursor mid-walk for deep pagination without re-keying. (default to 0)
588
+ # @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)
378
589
  # @option opts [Integer] :limit Max items per page. Hard cap is 100. (default to 20)
379
590
  # @option opts [String] :q Case-insensitive substring search on name, street, or city.
380
- # @option opts [String] :status Filter by listing status.
591
+ # @option opts [String] :status Filter by listing status. Defaults to &#x60;active&#x60;. Pass &#x60;inactive&#x60; to list the listings you can activate, &#x60;archived&#x60; for archived ones, or &#x60;all&#x60; for every status. Inactive listings are returned with identity fields only — &#x60;id&#x60;, &#x60;name&#x60;, &#x60;status&#x60; and &#x60;channels&#x60; — and never with &#x60;address&#x60;, &#x60;thumbnailUrl&#x60;, &#x60;content&#x60; or &#x60;details&#x60;; activate one to see the rest. (default to 'active')
381
592
  # @option opts [String] :channel Restrict to listings published on the given channel (&#x60;airbnb&#x60;, &#x60;booking&#x60;, &#x60;vrbo&#x60;, etc.). Joins through &#x60;listing_platform_links&#x60; and matches active links only.
382
593
  # @option opts [String] :include Comma-separated optional expansions. Currently supported: &#x60;content&#x60;, &#x60;details&#x60;. Unknown values return 422 with a &#x60;valid_values&#x60; envelope. (Note: &#x60;amenities&#x60; is not yet supported on the list endpoint — use the detail endpoint to fetch amenity rows for a single listing.)
383
594
  # @return [Array<(ListingListResponse, Integer, Hash)>] ListingListResponse data, response status code and response headers
@@ -401,7 +612,7 @@ module Repull
401
612
  fail ArgumentError, 'invalid value for "opts[:"limit"]" when calling ListingsApi.list_listings, must be greater than or equal to 1.'
402
613
  end
403
614
 
404
- allowable_values = ["active", "inactive", "archived"]
615
+ allowable_values = ["active", "inactive", "archived", "all"]
405
616
  if @api_client.config.client_side_validation && opts[:'status'] && !allowable_values.include?(opts[:'status'])
406
617
  fail ArgumentError, "invalid value for \"status\", must be one of #{allowable_values}"
407
618
  end
@@ -454,7 +665,7 @@ module Repull
454
665
  end
455
666
 
456
667
  # Publish a listing to Airbnb
457
- # Push a Repull listing to Airbnb. Pass `airbnbConnectionId` to update an already-mapped Airbnb listing, or `hostId` to create a brand-new Airbnb listing under that host.
668
+ # Push a Repull listing to Airbnb. Pass `airbnbConnectionId` to update an already-mapped Airbnb listing, or `hostId` to create a brand-new Airbnb listing under that host. 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.
458
669
  # @param id [Integer]
459
670
  # @param [Hash] opts the optional parameters
460
671
  # @option opts [ListingPublishAirbnbRequest] :listing_publish_airbnb_request
@@ -465,7 +676,7 @@ module Repull
465
676
  end
466
677
 
467
678
  # Publish a listing to Airbnb
468
- # Push a Repull listing to Airbnb. Pass &#x60;airbnbConnectionId&#x60; to update an already-mapped Airbnb listing, or &#x60;hostId&#x60; to create a brand-new Airbnb listing under that host.
679
+ # Push a Repull listing to Airbnb. Pass &#x60;airbnbConnectionId&#x60; to update an already-mapped Airbnb listing, or &#x60;hostId&#x60; to create a brand-new Airbnb listing under that host. 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.
469
680
  # @param id [Integer]
470
681
  # @param [Hash] opts the optional parameters
471
682
  # @option opts [ListingPublishAirbnbRequest] :listing_publish_airbnb_request
@@ -524,7 +735,7 @@ module Repull
524
735
  end
525
736
 
526
737
  # Publish a listing to Booking.com
527
- # Push a Repull listing to Booking.com. The listing must already be mapped to a Booking property + room (created via the Booking-claim Connect flow).
738
+ # Push a Repull listing to Booking.com. The listing must already be mapped to a Booking property + room (created via the Booking-claim Connect flow). 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.
528
739
  # @param id [Integer]
529
740
  # @param [Hash] opts the optional parameters
530
741
  # @return [ListingPublishResponse]
@@ -534,7 +745,7 @@ module Repull
534
745
  end
535
746
 
536
747
  # Publish a listing to Booking.com
537
- # Push a Repull listing to Booking.com. The listing must already be mapped to a Booking property + room (created via the Booking-claim Connect flow).
748
+ # Push a Repull listing to Booking.com. The listing must already be mapped to a Booking property + room (created via the Booking-claim Connect flow). 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.
538
749
  # @param id [Integer]
539
750
  # @param [Hash] opts the optional parameters
540
751
  # @return [Array<(ListingPublishResponse, Integer, Hash)>] ListingPublishResponse data, response status code and response headers
@@ -586,8 +797,76 @@ module Repull
586
797
  return data, status_code, headers
587
798
  end
588
799
 
800
+ # Activate or deactivate listings in bulk
801
+ # Sets up to 500 listings active or inactive in one call. Send `{ \"listingIds\": [\"4118\", \"4119\"], \"active\": false }` to deactivate them, or `\"active\": true` to activate them. An inactive listing is not counted toward your plan's listing limit or billed. It is NOT deleted and the upstream channel (Airbnb / Booking.com / your PMS) is never touched — its data keeps syncing, so it is complete the moment you activate it again. Until then it cannot be read, changed, or receive webhooks. **All or nothing.** Nothing changes unless the whole request can be applied: - If any id is not one of your listings, the call returns `404` naming those ids. - If activating would take you over your plan's listing limit, the call returns `402 listings_limit_exceeded`. Only listings that are currently inactive count toward the new total, so re-sending ids that are already active never trips the limit. Deactivating is always allowed, including when your account is already over its limit — it is how you get back under it. **Idempotent.** Ids already in the requested state are returned in `unchanged`; ids this call changed are returned in `updated`. For a single listing, `PATCH /v1/listings/{id}` does the same.
802
+ # @param listing_status_batch_request [ListingStatusBatchRequest]
803
+ # @param [Hash] opts the optional parameters
804
+ # @return [ListingStatusBatchResponse]
805
+ def set_listings_status(listing_status_batch_request, opts = {})
806
+ data, _status_code, _headers = set_listings_status_with_http_info(listing_status_batch_request, opts)
807
+ data
808
+ end
809
+
810
+ # Activate or deactivate listings in bulk
811
+ # Sets up to 500 listings active or inactive in one call. Send &#x60;{ \&quot;listingIds\&quot;: [\&quot;4118\&quot;, \&quot;4119\&quot;], \&quot;active\&quot;: false }&#x60; to deactivate them, or &#x60;\&quot;active\&quot;: true&#x60; to activate them. An inactive listing is not counted toward your plan&#39;s listing limit or billed. It is NOT deleted and the upstream channel (Airbnb / Booking.com / your PMS) is never touched — its data keeps syncing, so it is complete the moment you activate it again. Until then it cannot be read, changed, or receive webhooks. **All or nothing.** Nothing changes unless the whole request can be applied: - If any id is not one of your listings, the call returns &#x60;404&#x60; naming those ids. - If activating would take you over your plan&#39;s listing limit, the call returns &#x60;402 listings_limit_exceeded&#x60;. Only listings that are currently inactive count toward the new total, so re-sending ids that are already active never trips the limit. Deactivating is always allowed, including when your account is already over its limit — it is how you get back under it. **Idempotent.** Ids already in the requested state are returned in &#x60;unchanged&#x60;; ids this call changed are returned in &#x60;updated&#x60;. For a single listing, &#x60;PATCH /v1/listings/{id}&#x60; does the same.
812
+ # @param listing_status_batch_request [ListingStatusBatchRequest]
813
+ # @param [Hash] opts the optional parameters
814
+ # @return [Array<(ListingStatusBatchResponse, Integer, Hash)>] ListingStatusBatchResponse data, response status code and response headers
815
+ def set_listings_status_with_http_info(listing_status_batch_request, opts = {})
816
+ if @api_client.config.debugging
817
+ @api_client.config.logger.debug 'Calling API: ListingsApi.set_listings_status ...'
818
+ end
819
+ # verify the required parameter 'listing_status_batch_request' is set
820
+ if @api_client.config.client_side_validation && listing_status_batch_request.nil?
821
+ fail ArgumentError, "Missing the required parameter 'listing_status_batch_request' when calling ListingsApi.set_listings_status"
822
+ end
823
+ # resource path
824
+ local_var_path = '/v1/listings/status'
825
+
826
+ # query parameters
827
+ query_params = opts[:query_params] || {}
828
+
829
+ # header parameters
830
+ header_params = opts[:header_params] || {}
831
+ # HTTP header 'Accept' (if needed)
832
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
833
+ # HTTP header 'Content-Type'
834
+ content_type = @api_client.select_header_content_type(['application/json'])
835
+ if !content_type.nil?
836
+ header_params['Content-Type'] = content_type
837
+ end
838
+
839
+ # form parameters
840
+ form_params = opts[:form_params] || {}
841
+
842
+ # http body (model)
843
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(listing_status_batch_request)
844
+
845
+ # return_type
846
+ return_type = opts[:debug_return_type] || 'ListingStatusBatchResponse'
847
+
848
+ # auth_names
849
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
850
+
851
+ new_options = opts.merge(
852
+ :operation => :"ListingsApi.set_listings_status",
853
+ :header_params => header_params,
854
+ :query_params => query_params,
855
+ :form_params => form_params,
856
+ :body => post_body,
857
+ :auth_names => auth_names,
858
+ :return_type => return_type
859
+ )
860
+
861
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
862
+ if @api_client.config.debugging
863
+ @api_client.config.logger.debug "API called: ListingsApi#set_listings_status\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
864
+ end
865
+ return data, status_code, headers
866
+ end
867
+
589
868
  # Deactivate or reactivate a listing
590
- # Toggle a listing's active state. Send `{ \"active\": false }` to **deactivate** (exclude the listing from Repull) or `{ \"active\": true }` to **reactivate** it. \"Deactivate\" keeps the listing row — it is NOT a hard delete, and it NEVER touches the upstream channel (Airbnb / Hospitable / Booking.com). Repull only mutates its own copy of the inventory. Deactivating is the self-serve way to get back under the plan-listings cap without paying. Reactivation respects the plan-listings cap: if activating this listing would push you over the cap for your tier, the call returns `402 listings_limit_exceeded` and the listing stays inactive. Deactivate another listing or upgrade first. Idempotent: setting a listing to the state it's already in returns 200.
869
+ # Toggle a listing's active state. Send `{ \"active\": false }` to **deactivate** (exclude the listing from Repull) or `{ \"active\": true }` to **reactivate** it. \"Deactivate\" keeps the listing row — it is NOT a hard delete, and it NEVER touches the upstream channel (Airbnb / Hospitable / Booking.com). Repull only mutates its own copy of the inventory. Deactivating is the self-serve way to get back under the plan-listings cap without paying. Reactivation respects the plan-listings cap: if activating this listing would push you over the cap for your tier, the call returns `402 listings_limit_exceeded` and the listing stays inactive. Deactivate another listing or upgrade first. Idempotent: setting a listing to the state it's already in returns 200. To change many listings at once, all or nothing, use `POST /v1/listings/status`.
591
870
  # @param id [Integer] Repull listing id
592
871
  # @param listing_active_request [ListingActiveRequest]
593
872
  # @param [Hash] opts the optional parameters
@@ -598,7 +877,7 @@ module Repull
598
877
  end
599
878
 
600
879
  # Deactivate or reactivate a listing
601
- # Toggle a listing&#39;s active state. Send &#x60;{ \&quot;active\&quot;: false }&#x60; to **deactivate** (exclude the listing from Repull) or &#x60;{ \&quot;active\&quot;: true }&#x60; to **reactivate** it. \&quot;Deactivate\&quot; keeps the listing row — it is NOT a hard delete, and it NEVER touches the upstream channel (Airbnb / Hospitable / Booking.com). Repull only mutates its own copy of the inventory. Deactivating is the self-serve way to get back under the plan-listings cap without paying. Reactivation respects the plan-listings cap: if activating this listing would push you over the cap for your tier, the call returns &#x60;402 listings_limit_exceeded&#x60; and the listing stays inactive. Deactivate another listing or upgrade first. Idempotent: setting a listing to the state it&#39;s already in returns 200.
880
+ # Toggle a listing&#39;s active state. Send &#x60;{ \&quot;active\&quot;: false }&#x60; to **deactivate** (exclude the listing from Repull) or &#x60;{ \&quot;active\&quot;: true }&#x60; to **reactivate** it. \&quot;Deactivate\&quot; keeps the listing row — it is NOT a hard delete, and it NEVER touches the upstream channel (Airbnb / Hospitable / Booking.com). Repull only mutates its own copy of the inventory. Deactivating is the self-serve way to get back under the plan-listings cap without paying. Reactivation respects the plan-listings cap: if activating this listing would push you over the cap for your tier, the call returns &#x60;402 listings_limit_exceeded&#x60; and the listing stays inactive. Deactivate another listing or upgrade first. Idempotent: setting a listing to the state it&#39;s already in returns 200. To change many listings at once, all or nothing, use &#x60;POST /v1/listings/status&#x60;.
602
881
  # @param id [Integer] Repull listing id
603
882
  # @param listing_active_request [ListingActiveRequest]
604
883
  # @param [Hash] opts the optional parameters
@@ -661,7 +940,7 @@ module Repull
661
940
  end
662
941
 
663
942
  # Update canonical listing content
664
- # Write your PMS's canonical listing content — title, description, amenities, address, occupancy, and policies — into a Repull listing, making it the source of truth. This is the flagship \"the PMS owns listing content, Repull distributes it\" enabler. **Partial update:** every field is optional. Only the fields you send are written; absent fields are left untouched. `amenities` is a FULL replacement of the amenity set (omit to leave untouched, send `[]` to clear). **Local write only — NOT a channel publish.** This mutates Repull's own copy of the content. It does NOT push to Airbnb / Booking.com; it marks the channels dirty so a later publish knows what changed. Distribution stays a separate explicit step. **Photos are deferred:** a provided `photos` array is echoed back in the `deferred` field and NOT persisted (media ingestion is a follow-up). Cross-tenant access (a listing that belongs to a different workspace) returns 404 — never 403. This endpoint is served even when the account is over the plan-listings cap, since editing content on a listing you already own never grows the portfolio.
943
+ # Write your PMS's canonical listing content — title, description, amenities, address, occupancy, and policies — into a Repull listing, making it the source of truth. This is the flagship \"the PMS owns listing content, Repull distributes it\" enabler. **Partial update:** every field is optional. Only the fields you send are written; absent fields are left untouched. `amenities` is a FULL replacement of the amenity set (omit to leave untouched, send `[]` to clear). **Local write only — NOT a channel publish.** This mutates Repull's own copy of the content. It does NOT push to Airbnb / Booking.com; it marks the channels dirty so a later publish knows what changed. Distribution stays a separate explicit step. **Photos are deferred:** a provided `photos` array is echoed back in the `deferred` field and NOT persisted (media ingestion is a follow-up). Cross-tenant access (a listing that belongs to a different workspace) returns 404 — never 403. This endpoint is served even when the account is over the plan-listings cap, since editing content on a listing you already own never grows the portfolio. 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.
665
944
  # @param id [Integer] Repull listing id
666
945
  # @param listing_content_update_request [ListingContentUpdateRequest]
667
946
  # @param [Hash] opts the optional parameters
@@ -672,7 +951,7 @@ module Repull
672
951
  end
673
952
 
674
953
  # Update canonical listing content
675
- # Write your PMS&#39;s canonical listing content — title, description, amenities, address, occupancy, and policies — into a Repull listing, making it the source of truth. This is the flagship \&quot;the PMS owns listing content, Repull distributes it\&quot; enabler. **Partial update:** every field is optional. Only the fields you send are written; absent fields are left untouched. &#x60;amenities&#x60; is a FULL replacement of the amenity set (omit to leave untouched, send &#x60;[]&#x60; to clear). **Local write only — NOT a channel publish.** This mutates Repull&#39;s own copy of the content. It does NOT push to Airbnb / Booking.com; it marks the channels dirty so a later publish knows what changed. Distribution stays a separate explicit step. **Photos are deferred:** a provided &#x60;photos&#x60; array is echoed back in the &#x60;deferred&#x60; field and NOT persisted (media ingestion is a follow-up). Cross-tenant access (a listing that belongs to a different workspace) returns 404 — never 403. This endpoint is served even when the account is over the plan-listings cap, since editing content on a listing you already own never grows the portfolio.
954
+ # Write your PMS&#39;s canonical listing content — title, description, amenities, address, occupancy, and policies — into a Repull listing, making it the source of truth. This is the flagship \&quot;the PMS owns listing content, Repull distributes it\&quot; enabler. **Partial update:** every field is optional. Only the fields you send are written; absent fields are left untouched. &#x60;amenities&#x60; is a FULL replacement of the amenity set (omit to leave untouched, send &#x60;[]&#x60; to clear). **Local write only — NOT a channel publish.** This mutates Repull&#39;s own copy of the content. It does NOT push to Airbnb / Booking.com; it marks the channels dirty so a later publish knows what changed. Distribution stays a separate explicit step. **Photos are deferred:** a provided &#x60;photos&#x60; array is echoed back in the &#x60;deferred&#x60; field and NOT persisted (media ingestion is a follow-up). Cross-tenant access (a listing that belongs to a different workspace) returns 404 — never 403. This endpoint is served even when the account is over the plan-listings cap, since editing content on a listing you already own never grows the portfolio. 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.
676
955
  # @param id [Integer] Repull listing id
677
956
  # @param listing_content_update_request [ListingContentUpdateRequest]
678
957
  # @param [Hash] opts the optional parameters
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
  #Repull API
3
3
 
4
- #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_test_YOUR_API_KEY ``` Sandbox keys start with `sk_test_`, production with `sk_live_`. ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resets_at` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | 50 | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
4
+ #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_live_YOUR_API_KEY ``` ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resetsAt` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | 50 | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
5
 
6
6
  The version of the OpenAPI document: 1.0.0
7
7
  Contact: ivan@vanio.ai
@@ -168,7 +168,7 @@ module Repull
168
168
  # @option opts [String] :country ISO 3166-1 alpha-2 (e.g. &#x60;US&#x60;, &#x60;ES&#x60;).
169
169
  # @option opts [Integer] :min_listings Minimum comp-set size — cities with fewer active comps are excluded. (default to 5)
170
170
  # @option opts [String] :cursor Opaque cursor returned by the previous page&#39;s &#x60;pagination.nextCursor&#x60;.
171
- # @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.next_cursor&#x60; so consumers can switch from offset → cursor mid-walk for deep pagination without re-keying. (default to 0)
171
+ # @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)
172
172
  # @option opts [Integer] :limit (default to 30)
173
173
  # @option opts [String] :sort (default to 'listings_desc')
174
174
  # @return [MarketBrowseResponse]
@@ -184,7 +184,7 @@ module Repull
184
184
  # @option opts [String] :country ISO 3166-1 alpha-2 (e.g. &#x60;US&#x60;, &#x60;ES&#x60;).
185
185
  # @option opts [Integer] :min_listings Minimum comp-set size — cities with fewer active comps are excluded. (default to 5)
186
186
  # @option opts [String] :cursor Opaque cursor returned by the previous page&#39;s &#x60;pagination.nextCursor&#x60;.
187
- # @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.next_cursor&#x60; so consumers can switch from offset → cursor mid-walk for deep pagination without re-keying. (default to 0)
187
+ # @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)
188
188
  # @option opts [Integer] :limit (default to 30)
189
189
  # @option opts [String] :sort (default to 'listings_desc')
190
190
  # @return [Array<(MarketBrowseResponse, Integer, Hash)>] MarketBrowseResponse data, response status code and response headers