repull 0.2.10 → 0.2.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (453) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/repull/api/airbnb_api.rb +1569 -196
  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 +763 -10
  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 +392 -29
  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_account_freshness.rb +239 -0
  41. data/lib/repull/models/airbnb_alteration.rb +198 -10
  42. data/lib/repull/models/airbnb_alteration_create_request.rb +264 -0
  43. data/lib/repull/models/airbnb_amenity.rb +1 -1
  44. data/lib/repull/models/airbnb_availability_write_request.rb +20 -1
  45. data/lib/repull/models/airbnb_calendar_operation.rb +97 -8
  46. data/lib/repull/models/airbnb_connection.rb +73 -6
  47. data/lib/repull/models/airbnb_connection_accessibility_amenities_inner.rb +1 -1
  48. data/lib/repull/models/airbnb_connection_amenities_inner.rb +1 -1
  49. data/lib/repull/models/airbnb_connection_host.rb +2 -2
  50. data/lib/repull/models/airbnb_connection_response.rb +1 -1
  51. data/lib/repull/models/airbnb_connection_summary.rb +1 -1
  52. data/lib/repull/models/airbnb_content_write_response.rb +275 -0
  53. data/lib/repull/models/airbnb_data_freshness.rb +24 -12
  54. data/lib/repull/models/airbnb_description_write_request.rb +192 -0
  55. data/lib/repull/models/airbnb_description_write_request_description.rb +365 -0
  56. data/lib/repull/models/airbnb_listing.rb +14 -3
  57. data/lib/repull/models/airbnb_listing_action200_response.rb +105 -0
  58. data/lib/repull/models/airbnb_listing_action200_response_one_of.rb +157 -0
  59. data/lib/repull/models/airbnb_listing_action200_response_one_of1.rb +175 -0
  60. data/lib/repull/models/airbnb_listing_action_request.rb +3 -3
  61. data/lib/repull/models/airbnb_listing_details_response.rb +284 -0
  62. data/lib/repull/models/airbnb_listing_details_write_request.rb +209 -0
  63. data/lib/repull/models/airbnb_listing_details_write_request_check_in_option.rb +214 -0
  64. data/lib/repull/models/airbnb_listing_details_write_request_quiet_hours_inner.rb +190 -0
  65. data/lib/repull/models/airbnb_listing_lifecycle_response.rb +196 -0
  66. data/lib/repull/models/airbnb_listing_list_response.rb +2 -2
  67. data/lib/repull/models/airbnb_permits_response.rb +163 -0
  68. data/lib/repull/models/airbnb_permits_response_cached_inner.rb +200 -0
  69. data/lib/repull/models/airbnb_permits_write_request.rb +176 -0
  70. data/lib/repull/models/airbnb_permits_write_request_permits_inner.rb +228 -0
  71. data/lib/repull/models/airbnb_permits_write_request_permits_inner_answers_inner.rb +198 -0
  72. data/lib/repull/models/airbnb_photo_position.rb +159 -0
  73. data/lib/repull/models/airbnb_pricing_write_request.rb +54 -3
  74. data/lib/repull/models/airbnb_pricing_write_request_records_inner.rb +236 -0
  75. data/lib/repull/models/airbnb_publish_result.rb +263 -0
  76. data/lib/repull/models/airbnb_reservation.rb +24 -2
  77. data/lib/repull/models/airbnb_reservation_list_response.rb +15 -6
  78. data/lib/repull/models/airbnb_review.rb +24 -2
  79. data/lib/repull/models/airbnb_review_list_response.rb +14 -5
  80. data/lib/repull/models/airbnb_safety_disclosure.rb +202 -0
  81. data/lib/repull/models/airbnb_safety_disclosures_response.rb +162 -0
  82. data/lib/repull/models/airbnb_safety_disclosures_write_request.rb +176 -0
  83. data/lib/repull/models/airbnb_thread.rb +24 -2
  84. data/lib/repull/models/airbnb_thread_list_response.rb +14 -5
  85. data/lib/repull/models/airbnb_transaction.rb +524 -0
  86. data/lib/repull/models/airbnb_transaction_guest_breakdown.rb +171 -0
  87. data/lib/repull/models/airbnb_transaction_host_breakdown.rb +246 -0
  88. data/lib/repull/models/airbnb_transaction_payout.rb +175 -0
  89. data/lib/repull/models/alteration_change.rb +161 -0
  90. data/lib/repull/models/alteration_webhook_object.rb +296 -0
  91. data/lib/repull/models/availability_batch_write_request.rb +296 -0
  92. data/lib/repull/models/availability_write_request.rb +259 -0
  93. data/lib/repull/models/availability_write_result.rb +178 -0
  94. data/lib/repull/models/availability_write_result_synced.rb +176 -0
  95. data/lib/repull/models/availability_write_settings.rb +215 -0
  96. data/lib/repull/models/booking_availability_state_response.rb +149 -0
  97. data/lib/repull/models/booking_availability_update.rb +1 -1
  98. data/lib/repull/models/booking_availability_update_request.rb +1 -1
  99. data/lib/repull/models/booking_availability_update_request_property_id.rb +1 -1
  100. data/lib/repull/models/booking_availability_update_request_updates_inner.rb +1 -1
  101. data/lib/repull/models/booking_connect_listing_option.rb +1 -1
  102. data/lib/repull/models/booking_connect_room.rb +1 -1
  103. data/lib/repull/models/booking_connect_rooms_response.rb +39 -5
  104. data/lib/repull/models/booking_conversation.rb +1 -1
  105. data/lib/repull/models/booking_pricing_rate_update.rb +1 -1
  106. data/lib/repull/models/booking_pricing_rate_update_date_range.rb +1 -1
  107. data/lib/repull/models/booking_pricing_rate_update_restrictions.rb +1 -1
  108. data/lib/repull/models/booking_pricing_response.rb +1 -1
  109. data/lib/repull/models/booking_pricing_update_request.rb +1 -1
  110. data/lib/repull/models/booking_pricing_update_response.rb +1 -1
  111. data/lib/repull/models/booking_property.rb +1 -1
  112. data/lib/repull/models/booking_reservation.rb +277 -0
  113. data/lib/repull/models/booking_reservation_room.rb +271 -0
  114. data/lib/repull/models/booking_room_mapping.rb +18 -8
  115. data/lib/repull/models/booking_rooms_rates_response.rb +170 -0
  116. data/lib/repull/models/booking_rooms_rates_response_rooms_inner.rb +170 -0
  117. data/lib/repull/models/booking_rooms_rates_response_rooms_inner_rates_inner.rb +212 -0
  118. data/lib/repull/models/booking_setup_request.rb +1 -1
  119. data/lib/repull/models/booking_verify_hotel_request.rb +1 -1
  120. data/lib/repull/models/booking_verify_hotel_response.rb +40 -6
  121. data/lib/repull/models/bulk_pricing_failure.rb +1 -1
  122. data/lib/repull/models/bulk_pricing_item.rb +1 -1
  123. data/lib/repull/models/bulk_pricing_request.rb +1 -1
  124. data/lib/repull/models/bulk_pricing_response.rb +1 -1
  125. data/lib/repull/models/calendar_day.rb +1 -1
  126. data/lib/repull/models/calendar_response.rb +1 -1
  127. data/lib/repull/models/calendar_updated_event.rb +1 -1
  128. data/lib/repull/models/calendar_updated_payload.rb +1 -1
  129. data/lib/repull/models/calendar_updated_payload_range.rb +1 -1
  130. data/lib/repull/models/clear_kv200_response.rb +1 -1
  131. data/lib/repull/models/connect_host.rb +1 -1
  132. data/lib/repull/models/connect_provider.rb +1 -1
  133. data/lib/repull/models/connect_provider_list_response.rb +1 -1
  134. data/lib/repull/models/connect_session.rb +1 -1
  135. data/lib/repull/models/connect_status.rb +18 -6
  136. data/lib/repull/models/connect_status_accounts_inner.rb +188 -0
  137. data/lib/repull/models/connection.rb +1 -1
  138. data/lib/repull/models/connection_list_response.rb +1 -1
  139. data/lib/repull/models/conversation.rb +13 -2
  140. data/lib/repull/models/conversation_detail.rb +13 -2
  141. data/lib/repull/models/conversation_guest.rb +1 -1
  142. data/lib/repull/models/conversation_guest_contact.rb +1 -1
  143. data/lib/repull/models/conversation_host.rb +1 -1
  144. data/lib/repull/models/conversation_list_response.rb +1 -1
  145. data/lib/repull/models/conversation_message_attachment.rb +1 -1
  146. data/lib/repull/models/create_airbnb_listing_room_request.rb +315 -0
  147. data/lib/repull/models/create_airbnb_offer_request.rb +1 -1
  148. data/lib/repull/models/create_billing_checkout_request.rb +1 -1
  149. data/lib/repull/models/create_booking_webhook_request.rb +1 -1
  150. data/lib/repull/models/create_connect_session_request.rb +1 -1
  151. data/lib/repull/models/create_connection_request.rb +2 -2
  152. data/lib/repull/models/create_webhook_request.rb +1 -1
  153. data/lib/repull/models/custom_schema.rb +1 -1
  154. data/lib/repull/models/custom_schema_create.rb +1 -1
  155. data/lib/repull/models/custom_schema_create_response.rb +1 -1
  156. data/lib/repull/models/custom_schema_delete_response.rb +1 -1
  157. data/lib/repull/models/custom_schema_list_response.rb +1 -1
  158. data/lib/repull/models/custom_schema_summary.rb +1 -1
  159. data/lib/repull/models/custom_schema_update.rb +1 -1
  160. data/lib/repull/models/delete_airbnb_listing_photo200_response.rb +15 -5
  161. data/lib/repull/models/delete_airbnb_listing_room200_response.rb +157 -0
  162. data/lib/repull/models/delete_connection200_response.rb +234 -0
  163. data/lib/repull/models/delete_kv200_response.rb +1 -1
  164. data/lib/repull/models/error.rb +1 -1
  165. data/lib/repull/models/error_error.rb +44 -2
  166. data/lib/repull/models/error_error_support.rb +1 -1
  167. data/lib/repull/models/get_airbnb_alteration200_response.rb +2 -2
  168. data/lib/repull/models/get_airbnb_booking_settings200_response.rb +190 -0
  169. data/lib/repull/models/get_airbnb_booking_settings200_response_data.rb +246 -0
  170. data/lib/repull/models/get_airbnb_booking_settings200_response_data_advance_notice.rb +172 -0
  171. data/lib/repull/models/get_airbnb_booking_settings200_response_data_booking_window.rb +160 -0
  172. data/lib/repull/models/get_airbnb_booking_settings200_response_data_cancellation.rb +203 -0
  173. data/lib/repull/models/get_airbnb_booking_settings200_response_data_cancellation_non_refundable.rb +218 -0
  174. data/lib/repull/models/get_airbnb_booking_settings200_response_data_check_in.rb +159 -0
  175. data/lib/repull/models/get_airbnb_booking_settings200_response_data_check_in_start.rb +104 -0
  176. data/lib/repull/models/get_airbnb_booking_settings200_response_data_check_out.rb +172 -0
  177. data/lib/repull/models/get_airbnb_booking_settings200_response_data_instant_book.rb +206 -0
  178. data/lib/repull/models/get_airbnb_booking_settings200_response_data_preparation_time.rb +173 -0
  179. data/lib/repull/models/get_airbnb_checkin_guide200_response.rb +192 -0
  180. data/lib/repull/models/get_airbnb_listing_details200_response.rb +192 -0
  181. data/lib/repull/models/get_airbnb_listing_quality200_response.rb +2 -2
  182. data/lib/repull/models/get_airbnb_listing_settings200_response.rb +2 -2
  183. data/lib/repull/models/get_airbnb_thread200_response.rb +2 -2
  184. data/lib/repull/models/get_health200_response.rb +1 -1
  185. data/lib/repull/models/get_usage_logs200_response.rb +1 -1
  186. data/lib/repull/models/get_usage_logs200_response_data_inner.rb +1 -1
  187. data/lib/repull/models/get_usage_logs200_response_pagination.rb +3 -3
  188. data/lib/repull/models/get_usage_summary200_response.rb +2 -2
  189. data/lib/repull/models/get_usage_summary200_response_breakdown_inner.rb +1 -1
  190. data/lib/repull/models/get_usage_summary200_response_limits.rb +3 -3
  191. data/lib/repull/models/get_usage_summary200_response_remaining.rb +2 -2
  192. data/lib/repull/models/get_usage_summary200_response_status_distribution.rb +1 -1
  193. data/lib/repull/models/get_usage_summary200_response_timeline_inner.rb +1 -1
  194. data/lib/repull/models/get_usage_summary200_response_totals.rb +1 -1
  195. data/lib/repull/models/get_usage_summary200_response_used.rb +2 -2
  196. data/lib/repull/models/get_usage_tier200_response.rb +2 -2
  197. data/lib/repull/models/get_usage_tier200_response_limits.rb +4 -4
  198. data/lib/repull/models/get_usage_tier200_response_remaining.rb +3 -3
  199. data/lib/repull/models/get_usage_tier200_response_used.rb +3 -3
  200. data/lib/repull/models/guest.rb +1 -1
  201. data/lib/repull/models/guest_contact.rb +1 -1
  202. data/lib/repull/models/guest_create_request.rb +250 -0
  203. data/lib/repull/models/guest_create_response.rb +227 -0
  204. data/lib/repull/models/guest_create_response_contacts_inner.rb +199 -0
  205. data/lib/repull/models/guest_flag.rb +1 -1
  206. data/lib/repull/models/guest_list_response.rb +1 -1
  207. data/lib/repull/models/guest_note.rb +1 -1
  208. data/lib/repull/models/guest_profile.rb +1 -1
  209. data/lib/repull/models/guest_reservations_summary.rb +1 -1
  210. data/lib/repull/models/list_airbnb_alterations200_response.rb +2 -2
  211. data/lib/repull/models/list_airbnb_listing_amenities200_response.rb +2 -2
  212. data/lib/repull/models/list_airbnb_listing_amenities200_response_data.rb +1 -1
  213. data/lib/repull/models/list_airbnb_listing_permits200_response.rb +190 -0
  214. data/lib/repull/models/list_airbnb_listing_safety_disclosures200_response.rb +190 -0
  215. data/lib/repull/models/list_airbnb_transactions200_response.rb +3 -3
  216. data/lib/repull/models/list_booking_reservations200_response.rb +104 -0
  217. data/lib/repull/models/list_kv200_response.rb +1 -1
  218. data/lib/repull/models/list_kv200_response_data_inner.rb +1 -1
  219. data/lib/repull/models/list_kv200_response_pagination.rb +2 -2
  220. data/lib/repull/models/listing.rb +3 -2
  221. data/lib/repull/models/listing_active_request.rb +2 -2
  222. data/lib/repull/models/listing_active_response.rb +1 -1
  223. data/lib/repull/models/listing_address.rb +1 -1
  224. data/lib/repull/models/listing_amenity.rb +1 -1
  225. data/lib/repull/models/listing_channel.rb +1 -1
  226. data/lib/repull/models/listing_comp.rb +1 -1
  227. data/lib/repull/models/listing_comp_nightly.rb +1 -1
  228. data/lib/repull/models/listing_comp_ratings.rb +1 -1
  229. data/lib/repull/models/listing_comps_response.rb +1 -1
  230. data/lib/repull/models/listing_content.rb +14 -3
  231. data/lib/repull/models/listing_content_update_request.rb +22 -3
  232. data/lib/repull/models/listing_content_update_request_address.rb +1 -1
  233. data/lib/repull/models/listing_content_update_request_amenities.rb +1 -1
  234. data/lib/repull/models/listing_content_update_request_amenities_one_of_inner.rb +1 -1
  235. data/lib/repull/models/listing_content_update_request_details.rb +206 -0
  236. data/lib/repull/models/listing_content_update_request_occupancy.rb +1 -1
  237. data/lib/repull/models/listing_content_update_request_photos_inner.rb +1 -1
  238. data/lib/repull/models/listing_content_update_request_photos_inner_one_of.rb +1 -1
  239. data/lib/repull/models/listing_content_update_request_policies.rb +96 -6
  240. data/lib/repull/models/listing_content_update_response.rb +2 -2
  241. data/lib/repull/models/listing_create_request.rb +1 -1
  242. data/lib/repull/models/listing_create_response.rb +1 -1
  243. data/lib/repull/models/listing_created_event.rb +1 -1
  244. data/lib/repull/models/listing_created_payload.rb +1 -1
  245. data/lib/repull/models/listing_created_payload_address.rb +1 -1
  246. data/lib/repull/models/listing_deleted_event.rb +1 -1
  247. data/lib/repull/models/listing_deleted_payload.rb +1 -1
  248. data/lib/repull/models/listing_details.rb +1 -1
  249. data/lib/repull/models/listing_generate_content_request.rb +1 -1
  250. data/lib/repull/models/listing_generate_content_response.rb +1 -1
  251. data/lib/repull/models/listing_list_response.rb +1 -1
  252. data/lib/repull/models/{studio_file.rb → listing_photo.rb} +23 -34
  253. data/lib/repull/models/listing_photo_delete_request.rb +165 -0
  254. data/lib/repull/models/{studio_error.rb → listing_photo_delete_response.rb} +20 -12
  255. data/lib/repull/models/listing_photo_upload_url_request.rb +203 -0
  256. data/lib/repull/models/listing_photo_upload_url_response.rb +198 -0
  257. data/lib/repull/models/{vrbo_listing_list_response.rb → listing_photos_response.rb} +19 -19
  258. data/lib/repull/models/listing_pricing_apply_request.rb +1 -1
  259. data/lib/repull/models/listing_pricing_apply_response.rb +1 -1
  260. data/lib/repull/models/listing_pricing_history_entry.rb +2 -2
  261. data/lib/repull/models/listing_pricing_history_response.rb +1 -1
  262. data/lib/repull/models/listing_pricing_recommendation.rb +1 -1
  263. data/lib/repull/models/listing_pricing_response.rb +1 -1
  264. data/lib/repull/models/listing_pricing_response_comp_summary.rb +1 -1
  265. data/lib/repull/models/listing_pricing_response_date_range.rb +1 -1
  266. data/lib/repull/models/listing_pricing_response_listing.rb +1 -1
  267. data/lib/repull/models/listing_pricing_strategy.rb +1 -1
  268. data/lib/repull/models/listing_pricing_strategy_input.rb +1 -1
  269. data/lib/repull/models/listing_publish_airbnb_request.rb +1 -1
  270. data/lib/repull/models/listing_publish_airbnb_response.rb +165 -0
  271. data/lib/repull/models/listing_publish_response.rb +1 -1
  272. data/lib/repull/models/listing_publish_status_channel.rb +1 -1
  273. data/lib/repull/models/listing_publish_status_connection.rb +1 -1
  274. data/lib/repull/models/listing_publish_status_response.rb +1 -1
  275. data/lib/repull/models/listing_pull_airbnb_request.rb +149 -0
  276. data/lib/repull/models/listing_pull_response.rb +231 -0
  277. data/lib/repull/models/listing_quality_tier.rb +1 -1
  278. data/lib/repull/models/listing_segment.rb +1 -1
  279. data/lib/repull/models/listing_segment_recommendation.rb +1 -1
  280. data/lib/repull/models/listing_segments_response.rb +1 -1
  281. data/lib/repull/models/listing_segments_response_scope.rb +1 -1
  282. data/lib/repull/models/listing_status_batch_request.rb +212 -0
  283. data/lib/repull/models/{sandbox_reset_result.rb → listing_status_batch_response.rb} +57 -51
  284. data/lib/repull/models/listing_updated_event.rb +1 -1
  285. data/lib/repull/models/listing_updated_payload.rb +1 -1
  286. data/lib/repull/models/map_airbnb_listing_request.rb +1 -1
  287. data/lib/repull/models/map_airbnb_listing_response.rb +1 -1
  288. data/lib/repull/models/map_connect_booking_rooms_request.rb +1 -1
  289. data/lib/repull/models/map_connect_booking_rooms_response.rb +16 -5
  290. data/lib/repull/models/market_browse_category.rb +1 -1
  291. data/lib/repull/models/market_browse_entry.rb +1 -1
  292. data/lib/repull/models/market_browse_featured.rb +1 -1
  293. data/lib/repull/models/market_browse_response.rb +1 -1
  294. data/lib/repull/models/market_calendar_day.rb +1 -1
  295. data/lib/repull/models/market_calendar_day_events_inner.rb +1 -1
  296. data/lib/repull/models/market_calendar_response.rb +1 -1
  297. data/lib/repull/models/market_detail_response.rb +1 -1
  298. data/lib/repull/models/market_detail_response_price_distribution_inner.rb +1 -1
  299. data/lib/repull/models/market_detail_response_property_type_mix_inner.rb +1 -1
  300. data/lib/repull/models/market_detail_response_supply_trend_inner.rb +1 -1
  301. data/lib/repull/models/market_detail_response_top_comps.rb +1 -1
  302. data/lib/repull/models/market_event.rb +1 -1
  303. data/lib/repull/models/market_my_listing.rb +1 -1
  304. data/lib/repull/models/market_summary.rb +1 -1
  305. data/lib/repull/models/market_top_comp.rb +1 -1
  306. data/lib/repull/models/markets_overview_response.rb +1 -1
  307. data/lib/repull/models/markets_overview_response_browse.rb +1 -1
  308. data/lib/repull/models/markets_overview_response_subscriptions.rb +1 -1
  309. data/lib/repull/models/markets_overview_response_totals.rb +1 -1
  310. data/lib/repull/models/message.rb +1 -1
  311. data/lib/repull/models/message_list_response.rb +1 -1
  312. data/lib/repull/models/pagination.rb +1 -1
  313. data/lib/repull/models/payment_completed_event.rb +1 -1
  314. data/lib/repull/models/payment_completed_payload.rb +1 -1
  315. data/lib/repull/models/payment_refunded_event.rb +1 -1
  316. data/lib/repull/models/payment_refunded_payload.rb +1 -1
  317. data/lib/repull/models/plumguide_listing.rb +1 -1
  318. data/lib/repull/models/plumguide_listing_list_response.rb +1 -1
  319. data/lib/repull/models/property.rb +17 -7
  320. data/lib/repull/models/property_availability.rb +33 -7
  321. data/lib/repull/models/property_availability_coverage.rb +222 -0
  322. data/lib/repull/models/property_availability_day.rb +4 -4
  323. data/lib/repull/models/property_list_response.rb +1 -1
  324. data/lib/repull/models/{studio_error_error.rb → publish_section_error.rb} +56 -36
  325. data/lib/repull/models/quote.rb +240 -0
  326. data/lib/repull/models/quote_pricing.rb +218 -0
  327. data/lib/repull/models/reorder_airbnb_listing_photos200_response.rb +191 -0
  328. data/lib/repull/models/reorder_airbnb_listing_photos200_response_data.rb +172 -0
  329. data/lib/repull/models/reorder_airbnb_listing_photos_request.rb +185 -0
  330. data/lib/repull/models/reply_booking_review200_response.rb +1 -1
  331. data/lib/repull/models/reply_booking_review_request.rb +1 -1
  332. data/lib/repull/models/reply_to_review201_response.rb +165 -0
  333. data/lib/repull/models/reply_to_review_request.rb +165 -0
  334. data/lib/repull/models/repull_ping_event.rb +1 -1
  335. data/lib/repull/models/repull_ping_payload.rb +1 -1
  336. data/lib/repull/models/reservation.rb +24 -2
  337. data/lib/repull/models/{studio_deployment.rb → reservation_alteration_created_event.rb} +67 -57
  338. data/lib/repull/models/reservation_alteration_created_payload.rb +177 -0
  339. data/lib/repull/models/reservation_alteration_responded_event.rb +217 -0
  340. data/lib/repull/models/reservation_alteration_responded_payload.rb +175 -0
  341. data/lib/repull/models/reservation_cancelled_event.rb +1 -1
  342. data/lib/repull/models/reservation_cancelled_payload.rb +1 -1
  343. data/lib/repull/models/reservation_create_request.rb +403 -0
  344. data/lib/repull/models/{create_airbnb_alteration_request.rb → reservation_create_response.rb} +73 -35
  345. data/lib/repull/models/reservation_created_event.rb +1 -1
  346. data/lib/repull/models/reservation_created_payload.rb +1 -1
  347. data/lib/repull/models/reservation_financials.rb +36 -8
  348. data/lib/repull/models/reservation_guest_financials.rb +173 -0
  349. data/lib/repull/models/reservation_guest_input.rb +193 -0
  350. data/lib/repull/models/reservation_host_financials.rb +207 -0
  351. data/lib/repull/models/reservation_list_response.rb +1 -1
  352. data/lib/repull/models/reservation_message_received_event.rb +1 -1
  353. data/lib/repull/models/reservation_message_received_payload.rb +1 -1
  354. data/lib/repull/models/reservation_message_received_payload_from.rb +1 -1
  355. data/lib/repull/models/reservation_money_line.rb +216 -0
  356. data/lib/repull/models/reservation_occupancy.rb +1 -1
  357. data/lib/repull/models/reservation_primary_guest.rb +1 -1
  358. data/lib/repull/models/reservation_update_request.rb +255 -0
  359. data/lib/repull/models/reservation_update_response.rb +240 -0
  360. data/lib/repull/models/reservation_updated_event.rb +1 -1
  361. data/lib/repull/models/reservation_updated_payload.rb +1 -1
  362. data/lib/repull/models/reservation_webhook_object.rb +39 -6
  363. data/lib/repull/models/respond_airbnb_review_request.rb +1 -1
  364. data/lib/repull/models/review.rb +14 -3
  365. data/lib/repull/models/review_category.rb +1 -1
  366. data/lib/repull/models/review_created_event.rb +217 -0
  367. data/lib/repull/models/review_created_payload.rb +165 -0
  368. data/lib/repull/models/review_list_response.rb +1 -1
  369. data/lib/repull/models/review_responded_event.rb +217 -0
  370. data/lib/repull/models/review_responded_payload.rb +175 -0
  371. data/lib/repull/models/review_response.rb +1 -1
  372. data/lib/repull/models/review_webhook_object.rb +277 -0
  373. data/lib/repull/models/rotate_webhook_secret200_response.rb +1 -1
  374. data/lib/repull/models/select_connect_provider_request.rb +1 -1
  375. data/lib/repull/models/select_provider_response.rb +1 -1
  376. data/lib/repull/models/send_airbnb_message_request.rb +187 -0
  377. data/lib/repull/models/{sandbox_reset_result_deleted.rb → send_booking_message_request.rb} +53 -50
  378. data/lib/repull/models/send_message_request.rb +193 -0
  379. data/lib/repull/models/send_message_response.rb +241 -0
  380. data/lib/repull/models/set_airbnb_listing_cover_photo200_response.rb +191 -0
  381. data/lib/repull/models/set_airbnb_listing_cover_photo200_response_data.rb +171 -0
  382. data/lib/repull/models/set_airbnb_listing_cover_photo_request.rb +165 -0
  383. data/lib/repull/models/set_kv_request.rb +1 -1
  384. data/lib/repull/models/{booking_property_list_response.rb → submit_beds24_credentials200_response.rb} +19 -19
  385. data/lib/repull/models/submit_beds24_credentials_request.rb +177 -0
  386. data/lib/repull/models/submit_bookingsync_credentials_request.rb +177 -0
  387. data/lib/repull/models/submit_guesty_credentials_request.rb +177 -0
  388. data/lib/repull/models/submit_hospitable_credentials_request.rb +177 -0
  389. data/lib/repull/models/submit_hostaway_credentials_request.rb +177 -0
  390. data/lib/repull/models/submit_igms_credentials_request.rb +177 -0
  391. data/lib/repull/models/submit_lodgify_credentials_request.rb +177 -0
  392. data/lib/repull/models/submit_ownerrez_credentials_request.rb +177 -0
  393. data/lib/repull/models/submit_smoobu_credentials_request.rb +177 -0
  394. data/lib/repull/models/submit_vrbo_credentials_request.rb +177 -0
  395. data/lib/repull/models/sync_airbnb_transactions200_response.rb +191 -0
  396. data/lib/repull/models/sync_airbnb_transactions_request.rb +201 -0
  397. data/lib/repull/models/test_webhook_request.rb +1 -1
  398. data/lib/repull/models/{booking_conversation_list_response.rb → update_airbnb_booking_settings200_response.rb} +26 -20
  399. data/lib/repull/models/update_airbnb_booking_settings200_response_data.rb +205 -0
  400. data/lib/repull/models/update_airbnb_booking_settings_request.rb +202 -0
  401. data/lib/repull/models/update_airbnb_booking_settings_request_advance_notice.rb +183 -0
  402. data/lib/repull/models/update_airbnb_booking_settings_request_booking_window.rb +183 -0
  403. data/lib/repull/models/update_airbnb_booking_settings_request_cancellation.rb +201 -0
  404. data/lib/repull/models/update_airbnb_booking_settings_request_cancellation_non_refundable.rb +183 -0
  405. data/lib/repull/models/update_airbnb_booking_settings_request_check_in.rb +159 -0
  406. data/lib/repull/models/update_airbnb_booking_settings_request_check_out.rb +182 -0
  407. data/lib/repull/models/update_airbnb_booking_settings_request_instant_book.rb +203 -0
  408. data/lib/repull/models/update_airbnb_booking_settings_request_preparation_time.rb +182 -0
  409. data/lib/repull/models/update_airbnb_listing_amenities200_response.rb +191 -0
  410. data/lib/repull/models/update_airbnb_listing_amenities200_response_data.rb +158 -0
  411. data/lib/repull/models/update_airbnb_listing_amenities_request.rb +199 -0
  412. data/lib/repull/models/update_airbnb_listing_amenities_request_accessibility_amenities_inner.rb +246 -0
  413. data/lib/repull/models/update_airbnb_listing_amenities_request_amenities_inner.rb +218 -0
  414. data/lib/repull/models/update_airbnb_listing_permits200_response.rb +168 -0
  415. data/lib/repull/models/update_airbnb_listing_photo200_response.rb +194 -0
  416. data/lib/repull/models/update_airbnb_listing_photo_request.rb +242 -0
  417. data/lib/repull/models/update_airbnb_listing_room200_response.rb +194 -0
  418. data/lib/repull/models/update_airbnb_listing_room_request.rb +293 -0
  419. data/lib/repull/models/update_airbnb_listing_room_request_beds_inner.rb +209 -0
  420. data/lib/repull/models/{sandbox_fixture_ref.rb → update_airbnb_listing_room_request_room_amenities_inner.rb} +26 -37
  421. data/lib/repull/models/update_airbnb_listing_room_request_room_amenities_inner_value.rb +105 -0
  422. data/lib/repull/models/update_airbnb_listing_safety_disclosures200_response.rb +180 -0
  423. data/lib/repull/models/update_airbnb_message_request.rb +1 -1
  424. data/lib/repull/models/update_booking_charges_request.rb +1 -1
  425. data/lib/repull/models/update_listing_pricing_strategy200_response.rb +1 -1
  426. data/lib/repull/models/update_webhook_request.rb +1 -1
  427. data/lib/repull/models/upload_airbnb_listing_photos_request.rb +184 -0
  428. data/lib/repull/models/upload_airbnb_listing_photos_request_photos_inner.rb +305 -0
  429. data/lib/repull/models/upload_airbnb_listing_photos_request_photos_inner_listing_id.rb +105 -0
  430. data/lib/repull/models/vrbo_listing.rb +1 -1
  431. data/lib/repull/models/vrbo_reservation.rb +1 -1
  432. data/lib/repull/models/vrbo_reservation_list_response.rb +1 -1
  433. data/lib/repull/models/webhook_delivery.rb +1 -1
  434. data/lib/repull/models/webhook_delivery_detail.rb +1 -1
  435. data/lib/repull/models/webhook_delivery_list_response.rb +1 -1
  436. data/lib/repull/models/webhook_event.rb +12 -4
  437. data/lib/repull/models/webhook_event_catalog.rb +1 -1
  438. data/lib/repull/models/webhook_event_catalog_domains_inner.rb +1 -1
  439. data/lib/repull/models/webhook_event_catalog_entry.rb +1 -1
  440. data/lib/repull/models/webhook_event_type.rb +6 -2
  441. data/lib/repull/models/webhook_list_response.rb +1 -1
  442. data/lib/repull/models/webhook_subscription.rb +1 -1
  443. data/lib/repull/version.rb +2 -2
  444. data/lib/repull.rb +153 -16
  445. data/openapi/v1.json +12620 -5281
  446. data/scripts/check-spec-freshness.py +399 -0
  447. data/scripts/regen.sh +32 -3
  448. metadata +155 -19
  449. data/lib/repull/api/sandbox_api.rb +0 -136
  450. data/lib/repull/models/sandbox_seed_result.rb +0 -278
  451. data/lib/repull/models/studio_generation.rb +0 -215
  452. data/lib/repull/models/studio_project.rb +0 -241
  453. data/spec/api/ai_api_spec.rb +0 -47
@@ -0,0 +1,264 @@
1
+ =begin
2
+ #Repull API
3
+
4
+ #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_live_YOUR_API_KEY ``` ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resetsAt` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | 50 | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
+
6
+ The version of the OpenAPI document: 1.0.0
7
+ Contact: ivan@vanio.ai
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.22.0
10
+
11
+ =end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ module Repull
17
+ # A proposed change to an existing Airbnb reservation. `confirmation_code` names the reservation; at least one of `check_in`, `check_out`, `number_of_guests`, `total_price` or `listing_id` must be sent with it, because an alteration that changes nothing is not something Airbnb can act on (it is refused with `422 invalid_params`). Unknown fields are refused rather than silently dropped. The older connector-native spellings (`start_date`, `end_date`, `total_price_override`, and an Airbnb guest-details object in place of `number_of_guests`) are still accepted for existing integrations; send the canonical names above in new code, and never a canonical field and its older spelling with different values.
18
+ class AirbnbAlterationCreateRequest < ApiModelBase
19
+ # Airbnb confirmation code of the reservation to alter. `GET /v1/channels/airbnb/reservations` lists them.
20
+ attr_accessor :confirmation_code
21
+
22
+ # New check-in date, `YYYY-MM-DD`.
23
+ attr_accessor :check_in
24
+
25
+ # New check-out date, `YYYY-MM-DD`. Must be after `check_in` when both are sent.
26
+ attr_accessor :check_out
27
+
28
+ # New guest count for the stay.
29
+ attr_accessor :number_of_guests
30
+
31
+ # New total for the whole stay, in the listing currency. Sent to Airbnb as the alteration's price override.
32
+ attr_accessor :total_price
33
+
34
+ # Move the reservation to this listing — a **listing transfer**. This is the **Repull** listing id (the `id` from `GET /v1/properties`), the same id every other Airbnb channel route takes; Repull verifies you own it, that it is active and connected to Airbnb, and translates it to the Airbnb listing id before sending it. Airbnb decides whether to honour the move.
35
+ attr_accessor :listing_id
36
+
37
+ # The transfer target as the **Airbnb** listing id, for callers who hold that instead of the Repull id. Prefer `listing_id`. Sending both is allowed only when they name the same listing.
38
+ attr_accessor :airbnb_listing_id
39
+
40
+ # Attribute mapping from ruby-style variable name to JSON key.
41
+ def self.attribute_map
42
+ {
43
+ :'confirmation_code' => :'confirmation_code',
44
+ :'check_in' => :'check_in',
45
+ :'check_out' => :'check_out',
46
+ :'number_of_guests' => :'number_of_guests',
47
+ :'total_price' => :'total_price',
48
+ :'listing_id' => :'listing_id',
49
+ :'airbnb_listing_id' => :'airbnb_listing_id'
50
+ }
51
+ end
52
+
53
+ # Returns attribute mapping this model knows about
54
+ def self.acceptable_attribute_map
55
+ attribute_map
56
+ end
57
+
58
+ # Returns all the JSON keys this model knows about
59
+ def self.acceptable_attributes
60
+ acceptable_attribute_map.values
61
+ end
62
+
63
+ # Attribute type mapping.
64
+ def self.openapi_types
65
+ {
66
+ :'confirmation_code' => :'String',
67
+ :'check_in' => :'Date',
68
+ :'check_out' => :'Date',
69
+ :'number_of_guests' => :'Integer',
70
+ :'total_price' => :'Float',
71
+ :'listing_id' => :'Integer',
72
+ :'airbnb_listing_id' => :'String'
73
+ }
74
+ end
75
+
76
+ # List of attributes with nullable: true
77
+ def self.openapi_nullable
78
+ Set.new([
79
+ ])
80
+ end
81
+
82
+ # Initializes the object
83
+ # @param [Hash] attributes Model attributes in the form of hash
84
+ def initialize(attributes = {})
85
+ if (!attributes.is_a?(Hash))
86
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Repull::AirbnbAlterationCreateRequest` initialize method"
87
+ end
88
+
89
+ # check to see if the attribute exists and convert string to symbol for hash key
90
+ acceptable_attribute_map = self.class.acceptable_attribute_map
91
+ attributes = attributes.each_with_object({}) { |(k, v), h|
92
+ if (!acceptable_attribute_map.key?(k.to_sym))
93
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Repull::AirbnbAlterationCreateRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
94
+ end
95
+ h[k.to_sym] = v
96
+ }
97
+
98
+ if attributes.key?(:'confirmation_code')
99
+ self.confirmation_code = attributes[:'confirmation_code']
100
+ else
101
+ self.confirmation_code = nil
102
+ end
103
+
104
+ if attributes.key?(:'check_in')
105
+ self.check_in = attributes[:'check_in']
106
+ end
107
+
108
+ if attributes.key?(:'check_out')
109
+ self.check_out = attributes[:'check_out']
110
+ end
111
+
112
+ if attributes.key?(:'number_of_guests')
113
+ self.number_of_guests = attributes[:'number_of_guests']
114
+ end
115
+
116
+ if attributes.key?(:'total_price')
117
+ self.total_price = attributes[:'total_price']
118
+ end
119
+
120
+ if attributes.key?(:'listing_id')
121
+ self.listing_id = attributes[:'listing_id']
122
+ end
123
+
124
+ if attributes.key?(:'airbnb_listing_id')
125
+ self.airbnb_listing_id = attributes[:'airbnb_listing_id']
126
+ end
127
+ end
128
+
129
+ # Show invalid properties with the reasons. Usually used together with valid?
130
+ # @return Array for valid properties with the reasons
131
+ def list_invalid_properties
132
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
133
+ invalid_properties = Array.new
134
+ if @confirmation_code.nil?
135
+ invalid_properties.push('invalid value for "confirmation_code", confirmation_code cannot be nil.')
136
+ end
137
+
138
+ if !@number_of_guests.nil? && @number_of_guests < 1
139
+ invalid_properties.push('invalid value for "number_of_guests", must be greater than or equal to 1.')
140
+ end
141
+
142
+ if !@total_price.nil? && @total_price < 0
143
+ invalid_properties.push('invalid value for "total_price", must be greater than or equal to 0.')
144
+ end
145
+
146
+ invalid_properties
147
+ end
148
+
149
+ # Check to see if the all the properties in the model are valid
150
+ # @return true if the model is valid
151
+ def valid?
152
+ warn '[DEPRECATED] the `valid?` method is obsolete'
153
+ return false if @confirmation_code.nil?
154
+ return false if !@number_of_guests.nil? && @number_of_guests < 1
155
+ return false if !@total_price.nil? && @total_price < 0
156
+ true
157
+ end
158
+
159
+ # Custom attribute writer method with validation
160
+ # @param [Object] confirmation_code Value to be assigned
161
+ def confirmation_code=(confirmation_code)
162
+ if confirmation_code.nil?
163
+ fail ArgumentError, 'confirmation_code cannot be nil'
164
+ end
165
+
166
+ @confirmation_code = confirmation_code
167
+ end
168
+
169
+ # Custom attribute writer method with validation
170
+ # @param [Object] number_of_guests Value to be assigned
171
+ def number_of_guests=(number_of_guests)
172
+ if number_of_guests.nil?
173
+ fail ArgumentError, 'number_of_guests cannot be nil'
174
+ end
175
+
176
+ if number_of_guests < 1
177
+ fail ArgumentError, 'invalid value for "number_of_guests", must be greater than or equal to 1.'
178
+ end
179
+
180
+ @number_of_guests = number_of_guests
181
+ end
182
+
183
+ # Custom attribute writer method with validation
184
+ # @param [Object] total_price Value to be assigned
185
+ def total_price=(total_price)
186
+ if total_price.nil?
187
+ fail ArgumentError, 'total_price cannot be nil'
188
+ end
189
+
190
+ if total_price < 0
191
+ fail ArgumentError, 'invalid value for "total_price", must be greater than or equal to 0.'
192
+ end
193
+
194
+ @total_price = total_price
195
+ end
196
+
197
+ # Checks equality by comparing each attribute.
198
+ # @param [Object] Object to be compared
199
+ def ==(o)
200
+ return true if self.equal?(o)
201
+ self.class == o.class &&
202
+ confirmation_code == o.confirmation_code &&
203
+ check_in == o.check_in &&
204
+ check_out == o.check_out &&
205
+ number_of_guests == o.number_of_guests &&
206
+ total_price == o.total_price &&
207
+ listing_id == o.listing_id &&
208
+ airbnb_listing_id == o.airbnb_listing_id
209
+ end
210
+
211
+ # @see the `==` method
212
+ # @param [Object] Object to be compared
213
+ def eql?(o)
214
+ self == o
215
+ end
216
+
217
+ # Calculates hash code according to all attributes.
218
+ # @return [Integer] Hash code
219
+ def hash
220
+ [confirmation_code, check_in, check_out, number_of_guests, total_price, listing_id, airbnb_listing_id].hash
221
+ end
222
+
223
+ # Builds the object from hash
224
+ # @param [Hash] attributes Model attributes in the form of hash
225
+ # @return [Object] Returns the model itself
226
+ def self.build_from_hash(attributes)
227
+ return nil unless attributes.is_a?(Hash)
228
+ attributes = attributes.transform_keys(&:to_sym)
229
+ transformed_hash = {}
230
+ openapi_types.each_pair do |key, type|
231
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
232
+ transformed_hash["#{key}"] = nil
233
+ elsif type =~ /\AArray<(.*)>/i
234
+ # check to ensure the input is an array given that the attribute
235
+ # is documented as an array but the input is not
236
+ if attributes[attribute_map[key]].is_a?(Array)
237
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
238
+ end
239
+ elsif !attributes[attribute_map[key]].nil?
240
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
241
+ end
242
+ end
243
+ new(transformed_hash)
244
+ end
245
+
246
+ # Returns the object in the form of hash
247
+ # @return [Hash] Returns the object in the form of hash
248
+ def to_hash
249
+ hash = {}
250
+ self.class.attribute_map.each_pair do |attr, param|
251
+ value = self.send(attr)
252
+ if value.nil?
253
+ is_nullable = self.class.openapi_nullable.include?(attr)
254
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
255
+ end
256
+
257
+ hash[param] = _to_hash(value)
258
+ end
259
+ hash
260
+ end
261
+
262
+ end
263
+
264
+ end
@@ -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
@@ -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
@@ -102,6 +102,10 @@ module Repull
102
102
  invalid_properties.push('invalid value for "type", type cannot be nil.')
103
103
  end
104
104
 
105
+ if !@operations.nil? && @operations.length < 1
106
+ invalid_properties.push('invalid value for "operations", number of items must be greater than or equal to 1.')
107
+ end
108
+
105
109
  invalid_properties
106
110
  end
107
111
 
@@ -110,6 +114,7 @@ module Repull
110
114
  def valid?
111
115
  warn '[DEPRECATED] the `valid?` method is obsolete'
112
116
  return false if @type.nil?
117
+ return false if !@operations.nil? && @operations.length < 1
113
118
  true
114
119
  end
115
120
 
@@ -123,6 +128,20 @@ module Repull
123
128
  @type = type
124
129
  end
125
130
 
131
+ # Custom attribute writer method with validation
132
+ # @param [Object] operations Value to be assigned
133
+ def operations=(operations)
134
+ if operations.nil?
135
+ fail ArgumentError, 'operations cannot be nil'
136
+ end
137
+
138
+ if operations.length < 1
139
+ fail ArgumentError, 'invalid value for "operations", number of items must be greater than or equal to 1.'
140
+ end
141
+
142
+ @operations = operations
143
+ end
144
+
126
145
  # Checks equality by comparing each attribute.
127
146
  # @param [Object] Object to be compared
128
147
  def ==(o)
@@ -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
@@ -14,27 +14,30 @@ require 'date'
14
14
  require 'time'
15
15
 
16
16
  module Repull
17
- # One calendar operation. Supply either `start_date` + `end_date` OR a `dates` array. Every restriction here is forwarded verbatim to Airbnb's batch calendar API.
17
+ # One calendar operation, applied to every date it names. Supply either `dates` OR a `start_date` + `end_date` pair (not both). Unknown fields are refused with `422 invalid_params` rather than dropped, so a misspelling such as `price` (the field is `daily_price`) can never look like a successful write.
18
18
  class AirbnbCalendarOperation < ApiModelBase
19
- # Inclusive range start (pair with `end_date`).
19
+ # Inclusive range start, YYYY-MM-DD. Send together with `end_date`.
20
20
  attr_accessor :start_date
21
21
 
22
- # Inclusive range end (pair with `start_date`).
22
+ # Inclusive range end, YYYY-MM-DD, on or after `start_date`.
23
23
  attr_accessor :end_date
24
24
 
25
- # Explicit date or `start:end` range strings, as an alternative to `start_date`/`end_date`.
25
+ # Dates as `YYYY-MM-DD`, or inclusive ranges as `YYYY-MM-DD:YYYY-MM-DD` an alternative to `start_date`/`end_date`.
26
26
  attr_accessor :dates
27
27
 
28
- # Nightly price override.
28
+ # Nightly price override, in the listing currency.
29
29
  attr_accessor :daily_price
30
30
 
31
31
  # Stop-sell is expressed here: `unavailable` blocks the date(s); `available` re-opens; `default` reverts to rule-based availability.
32
32
  attr_accessor :availability
33
33
 
34
+ # Why a blocked date is blocked. Airbnb requires it whenever `availability` is `unavailable`; when you leave it out, Repull sends **`BLOCKED_BY_HOST`**. Use `OUTSIDE_RESERVATION` for a date held by a booking made on another channel.
35
+ attr_accessor :busy_subtype
36
+
34
37
  # Minimum length of stay for the date(s).
35
38
  attr_accessor :min_nights
36
39
 
37
- # Maximum length of stay for the date(s).
40
+ # Maximum length of stay for the date(s); no lower than `min_nights`.
38
41
  attr_accessor :max_nights
39
42
 
40
43
  # Closed-to-arrival — no check-ins on the affected date(s).
@@ -53,6 +56,7 @@ module Repull
53
56
  :'dates' => :'dates',
54
57
  :'daily_price' => :'daily_price',
55
58
  :'availability' => :'availability',
59
+ :'busy_subtype' => :'busy_subtype',
56
60
  :'min_nights' => :'min_nights',
57
61
  :'max_nights' => :'max_nights',
58
62
  :'closed_to_arrival' => :'closed_to_arrival',
@@ -79,6 +83,7 @@ module Repull
79
83
  :'dates' => :'Array<String>',
80
84
  :'daily_price' => :'Float',
81
85
  :'availability' => :'String',
86
+ :'busy_subtype' => :'String',
82
87
  :'min_nights' => :'Integer',
83
88
  :'max_nights' => :'Integer',
84
89
  :'closed_to_arrival' => :'Boolean',
@@ -95,6 +100,7 @@ module Repull
95
100
  :'dates',
96
101
  :'daily_price',
97
102
  :'availability',
103
+ :'busy_subtype',
98
104
  :'min_nights',
99
105
  :'max_nights',
100
106
  :'closed_to_arrival',
@@ -141,6 +147,10 @@ module Repull
141
147
  self.availability = attributes[:'availability']
142
148
  end
143
149
 
150
+ if attributes.key?(:'busy_subtype')
151
+ self.busy_subtype = attributes[:'busy_subtype']
152
+ end
153
+
144
154
  if attributes.key?(:'min_nights')
145
155
  self.min_nights = attributes[:'min_nights']
146
156
  end
@@ -167,6 +177,30 @@ module Repull
167
177
  def list_invalid_properties
168
178
  warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
169
179
  invalid_properties = Array.new
180
+ if !@dates.nil? && @dates.length < 1
181
+ invalid_properties.push('invalid value for "dates", number of items must be greater than or equal to 1.')
182
+ end
183
+
184
+ if !@daily_price.nil? && @daily_price < 0
185
+ invalid_properties.push('invalid value for "daily_price", must be greater than or equal to 0.')
186
+ end
187
+
188
+ if !@min_nights.nil? && @min_nights > 1125
189
+ invalid_properties.push('invalid value for "min_nights", must be smaller than or equal to 1125.')
190
+ end
191
+
192
+ if !@min_nights.nil? && @min_nights < 1
193
+ invalid_properties.push('invalid value for "min_nights", must be greater than or equal to 1.')
194
+ end
195
+
196
+ if !@max_nights.nil? && @max_nights > 1125
197
+ invalid_properties.push('invalid value for "max_nights", must be smaller than or equal to 1125.')
198
+ end
199
+
200
+ if !@max_nights.nil? && @max_nights < 1
201
+ invalid_properties.push('invalid value for "max_nights", must be greater than or equal to 1.')
202
+ end
203
+
170
204
  invalid_properties
171
205
  end
172
206
 
@@ -174,9 +208,63 @@ module Repull
174
208
  # @return true if the model is valid
175
209
  def valid?
176
210
  warn '[DEPRECATED] the `valid?` method is obsolete'
211
+ return false if !@dates.nil? && @dates.length < 1
212
+ return false if !@daily_price.nil? && @daily_price < 0
213
+ return false if !@min_nights.nil? && @min_nights > 1125
214
+ return false if !@min_nights.nil? && @min_nights < 1
215
+ return false if !@max_nights.nil? && @max_nights > 1125
216
+ return false if !@max_nights.nil? && @max_nights < 1
177
217
  true
178
218
  end
179
219
 
220
+ # Custom attribute writer method with validation
221
+ # @param [Object] dates Value to be assigned
222
+ def dates=(dates)
223
+ if !dates.nil? && dates.length < 1
224
+ fail ArgumentError, 'invalid value for "dates", number of items must be greater than or equal to 1.'
225
+ end
226
+
227
+ @dates = dates
228
+ end
229
+
230
+ # Custom attribute writer method with validation
231
+ # @param [Object] daily_price Value to be assigned
232
+ def daily_price=(daily_price)
233
+ if !daily_price.nil? && daily_price < 0
234
+ fail ArgumentError, 'invalid value for "daily_price", must be greater than or equal to 0.'
235
+ end
236
+
237
+ @daily_price = daily_price
238
+ end
239
+
240
+ # Custom attribute writer method with validation
241
+ # @param [Object] min_nights Value to be assigned
242
+ def min_nights=(min_nights)
243
+ if !min_nights.nil? && min_nights > 1125
244
+ fail ArgumentError, 'invalid value for "min_nights", must be smaller than or equal to 1125.'
245
+ end
246
+
247
+ if !min_nights.nil? && min_nights < 1
248
+ fail ArgumentError, 'invalid value for "min_nights", must be greater than or equal to 1.'
249
+ end
250
+
251
+ @min_nights = min_nights
252
+ end
253
+
254
+ # Custom attribute writer method with validation
255
+ # @param [Object] max_nights Value to be assigned
256
+ def max_nights=(max_nights)
257
+ if !max_nights.nil? && max_nights > 1125
258
+ fail ArgumentError, 'invalid value for "max_nights", must be smaller than or equal to 1125.'
259
+ end
260
+
261
+ if !max_nights.nil? && max_nights < 1
262
+ fail ArgumentError, 'invalid value for "max_nights", must be greater than or equal to 1.'
263
+ end
264
+
265
+ @max_nights = max_nights
266
+ end
267
+
180
268
  # Checks equality by comparing each attribute.
181
269
  # @param [Object] Object to be compared
182
270
  def ==(o)
@@ -187,6 +275,7 @@ module Repull
187
275
  dates == o.dates &&
188
276
  daily_price == o.daily_price &&
189
277
  availability == o.availability &&
278
+ busy_subtype == o.busy_subtype &&
190
279
  min_nights == o.min_nights &&
191
280
  max_nights == o.max_nights &&
192
281
  closed_to_arrival == o.closed_to_arrival &&
@@ -203,7 +292,7 @@ module Repull
203
292
  # Calculates hash code according to all attributes.
204
293
  # @return [Integer] Hash code
205
294
  def hash
206
- [start_date, end_date, dates, daily_price, availability, min_nights, max_nights, closed_to_arrival, closed_to_departure, notes].hash
295
+ [start_date, end_date, dates, daily_price, availability, busy_subtype, min_nights, max_nights, closed_to_arrival, closed_to_departure, notes].hash
207
296
  end
208
297
 
209
298
  # Builds the object from hash