repull 0.2.26 → 0.2.28

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 (666) hide show
  1. checksums.yaml +4 -4
  2. data/lib/repull/api/airbnb_api.rb +39 -24
  3. data/lib/repull/api/atlas_api.rb +1 -1
  4. data/lib/repull/api/availability_api.rb +1 -1
  5. data/lib/repull/api/billing_api.rb +1 -1
  6. data/lib/repull/api/booking_com_api.rb +10 -3
  7. data/lib/repull/api/connect_api.rb +205 -5
  8. data/lib/repull/api/connections_api.rb +1 -1
  9. data/lib/repull/api/conversations_api.rb +1 -1
  10. data/lib/repull/api/guests_api.rb +1 -1
  11. data/lib/repull/api/health_api.rb +1 -1
  12. data/lib/repull/api/kv_api.rb +1 -1
  13. data/lib/repull/api/listings_api.rb +3 -3
  14. data/lib/repull/api/markets_api.rb +1 -1
  15. data/lib/repull/api/migrate_api.rb +1 -1
  16. data/lib/repull/api/plumguide_api.rb +1 -1
  17. data/lib/repull/api/pricing_api.rb +1 -1
  18. data/lib/repull/api/properties_api.rb +3 -3
  19. data/lib/repull/api/quotes_api.rb +1 -1
  20. data/lib/repull/api/reservations_api.rb +94 -7
  21. data/lib/repull/api/reviews_api.rb +1 -1
  22. data/lib/repull/api/schema_api.rb +1 -1
  23. data/lib/repull/api/system_api.rb +1 -1
  24. data/lib/repull/api/vrbo_api.rb +10 -3
  25. data/lib/repull/api/webhooks_api.rb +1 -1
  26. data/lib/repull/api_client.rb +1 -1
  27. data/lib/repull/api_error.rb +1 -1
  28. data/lib/repull/api_model_base.rb +1 -1
  29. data/lib/repull/configuration.rb +1 -1
  30. data/lib/repull/models/accept_reservation_request200_response.rb +1 -1
  31. data/lib/repull/models/account_created_event.rb +1 -1
  32. data/lib/repull/models/account_created_payload.rb +1 -1
  33. data/lib/repull/models/account_disconnected_event.rb +1 -1
  34. data/lib/repull/models/account_disconnected_payload.rb +1 -1
  35. data/lib/repull/models/acknowledge_booking_reservations_request.rb +1 -1
  36. data/lib/repull/models/ai_operation.rb +1 -1
  37. data/lib/repull/models/ai_operation_completed_event.rb +1 -1
  38. data/lib/repull/models/ai_operation_completed_payload.rb +1 -1
  39. data/lib/repull/models/ai_operation_failed_event.rb +1 -1
  40. data/lib/repull/models/ai_operation_failed_payload.rb +1 -1
  41. data/lib/repull/models/ai_operation_failed_payload_error.rb +1 -1
  42. data/lib/repull/models/airbnb_account_freshness.rb +1 -1
  43. data/lib/repull/models/airbnb_alteration.rb +1 -1
  44. data/lib/repull/models/airbnb_alteration_create_request.rb +1 -1
  45. data/lib/repull/models/airbnb_amenity.rb +1 -1
  46. data/lib/repull/models/airbnb_availability_write_request.rb +1 -1
  47. data/lib/repull/models/airbnb_calendar_operation.rb +1 -1
  48. data/lib/repull/models/airbnb_connection.rb +1 -1
  49. data/lib/repull/models/airbnb_connection_accessibility_amenities_inner.rb +1 -1
  50. data/lib/repull/models/airbnb_connection_amenities_inner.rb +1 -1
  51. data/lib/repull/models/airbnb_connection_host.rb +1 -1
  52. data/lib/repull/models/airbnb_connection_response.rb +1 -1
  53. data/lib/repull/models/airbnb_connection_summary.rb +1 -1
  54. data/lib/repull/models/airbnb_content_write_response.rb +1 -1
  55. data/lib/repull/models/airbnb_data_freshness.rb +1 -1
  56. data/lib/repull/models/airbnb_description_write_request.rb +1 -1
  57. data/lib/repull/models/airbnb_description_write_request_description.rb +1 -1
  58. data/lib/repull/models/airbnb_host_review_submit.rb +1 -1
  59. data/lib/repull/models/airbnb_host_review_submit_category_ratings_inner.rb +1 -1
  60. data/lib/repull/models/airbnb_listing.rb +14 -3
  61. data/lib/repull/models/airbnb_listing_action200_response.rb +1 -1
  62. data/lib/repull/models/airbnb_listing_action200_response_one_of.rb +1 -1
  63. data/lib/repull/models/airbnb_listing_action200_response_one_of1.rb +1 -1
  64. data/lib/repull/models/airbnb_listing_action_request.rb +1 -1
  65. data/lib/repull/models/airbnb_listing_details_response.rb +1 -1
  66. data/lib/repull/models/airbnb_listing_details_write_request.rb +110 -6
  67. data/lib/repull/models/airbnb_listing_details_write_request_check_in_option.rb +2 -2
  68. data/lib/repull/models/airbnb_listing_details_write_request_quiet_hours_inner.rb +1 -1
  69. data/lib/repull/models/airbnb_listing_lifecycle_response.rb +1 -1
  70. data/lib/repull/models/airbnb_listing_list_response.rb +1 -1
  71. data/lib/repull/models/airbnb_permits_response.rb +1 -1
  72. data/lib/repull/models/airbnb_permits_response_cached_inner.rb +1 -1
  73. data/lib/repull/models/airbnb_permits_write_request.rb +1 -1
  74. data/lib/repull/models/airbnb_permits_write_request_permits_inner.rb +3 -3
  75. data/lib/repull/models/airbnb_photo_position.rb +1 -1
  76. data/lib/repull/models/airbnb_pricing_write_request.rb +31 -3
  77. data/lib/repull/models/airbnb_pricing_write_request_fees_inner.rb +291 -0
  78. data/lib/repull/models/airbnb_pricing_write_request_records_inner.rb +1 -1
  79. data/lib/repull/models/airbnb_publish_result.rb +1 -1
  80. data/lib/repull/models/airbnb_reservation.rb +1 -1
  81. data/lib/repull/models/airbnb_reservation_action200_response.rb +1 -1
  82. data/lib/repull/models/airbnb_reservation_action_request.rb +1 -1
  83. data/lib/repull/models/airbnb_reservation_list_response.rb +1 -1
  84. data/lib/repull/models/airbnb_review.rb +1 -1
  85. data/lib/repull/models/airbnb_review_list_response.rb +1 -1
  86. data/lib/repull/models/airbnb_safety_disclosure.rb +1 -1
  87. data/lib/repull/models/airbnb_safety_disclosures_response.rb +1 -1
  88. data/lib/repull/models/airbnb_safety_disclosures_write_request.rb +1 -1
  89. data/lib/repull/models/airbnb_thread.rb +1 -1
  90. data/lib/repull/models/airbnb_thread_list_response.rb +1 -1
  91. data/lib/repull/models/airbnb_transaction.rb +1 -1
  92. data/lib/repull/models/airbnb_transaction_fees.rb +1 -1
  93. data/lib/repull/models/airbnb_transaction_payout.rb +1 -1
  94. data/lib/repull/models/alteration_change.rb +1 -1
  95. data/lib/repull/models/alteration_webhook_object.rb +1 -1
  96. data/lib/repull/models/apply_connection_mappings200_response.rb +1 -1
  97. data/lib/repull/models/apply_connection_mappings200_response_results_inner.rb +1 -1
  98. data/lib/repull/models/apply_connection_mappings_request.rb +1 -1
  99. data/lib/repull/models/apply_connection_mappings_request_mappings_inner.rb +1 -1
  100. data/lib/repull/models/auto_map_connection_units200_response.rb +1 -1
  101. data/lib/repull/models/auto_map_connection_units_request.rb +1 -1
  102. data/lib/repull/models/availability_batch_write_request.rb +1 -1
  103. data/lib/repull/models/availability_write_request.rb +1 -1
  104. data/lib/repull/models/availability_write_result.rb +1 -1
  105. data/lib/repull/models/availability_write_result_synced.rb +1 -1
  106. data/lib/repull/models/availability_write_settings.rb +1 -1
  107. data/lib/repull/models/booking_availability_state_response.rb +1 -1
  108. data/lib/repull/models/booking_availability_update.rb +1 -1
  109. data/lib/repull/models/booking_availability_update_date_range.rb +1 -1
  110. data/lib/repull/models/booking_availability_update_request.rb +1 -1
  111. data/lib/repull/models/booking_availability_update_request_property_id.rb +1 -1
  112. data/lib/repull/models/booking_availability_update_request_updates_inner.rb +1 -1
  113. data/lib/repull/models/booking_connect_listing_option.rb +1 -1
  114. data/lib/repull/models/booking_connect_room.rb +1 -1
  115. data/lib/repull/models/booking_connect_rooms_response.rb +1 -1
  116. data/lib/repull/models/booking_conversation.rb +1 -1
  117. data/lib/repull/models/booking_pricing_rate_update.rb +1 -1
  118. data/lib/repull/models/booking_pricing_rate_update_date_range.rb +1 -1
  119. data/lib/repull/models/booking_pricing_rate_update_restrictions.rb +1 -1
  120. data/lib/repull/models/booking_pricing_response.rb +1 -1
  121. data/lib/repull/models/booking_pricing_update_request.rb +1 -1
  122. data/lib/repull/models/booking_pricing_update_response.rb +1 -1
  123. data/lib/repull/models/booking_property.rb +1 -1
  124. data/lib/repull/models/booking_property_action_request.rb +1 -1
  125. data/lib/repull/models/booking_property_action_response.rb +1 -1
  126. data/lib/repull/models/booking_property_listings_inner.rb +58 -2
  127. data/lib/repull/models/booking_publish_result.rb +1 -1
  128. data/lib/repull/models/booking_publish_section_error.rb +1 -1
  129. data/lib/repull/models/booking_rate_write_occupancy.rb +1 -1
  130. data/lib/repull/models/booking_rate_write_price_half.rb +1 -1
  131. data/lib/repull/models/booking_rate_write_restriction_half.rb +1 -1
  132. data/lib/repull/models/booking_rate_write_verification.rb +1 -1
  133. data/lib/repull/models/booking_rate_write_verification_row.rb +1 -1
  134. data/lib/repull/models/booking_reservation.rb +1 -1
  135. data/lib/repull/models/booking_reservation_room.rb +1 -1
  136. data/lib/repull/models/booking_restriction_request_row.rb +1 -1
  137. data/lib/repull/models/booking_restriction_verification.rb +1 -1
  138. data/lib/repull/models/booking_restriction_verification_row.rb +1 -1
  139. data/lib/repull/models/booking_restriction_verification_row_booking_value.rb +1 -1
  140. data/lib/repull/models/booking_restriction_verification_row_expected.rb +1 -1
  141. data/lib/repull/models/booking_room_mapping.rb +1 -1
  142. data/lib/repull/models/booking_rooms_rates_response.rb +1 -1
  143. data/lib/repull/models/booking_rooms_rates_response_rooms_inner.rb +1 -1
  144. data/lib/repull/models/booking_rooms_rates_response_rooms_inner_rates_inner.rb +1 -1
  145. data/lib/repull/models/booking_setup_request.rb +1 -1
  146. data/lib/repull/models/booking_setup_request_legal_entity.rb +1 -1
  147. data/lib/repull/models/booking_upstream_failure.rb +1 -1
  148. data/lib/repull/models/booking_verify_hotel_request.rb +1 -1
  149. data/lib/repull/models/booking_verify_hotel_response.rb +1 -1
  150. data/lib/repull/models/bulk_pricing_failure.rb +1 -1
  151. data/lib/repull/models/bulk_pricing_item.rb +1 -1
  152. data/lib/repull/models/bulk_pricing_request.rb +1 -1
  153. data/lib/repull/models/bulk_pricing_response.rb +1 -1
  154. data/lib/repull/models/calendar_day.rb +1 -1
  155. data/lib/repull/models/calendar_response.rb +1 -1
  156. data/lib/repull/models/calendar_updated_event.rb +1 -1
  157. data/lib/repull/models/calendar_updated_payload.rb +1 -1
  158. data/lib/repull/models/calendar_updated_payload_range.rb +1 -1
  159. data/lib/repull/models/cancel_reservation200_response.rb +2 -2
  160. data/lib/repull/models/cancel_reservation_request.rb +1 -1
  161. data/lib/repull/models/channel_market_state_item.rb +1 -1
  162. data/lib/repull/models/check_migration_cutover200_response.rb +1 -1
  163. data/lib/repull/models/check_migration_cutover_request.rb +1 -1
  164. data/lib/repull/models/check_migration_cutover_request_reservations_inner.rb +1 -1
  165. data/lib/repull/models/clear_kv200_response.rb +1 -1
  166. data/lib/repull/models/connect_host.rb +1 -1
  167. data/lib/repull/models/connect_provider.rb +1 -1
  168. data/lib/repull/models/connect_provider_list_response.rb +1 -1
  169. data/lib/repull/models/connect_session.rb +1 -1
  170. data/lib/repull/models/connect_session_completed_event.rb +1 -1
  171. data/lib/repull/models/connect_session_completed_payload.rb +1 -1
  172. data/lib/repull/models/connect_status.rb +36 -5
  173. data/lib/repull/models/connect_status_accounts_inner.rb +1 -1
  174. data/lib/repull/models/connect_status_capabilities.rb +148 -0
  175. data/lib/repull/models/connection.rb +29 -6
  176. data/lib/repull/models/connection_action.rb +188 -0
  177. data/lib/repull/models/connection_list_response.rb +1 -1
  178. data/lib/repull/models/conversation.rb +1 -1
  179. data/lib/repull/models/conversation_capabilities.rb +1 -1
  180. data/lib/repull/models/conversation_detail.rb +1 -1
  181. data/lib/repull/models/conversation_guest.rb +1 -1
  182. data/lib/repull/models/conversation_guest_contact.rb +1 -1
  183. data/lib/repull/models/conversation_host.rb +1 -1
  184. data/lib/repull/models/conversation_list_response.rb +1 -1
  185. data/lib/repull/models/conversation_message_attachment.rb +1 -1
  186. data/lib/repull/models/create_airbnb_listing_room_request.rb +1 -1
  187. data/lib/repull/models/create_airbnb_offer_request.rb +1 -1
  188. data/lib/repull/models/create_airbnb_offer_request_guest_details.rb +1 -1
  189. data/lib/repull/models/create_billing_checkout_request.rb +1 -1
  190. data/lib/repull/models/create_booking_webhook_request.rb +1 -1
  191. data/lib/repull/models/create_connect_session_request.rb +40 -2
  192. data/lib/repull/models/create_connect_session_request_copy.rb +1 -1
  193. data/lib/repull/models/create_connect_session_request_workspace.rb +1 -1
  194. data/lib/repull/models/create_connection_request.rb +40 -2
  195. data/lib/repull/models/create_conversation_special_offer201_response.rb +1 -1
  196. data/lib/repull/models/create_conversation_special_offer201_response_fees_inner.rb +1 -1
  197. data/lib/repull/models/create_conversation_special_offer201_response_guests.rb +1 -1
  198. data/lib/repull/models/create_conversation_special_offer201_response_lines_inner.rb +1 -1
  199. data/lib/repull/models/create_conversation_special_offer_request.rb +1 -1
  200. data/lib/repull/models/create_conversation_special_offer_request_fees_inner.rb +1 -1
  201. data/lib/repull/models/create_conversation_special_offer_request_guests.rb +1 -1
  202. data/lib/repull/models/create_webhook_request.rb +1 -1
  203. data/lib/repull/models/custom_schema.rb +1 -1
  204. data/lib/repull/models/custom_schema_create.rb +1 -1
  205. data/lib/repull/models/custom_schema_create_response.rb +1 -1
  206. data/lib/repull/models/custom_schema_delete_response.rb +1 -1
  207. data/lib/repull/models/custom_schema_list_response.rb +1 -1
  208. data/lib/repull/models/custom_schema_summary.rb +1 -1
  209. data/lib/repull/models/custom_schema_update.rb +1 -1
  210. data/lib/repull/models/decline_reservation_request_request.rb +1 -1
  211. data/lib/repull/models/delete_airbnb_listing_photo200_response.rb +1 -1
  212. data/lib/repull/models/delete_airbnb_listing_room200_response.rb +1 -1
  213. data/lib/repull/models/delete_connection200_response.rb +1 -1
  214. data/lib/repull/models/delete_kv200_response.rb +1 -1
  215. data/lib/repull/models/delete_migration200_response.rb +1 -1
  216. data/lib/repull/models/delete_migration200_response_data.rb +1 -1
  217. data/lib/repull/models/error.rb +1 -1
  218. data/lib/repull/models/error_error.rb +14 -2
  219. data/lib/repull/models/{cancel_reservation200_response_pms.rb → error_error_listings_inner.rb} +37 -31
  220. data/lib/repull/models/error_error_support.rb +1 -1
  221. data/lib/repull/models/get_airbnb_alteration200_response.rb +1 -1
  222. data/lib/repull/models/get_airbnb_booking_settings200_response.rb +1 -1
  223. data/lib/repull/models/get_airbnb_booking_settings200_response_data.rb +1 -1
  224. data/lib/repull/models/get_airbnb_booking_settings200_response_data_advance_notice.rb +1 -1
  225. data/lib/repull/models/get_airbnb_booking_settings200_response_data_booking_window.rb +1 -1
  226. data/lib/repull/models/get_airbnb_booking_settings200_response_data_cancellation.rb +1 -1
  227. data/lib/repull/models/get_airbnb_booking_settings200_response_data_cancellation_non_refundable.rb +1 -1
  228. data/lib/repull/models/get_airbnb_booking_settings200_response_data_check_in.rb +1 -1
  229. data/lib/repull/models/get_airbnb_booking_settings200_response_data_check_in_start.rb +1 -1
  230. data/lib/repull/models/get_airbnb_booking_settings200_response_data_check_out.rb +1 -1
  231. data/lib/repull/models/get_airbnb_booking_settings200_response_data_instant_book.rb +1 -1
  232. data/lib/repull/models/get_airbnb_booking_settings200_response_data_preparation_time.rb +1 -1
  233. data/lib/repull/models/get_airbnb_checkin_guide200_response.rb +1 -1
  234. data/lib/repull/models/get_airbnb_listing_details200_response.rb +1 -1
  235. data/lib/repull/models/get_airbnb_listing_quality200_response.rb +1 -1
  236. data/lib/repull/models/get_airbnb_listing_settings200_response.rb +1 -1
  237. data/lib/repull/models/get_airbnb_offer200_response.rb +1 -1
  238. data/lib/repull/models/get_airbnb_thread200_response.rb +1 -1
  239. data/lib/repull/models/get_booking_extranet_login_config200_response.rb +1 -1
  240. data/lib/repull/models/get_booking_extranet_login_status200_response.rb +3 -2
  241. data/lib/repull/models/get_channel_health200_response.rb +1 -1
  242. data/lib/repull/models/get_channel_health200_response_vrbo.rb +1 -1
  243. data/lib/repull/models/get_connect_write_policy200_response.rb +1 -1
  244. data/lib/repull/models/get_health200_response.rb +1 -1
  245. data/lib/repull/models/get_listing_calendar_sync200_response.rb +1 -1
  246. data/lib/repull/models/get_listing_calendar_sync200_response_channels_inner.rb +1 -1
  247. data/lib/repull/models/get_listing_calendar_sync200_response_channels_inner_problems_inner.rb +1 -1
  248. data/lib/repull/models/get_listing_calendar_sync200_response_channels_inner_queue.rb +1 -1
  249. data/lib/repull/models/get_listing_calendar_sync200_response_channels_inner_queue_last_push.rb +1 -1
  250. data/lib/repull/models/get_listing_markups200_response.rb +1 -1
  251. data/lib/repull/models/get_listing_markups200_response_airbnb_inner.rb +1 -1
  252. data/lib/repull/models/get_listing_markups200_response_booking_inner.rb +1 -1
  253. data/lib/repull/models/get_migration200_response.rb +1 -1
  254. data/lib/repull/models/get_migration_channel_map200_response.rb +1 -1
  255. data/lib/repull/models/get_migration_report200_response.rb +1 -1
  256. data/lib/repull/models/get_usage_logs200_response.rb +1 -1
  257. data/lib/repull/models/get_usage_logs200_response_data_inner.rb +1 -1
  258. data/lib/repull/models/get_usage_logs200_response_pagination.rb +1 -1
  259. data/lib/repull/models/get_usage_summary200_response.rb +1 -1
  260. data/lib/repull/models/get_usage_summary200_response_breakdown_inner.rb +1 -1
  261. data/lib/repull/models/get_usage_summary200_response_limits.rb +1 -1
  262. data/lib/repull/models/get_usage_summary200_response_remaining.rb +1 -1
  263. data/lib/repull/models/get_usage_summary200_response_status_distribution.rb +1 -1
  264. data/lib/repull/models/get_usage_summary200_response_timeline_inner.rb +1 -1
  265. data/lib/repull/models/get_usage_summary200_response_totals.rb +1 -1
  266. data/lib/repull/models/get_usage_summary200_response_used.rb +1 -1
  267. data/lib/repull/models/get_usage_tier200_response.rb +1 -1
  268. data/lib/repull/models/get_usage_tier200_response_limits.rb +1 -1
  269. data/lib/repull/models/get_usage_tier200_response_remaining.rb +1 -1
  270. data/lib/repull/models/get_usage_tier200_response_used.rb +1 -1
  271. data/lib/repull/models/guest.rb +1 -1
  272. data/lib/repull/models/guest_contact.rb +1 -1
  273. data/lib/repull/models/guest_create_request.rb +1 -1
  274. data/lib/repull/models/guest_create_response.rb +1 -1
  275. data/lib/repull/models/guest_create_response_contacts_inner.rb +1 -1
  276. data/lib/repull/models/guest_flag.rb +1 -1
  277. data/lib/repull/models/guest_list_response.rb +1 -1
  278. data/lib/repull/models/guest_note.rb +1 -1
  279. data/lib/repull/models/guest_profile.rb +1 -1
  280. data/lib/repull/models/guest_reservations_summary.rb +1 -1
  281. data/lib/repull/models/inquiry_created_event.rb +1 -1
  282. data/lib/repull/models/inquiry_created_payload.rb +1 -1
  283. data/lib/repull/models/inquiry_updated_event.rb +1 -1
  284. data/lib/repull/models/inquiry_updated_payload.rb +1 -1
  285. data/lib/repull/models/inquiry_webhook_object.rb +1 -1
  286. data/lib/repull/models/inquiry_webhook_object_expected_payout.rb +1 -1
  287. data/lib/repull/models/inquiry_webhook_object_guests.rb +1 -1
  288. data/lib/repull/models/invite_booking_extranet_user200_response.rb +1 -1
  289. data/lib/repull/models/invite_booking_extranet_user_request.rb +1 -1
  290. data/lib/repull/models/list_airbnb_alterations200_response.rb +1 -1
  291. data/lib/repull/models/list_airbnb_listing_amenities200_response.rb +1 -1
  292. data/lib/repull/models/list_airbnb_listing_amenities200_response_data.rb +1 -1
  293. data/lib/repull/models/list_airbnb_listing_permits200_response.rb +1 -1
  294. data/lib/repull/models/list_airbnb_listing_safety_disclosures200_response.rb +1 -1
  295. data/lib/repull/models/list_airbnb_thread_messages200_response.rb +1 -1
  296. data/lib/repull/models/list_airbnb_thread_messages200_response_data_inner.rb +1 -1
  297. data/lib/repull/models/list_airbnb_thread_messages200_response_pagination.rb +1 -1
  298. data/lib/repull/models/list_airbnb_transactions200_response.rb +1 -1
  299. data/lib/repull/models/list_booking_reservations200_response.rb +1 -1
  300. data/lib/repull/models/list_connection_units200_response.rb +1 -1
  301. data/lib/repull/models/list_connection_units200_response_listing_options_inner.rb +1 -1
  302. data/lib/repull/models/list_connection_units200_response_units_inner.rb +1 -1
  303. data/lib/repull/models/list_inquiries200_response.rb +1 -1
  304. data/lib/repull/models/list_inquiries200_response_data_inner.rb +1 -1
  305. data/lib/repull/models/list_inquiries200_response_data_inner_expected_payout.rb +1 -1
  306. data/lib/repull/models/list_inquiries200_response_data_inner_guests.rb +1 -1
  307. data/lib/repull/models/list_kv200_response.rb +1 -1
  308. data/lib/repull/models/list_kv200_response_data_inner.rb +1 -1
  309. data/lib/repull/models/list_kv200_response_pagination.rb +1 -1
  310. data/lib/repull/models/list_listing_units200_response.rb +3 -2
  311. data/lib/repull/models/list_listing_units200_response_data_inner.rb +1 -1
  312. data/lib/repull/models/list_migrations200_response.rb +1 -1
  313. data/lib/repull/models/listing.rb +24 -3
  314. data/lib/repull/models/listing_active_request.rb +1 -1
  315. data/lib/repull/models/listing_active_response.rb +1 -1
  316. data/lib/repull/models/listing_address.rb +1 -1
  317. data/lib/repull/models/listing_address_readiness.rb +1 -1
  318. data/lib/repull/models/listing_amenity.rb +1 -1
  319. data/lib/repull/models/listing_capabilities.rb +148 -0
  320. data/lib/repull/models/listing_channel.rb +1 -1
  321. data/lib/repull/models/listing_comp.rb +1 -1
  322. data/lib/repull/models/listing_comp_nightly.rb +1 -1
  323. data/lib/repull/models/listing_comp_ratings.rb +1 -1
  324. data/lib/repull/models/listing_comps_response.rb +1 -1
  325. data/lib/repull/models/listing_content.rb +1 -1
  326. data/lib/repull/models/listing_content_update_request.rb +1 -1
  327. data/lib/repull/models/listing_content_update_request_address.rb +1 -1
  328. data/lib/repull/models/listing_content_update_request_amenities.rb +1 -1
  329. data/lib/repull/models/listing_content_update_request_amenities_one_of_inner.rb +1 -1
  330. data/lib/repull/models/listing_content_update_request_checkout_tasks_inner.rb +1 -1
  331. data/lib/repull/models/listing_content_update_request_details.rb +1 -1
  332. data/lib/repull/models/listing_content_update_request_occupancy.rb +1 -1
  333. data/lib/repull/models/listing_content_update_request_photos_inner.rb +1 -1
  334. data/lib/repull/models/listing_content_update_request_photos_inner_one_of.rb +1 -1
  335. data/lib/repull/models/listing_content_update_request_policies.rb +1 -1
  336. data/lib/repull/models/listing_content_update_request_pricing.rb +1 -1
  337. data/lib/repull/models/listing_content_update_request_rooms_inner.rb +1 -1
  338. data/lib/repull/models/listing_content_update_request_rooms_inner_beds_inner.rb +1 -1
  339. data/lib/repull/models/listing_content_update_response.rb +1 -1
  340. data/lib/repull/models/listing_create_request.rb +1 -1
  341. data/lib/repull/models/listing_create_response.rb +1 -1
  342. data/lib/repull/models/listing_created_event.rb +1 -1
  343. data/lib/repull/models/listing_created_payload.rb +1 -1
  344. data/lib/repull/models/listing_created_payload_address.rb +1 -1
  345. data/lib/repull/models/listing_deleted_event.rb +1 -1
  346. data/lib/repull/models/listing_deleted_payload.rb +1 -1
  347. data/lib/repull/models/listing_details.rb +1 -1
  348. data/lib/repull/models/listing_generate_content_request.rb +1 -1
  349. data/lib/repull/models/listing_generate_content_response.rb +1 -1
  350. data/lib/repull/models/listing_list_response.rb +1 -1
  351. data/lib/repull/models/listing_market_state_request.rb +1 -1
  352. data/lib/repull/models/listing_market_state_response.rb +1 -1
  353. data/lib/repull/models/listing_photo.rb +1 -1
  354. data/lib/repull/models/listing_photo_delete_request.rb +1 -1
  355. data/lib/repull/models/listing_photo_delete_response.rb +1 -1
  356. data/lib/repull/models/listing_photo_upload_url_request.rb +1 -1
  357. data/lib/repull/models/listing_photo_upload_url_response.rb +1 -1
  358. data/lib/repull/models/listing_photos_response.rb +1 -1
  359. data/lib/repull/models/listing_pricing_apply_request.rb +1 -1
  360. data/lib/repull/models/listing_pricing_apply_response.rb +1 -1
  361. data/lib/repull/models/listing_pricing_history_entry.rb +1 -1
  362. data/lib/repull/models/listing_pricing_history_response.rb +1 -1
  363. data/lib/repull/models/listing_pricing_recommendation.rb +1 -1
  364. data/lib/repull/models/listing_pricing_response.rb +1 -1
  365. data/lib/repull/models/listing_pricing_response_comp_summary.rb +1 -1
  366. data/lib/repull/models/listing_pricing_response_date_range.rb +1 -1
  367. data/lib/repull/models/listing_pricing_response_listing.rb +1 -1
  368. data/lib/repull/models/listing_pricing_strategy.rb +1 -1
  369. data/lib/repull/models/listing_pricing_strategy_input.rb +1 -1
  370. data/lib/repull/models/listing_publish_airbnb_request.rb +1 -1
  371. data/lib/repull/models/listing_publish_airbnb_response.rb +1 -1
  372. data/lib/repull/models/listing_publish_booking_request.rb +1 -1
  373. data/lib/repull/models/listing_publish_booking_response.rb +1 -1
  374. data/lib/repull/models/listing_publish_status_channel.rb +1 -1
  375. data/lib/repull/models/listing_publish_status_connection.rb +1 -1
  376. data/lib/repull/models/listing_publish_status_response.rb +1 -1
  377. data/lib/repull/models/listing_pull_airbnb_request.rb +1 -1
  378. data/lib/repull/models/listing_pull_response.rb +1 -1
  379. data/lib/repull/models/listing_quality_tier.rb +1 -1
  380. data/lib/repull/models/listing_reactivated_event.rb +1 -1
  381. data/lib/repull/models/listing_segment.rb +1 -1
  382. data/lib/repull/models/listing_segment_recommendation.rb +1 -1
  383. data/lib/repull/models/listing_segments_response.rb +1 -1
  384. data/lib/repull/models/listing_segments_response_scope.rb +1 -1
  385. data/lib/repull/models/listing_status_batch_request.rb +1 -1
  386. data/lib/repull/models/listing_status_batch_response.rb +1 -1
  387. data/lib/repull/models/listing_suspended_event.rb +1 -1
  388. data/lib/repull/models/listing_suspension_payload.rb +1 -1
  389. data/lib/repull/models/listing_units_inner.rb +1 -1
  390. data/lib/repull/models/listing_updated_event.rb +1 -1
  391. data/lib/repull/models/listing_updated_payload.rb +1 -1
  392. data/lib/repull/models/listing_webhook_object.rb +1 -1
  393. data/lib/repull/models/listing_webhook_object_address.rb +1 -1
  394. data/lib/repull/models/listing_webhook_object_channels_inner.rb +1 -1
  395. data/lib/repull/models/map_airbnb_listing_request.rb +1 -1
  396. data/lib/repull/models/map_airbnb_listing_response.rb +1 -1
  397. data/lib/repull/models/map_booking_room_request.rb +1 -1
  398. data/lib/repull/models/map_booking_room_response.rb +1 -1
  399. data/lib/repull/models/map_connect_booking_rooms_request.rb +1 -1
  400. data/lib/repull/models/map_connect_booking_rooms_response.rb +1 -1
  401. data/lib/repull/models/market_browse_category.rb +1 -1
  402. data/lib/repull/models/market_browse_entry.rb +1 -1
  403. data/lib/repull/models/market_browse_featured.rb +1 -1
  404. data/lib/repull/models/market_browse_response.rb +1 -1
  405. data/lib/repull/models/market_calendar_day.rb +1 -1
  406. data/lib/repull/models/market_calendar_day_events_inner.rb +1 -1
  407. data/lib/repull/models/market_calendar_response.rb +1 -1
  408. data/lib/repull/models/market_detail_response.rb +1 -1
  409. data/lib/repull/models/market_detail_response_price_distribution_inner.rb +1 -1
  410. data/lib/repull/models/market_detail_response_property_type_mix_inner.rb +1 -1
  411. data/lib/repull/models/market_detail_response_supply_trend_inner.rb +1 -1
  412. data/lib/repull/models/market_detail_response_top_comps.rb +1 -1
  413. data/lib/repull/models/market_event.rb +1 -1
  414. data/lib/repull/models/market_my_listing.rb +1 -1
  415. data/lib/repull/models/market_summary.rb +1 -1
  416. data/lib/repull/models/market_top_comp.rb +1 -1
  417. data/lib/repull/models/markets_overview_response.rb +1 -1
  418. data/lib/repull/models/markets_overview_response_browse.rb +1 -1
  419. data/lib/repull/models/markets_overview_response_subscriptions.rb +1 -1
  420. data/lib/repull/models/markets_overview_response_totals.rb +1 -1
  421. data/lib/repull/models/message.rb +1 -1
  422. data/lib/repull/models/message_list_response.rb +1 -1
  423. data/lib/repull/models/migration.rb +1 -1
  424. data/lib/repull/models/migration_channel_map.rb +1 -1
  425. data/lib/repull/models/migration_channel_map_listings_inner.rb +1 -1
  426. data/lib/repull/models/migration_channel_map_listings_inner_airbnb.rb +1 -1
  427. data/lib/repull/models/migration_channel_map_listings_inner_booking.rb +1 -1
  428. data/lib/repull/models/migration_channel_map_sources_inner.rb +1 -1
  429. data/lib/repull/models/migration_completed_event.rb +1 -1
  430. data/lib/repull/models/migration_connections_inner.rb +1 -1
  431. data/lib/repull/models/migration_counts.rb +1 -1
  432. data/lib/repull/models/migration_cutover_check.rb +1 -1
  433. data/lib/repull/models/migration_cutover_check_mismatched_inner.rb +1 -1
  434. data/lib/repull/models/migration_failed_event.rb +1 -1
  435. data/lib/repull/models/migration_import_payload.rb +1 -1
  436. data/lib/repull/models/migration_import_payload_results_inner.rb +1 -1
  437. data/lib/repull/models/migration_import_run.rb +1 -1
  438. data/lib/repull/models/migration_import_run_results_inner.rb +1 -1
  439. data/lib/repull/models/migration_report.rb +1 -1
  440. data/lib/repull/models/migration_report_issues_inner.rb +1 -1
  441. data/lib/repull/models/migration_reservation_ref.rb +1 -1
  442. data/lib/repull/models/pagination.rb +1 -1
  443. data/lib/repull/models/payment_completed_event.rb +1 -1
  444. data/lib/repull/models/payment_completed_payload.rb +1 -1
  445. data/lib/repull/models/payment_refunded_event.rb +1 -1
  446. data/lib/repull/models/payment_refunded_payload.rb +1 -1
  447. data/lib/repull/models/payment_webhook_object.rb +1 -1
  448. data/lib/repull/models/payout_completed_event.rb +1 -1
  449. data/lib/repull/models/payout_completed_payload.rb +1 -1
  450. data/lib/repull/models/plan_notice.rb +1 -1
  451. data/lib/repull/models/plumguide_listing.rb +1 -1
  452. data/lib/repull/models/plumguide_listing_list_response.rb +1 -1
  453. data/lib/repull/models/pms_write_policy.rb +1 -1
  454. data/lib/repull/models/pms_write_policy_calendar.rb +1 -1
  455. data/lib/repull/models/pms_write_policy_reservations.rb +1 -1
  456. data/lib/repull/models/preapprove_conversation201_response.rb +1 -1
  457. data/lib/repull/models/preapprove_conversation_request.rb +1 -1
  458. data/lib/repull/models/preview_conversation_special_offer_request.rb +1 -1
  459. data/lib/repull/models/preview_conversation_special_offer_request_fees_inner.rb +1 -1
  460. data/lib/repull/models/preview_conversation_special_offer_request_guests.rb +1 -1
  461. data/lib/repull/models/property.rb +15 -4
  462. data/lib/repull/models/property_availability.rb +1 -1
  463. data/lib/repull/models/property_availability_coverage.rb +1 -1
  464. data/lib/repull/models/property_availability_day.rb +1 -1
  465. data/lib/repull/models/property_list_response.rb +1 -1
  466. data/lib/repull/models/publish_section_error.rb +1 -1
  467. data/lib/repull/models/quote.rb +1 -1
  468. data/lib/repull/models/quote_pricing.rb +1 -1
  469. data/lib/repull/models/recheck_booking_extranet_login200_response.rb +178 -0
  470. data/lib/repull/models/recheck_booking_extranet_login_request.rb +192 -0
  471. data/lib/repull/models/record_account.rb +1 -1
  472. data/lib/repull/models/reorder_airbnb_listing_photos200_response.rb +1 -1
  473. data/lib/repull/models/reorder_airbnb_listing_photos200_response_data.rb +1 -1
  474. data/lib/repull/models/reorder_airbnb_listing_photos_request.rb +1 -1
  475. data/lib/repull/models/replay_webhook_delivery_request.rb +1 -1
  476. data/lib/repull/models/reply_booking_review200_response.rb +1 -1
  477. data/lib/repull/models/reply_booking_review_request.rb +1 -1
  478. data/lib/repull/models/reply_to_review201_response.rb +1 -1
  479. data/lib/repull/models/reply_to_review_request.rb +1 -1
  480. data/lib/repull/models/repull_ping_event.rb +1 -1
  481. data/lib/repull/models/repull_ping_payload.rb +1 -1
  482. data/lib/repull/models/reservation.rb +1 -1
  483. data/lib/repull/models/reservation_alteration_created_event.rb +1 -1
  484. data/lib/repull/models/reservation_alteration_created_payload.rb +1 -1
  485. data/lib/repull/models/reservation_alteration_responded_event.rb +1 -1
  486. data/lib/repull/models/reservation_alteration_responded_payload.rb +1 -1
  487. data/lib/repull/models/reservation_cancelled_event.rb +1 -1
  488. data/lib/repull/models/reservation_cancelled_payload.rb +1 -1
  489. data/lib/repull/models/reservation_capabilities.rb +230 -0
  490. data/lib/repull/models/reservation_create_request.rb +173 -34
  491. data/lib/repull/models/reservation_create_response.rb +7 -7
  492. data/lib/repull/models/reservation_create_response_unit.rb +2 -2
  493. data/lib/repull/models/reservation_created_event.rb +1 -1
  494. data/lib/repull/models/reservation_created_payload.rb +1 -1
  495. data/lib/repull/models/reservation_financials.rb +1 -1
  496. data/lib/repull/models/reservation_guest_financials.rb +1 -1
  497. data/lib/repull/models/reservation_guest_input.rb +1 -1
  498. data/lib/repull/models/reservation_host_financials.rb +1 -1
  499. data/lib/repull/models/reservation_list_response.rb +1 -1
  500. data/lib/repull/models/reservation_message_received_event.rb +1 -1
  501. data/lib/repull/models/reservation_message_received_payload.rb +1 -1
  502. data/lib/repull/models/reservation_message_received_payload_from.rb +1 -1
  503. data/lib/repull/models/reservation_message_sent_event.rb +1 -1
  504. data/lib/repull/models/reservation_message_sent_payload.rb +1 -1
  505. data/lib/repull/models/reservation_message_sent_payload_from.rb +1 -1
  506. data/lib/repull/models/reservation_message_updated_event.rb +1 -1
  507. data/lib/repull/models/reservation_message_updated_payload.rb +1 -1
  508. data/lib/repull/models/reservation_message_updated_payload_from.rb +1 -1
  509. data/lib/repull/models/reservation_money_line.rb +1 -1
  510. data/lib/repull/models/reservation_occupancy.rb +1 -1
  511. data/lib/repull/models/{reservation_create_response_pms.rb → reservation_pms_outcome.rb} +39 -9
  512. data/lib/repull/models/reservation_pms_outcome_quote.rb +168 -0
  513. data/lib/repull/models/{cancel_reservation200_response_pms_errors_inner.rb → reservation_pms_section_error.rb} +17 -17
  514. data/lib/repull/models/reservation_primary_guest.rb +1 -1
  515. data/lib/repull/models/reservation_quote_request.rb +312 -0
  516. data/lib/repull/models/reservation_quote_response.rb +228 -0
  517. data/lib/repull/models/reservation_quote_response_breakdown.rb +175 -0
  518. data/lib/repull/models/reservation_request_created_event.rb +1 -1
  519. data/lib/repull/models/reservation_request_created_payload.rb +1 -1
  520. data/lib/repull/models/reservation_request_updated_event.rb +1 -1
  521. data/lib/repull/models/reservation_request_updated_payload.rb +1 -1
  522. data/lib/repull/models/reservation_unit.rb +1 -1
  523. data/lib/repull/models/reservation_update_request.rb +1 -1
  524. data/lib/repull/models/reservation_update_response.rb +17 -7
  525. data/lib/repull/models/reservation_updated_event.rb +1 -1
  526. data/lib/repull/models/reservation_updated_payload.rb +1 -1
  527. data/lib/repull/models/reservation_webhook_object.rb +1 -1
  528. data/lib/repull/models/respond_airbnb_review_request.rb +1 -1
  529. data/lib/repull/models/resume_connect400_response.rb +208 -0
  530. data/lib/repull/models/resume_connect500_response.rb +188 -0
  531. data/lib/repull/models/review.rb +1 -1
  532. data/lib/repull/models/review_category.rb +1 -1
  533. data/lib/repull/models/review_created_event.rb +1 -1
  534. data/lib/repull/models/review_created_payload.rb +1 -1
  535. data/lib/repull/models/review_list_response.rb +1 -1
  536. data/lib/repull/models/review_responded_event.rb +1 -1
  537. data/lib/repull/models/review_responded_payload.rb +1 -1
  538. data/lib/repull/models/review_response.rb +1 -1
  539. data/lib/repull/models/review_webhook_object.rb +1 -1
  540. data/lib/repull/models/rotate_webhook_secret200_response.rb +1 -1
  541. data/lib/repull/models/run_migration_import202_response.rb +1 -1
  542. data/lib/repull/models/run_migration_import202_response_data.rb +1 -1
  543. data/lib/repull/models/run_migration_import202_response_data_queued_inner.rb +1 -1
  544. data/lib/repull/models/run_migration_import_request.rb +1 -1
  545. data/lib/repull/models/search_connect_session_listing_options200_response.rb +1 -1
  546. data/lib/repull/models/search_connect_session_listing_options200_response_data_inner.rb +1 -1
  547. data/lib/repull/models/search_connection_listing_options200_response.rb +1 -1
  548. data/lib/repull/models/select_connect_provider_request.rb +1 -1
  549. data/lib/repull/models/select_provider_response.rb +1 -1
  550. data/lib/repull/models/send_airbnb_message201_response.rb +1 -1
  551. data/lib/repull/models/send_airbnb_message_request.rb +1 -1
  552. data/lib/repull/models/send_booking_message_request.rb +1 -1
  553. data/lib/repull/models/send_message_attachment.rb +1 -1
  554. data/lib/repull/models/send_message_part.rb +1 -1
  555. data/lib/repull/models/send_message_request.rb +1 -1
  556. data/lib/repull/models/send_message_response.rb +1 -1
  557. data/lib/repull/models/sent_attachment.rb +1 -1
  558. data/lib/repull/models/set_airbnb_listing_cover_photo200_response.rb +1 -1
  559. data/lib/repull/models/set_airbnb_listing_cover_photo200_response_data.rb +1 -1
  560. data/lib/repull/models/set_airbnb_listing_cover_photo_request.rb +1 -1
  561. data/lib/repull/models/set_kv_request.rb +1 -1
  562. data/lib/repull/models/set_listing_markup_request.rb +1 -1
  563. data/lib/repull/models/start_booking_extranet_login200_response.rb +1 -1
  564. data/lib/repull/models/start_booking_extranet_login_request.rb +1 -1
  565. data/lib/repull/models/submit_beds24_credentials200_response.rb +1 -1
  566. data/lib/repull/models/submit_beds24_credentials_request.rb +1 -1
  567. data/lib/repull/models/submit_bookingsync_credentials_request.rb +1 -1
  568. data/lib/repull/models/submit_cloudbeds_credentials200_response.rb +1 -1
  569. data/lib/repull/models/submit_cloudbeds_credentials200_response_account_info.rb +1 -1
  570. data/lib/repull/models/submit_cloudbeds_credentials200_response_webhooks.rb +1 -1
  571. data/lib/repull/models/submit_cloudbeds_credentials_request.rb +1 -1
  572. data/lib/repull/models/submit_cloudbeds_credentials_request_credentials.rb +1 -1
  573. data/lib/repull/models/submit_guest_review200_response.rb +1 -1
  574. data/lib/repull/models/submit_guesty_credentials_request.rb +1 -1
  575. data/lib/repull/models/submit_hospitable_credentials_request.rb +1 -1
  576. data/lib/repull/models/submit_hostaway_credentials_request.rb +1 -1
  577. data/lib/repull/models/submit_igms_credentials_request.rb +1 -1
  578. data/lib/repull/models/submit_lodgify_credentials_request.rb +1 -1
  579. data/lib/repull/models/submit_mews_credentials200_response.rb +1 -1
  580. data/lib/repull/models/submit_mews_credentials200_response_account_info.rb +1 -1
  581. data/lib/repull/models/submit_mews_credentials_request.rb +1 -1
  582. data/lib/repull/models/submit_mews_credentials_request_credentials.rb +1 -1
  583. data/lib/repull/models/submit_ownerrez_credentials_request.rb +1 -1
  584. data/lib/repull/models/submit_smoobu_credentials_request.rb +3 -6
  585. data/lib/repull/models/submit_smoobu_credentials_request_credentials.rb +193 -0
  586. data/lib/repull/models/submit_track_credentials200_response.rb +213 -0
  587. data/lib/repull/models/submit_track_credentials200_response_account_info.rb +222 -0
  588. data/lib/repull/models/submit_track_credentials200_response_first_sync.rb +157 -0
  589. data/lib/repull/models/submit_track_credentials_request.rb +184 -0
  590. data/lib/repull/models/submit_track_credentials_request_credentials.rb +332 -0
  591. data/lib/repull/models/submit_vrbo_credentials_request.rb +1 -1
  592. data/lib/repull/models/sync_airbnb_transactions200_response.rb +1 -1
  593. data/lib/repull/models/sync_airbnb_transactions200_response_accounts_inner.rb +1 -1
  594. data/lib/repull/models/sync_airbnb_transactions200_response_accounts_inner_error.rb +1 -1
  595. data/lib/repull/models/sync_airbnb_transactions_request.rb +1 -1
  596. data/lib/repull/models/test_webhook_request.rb +1 -1
  597. data/lib/repull/models/update_airbnb_booking_settings200_response.rb +1 -1
  598. data/lib/repull/models/update_airbnb_booking_settings200_response_data.rb +1 -1
  599. data/lib/repull/models/update_airbnb_booking_settings_request.rb +1 -1
  600. data/lib/repull/models/update_airbnb_booking_settings_request_advance_notice.rb +1 -1
  601. data/lib/repull/models/update_airbnb_booking_settings_request_booking_window.rb +1 -1
  602. data/lib/repull/models/update_airbnb_booking_settings_request_cancellation.rb +1 -1
  603. data/lib/repull/models/update_airbnb_booking_settings_request_cancellation_non_refundable.rb +1 -1
  604. data/lib/repull/models/update_airbnb_booking_settings_request_check_in.rb +1 -1
  605. data/lib/repull/models/update_airbnb_booking_settings_request_check_out.rb +1 -1
  606. data/lib/repull/models/update_airbnb_booking_settings_request_instant_book.rb +1 -1
  607. data/lib/repull/models/update_airbnb_booking_settings_request_preparation_time.rb +1 -1
  608. data/lib/repull/models/update_airbnb_checkin_guide200_response.rb +147 -0
  609. data/lib/repull/models/update_airbnb_checkin_guide200_response_data.rb +177 -0
  610. data/lib/repull/models/{airbnb_permits_write_request_permits_inner_answers_value.rb → update_airbnb_checkin_guide200_response_data_steps_inner.rb} +25 -44
  611. data/lib/repull/models/update_airbnb_checkin_guide_request.rb +186 -0
  612. data/lib/repull/models/update_airbnb_checkin_guide_request_steps_inner.rb +182 -0
  613. data/lib/repull/models/update_airbnb_listing_amenities200_response.rb +1 -1
  614. data/lib/repull/models/update_airbnb_listing_amenities200_response_data.rb +1 -1
  615. data/lib/repull/models/update_airbnb_listing_amenities_request.rb +1 -1
  616. data/lib/repull/models/update_airbnb_listing_amenities_request_accessibility_amenities_inner.rb +1 -1
  617. data/lib/repull/models/update_airbnb_listing_amenities_request_amenities_inner.rb +1 -1
  618. data/lib/repull/models/update_airbnb_listing_permits200_response.rb +1 -1
  619. data/lib/repull/models/update_airbnb_listing_photo200_response.rb +1 -1
  620. data/lib/repull/models/update_airbnb_listing_photo_request.rb +1 -1
  621. data/lib/repull/models/update_airbnb_listing_room200_response.rb +1 -1
  622. data/lib/repull/models/update_airbnb_listing_room_request.rb +1 -1
  623. data/lib/repull/models/update_airbnb_listing_room_request_beds_inner.rb +1 -1
  624. data/lib/repull/models/update_airbnb_listing_room_request_room_amenities_inner.rb +1 -1
  625. data/lib/repull/models/update_airbnb_listing_room_request_room_amenities_inner_value.rb +1 -1
  626. data/lib/repull/models/update_airbnb_listing_safety_disclosures200_response.rb +1 -1
  627. data/lib/repull/models/update_airbnb_message_request.rb +1 -1
  628. data/lib/repull/models/update_booking_charges_request.rb +1 -1
  629. data/lib/repull/models/update_booking_content_request.rb +1 -1
  630. data/lib/repull/models/update_booking_content_request_content_data_inner.rb +1 -1
  631. data/lib/repull/models/update_booking_content_request_photos_inner.rb +1 -1
  632. data/lib/repull/models/update_connect_write_policy_request.rb +1 -1
  633. data/lib/repull/models/update_connect_write_policy_request_calendar.rb +1 -1
  634. data/lib/repull/models/update_connect_write_policy_request_reservations.rb +1 -1
  635. data/lib/repull/models/update_listing_pricing_strategy200_response.rb +1 -1
  636. data/lib/repull/models/update_webhook_request.rb +1 -1
  637. data/lib/repull/models/upload_airbnb_listing_photos_request.rb +1 -1
  638. data/lib/repull/models/upload_airbnb_listing_photos_request_photos_inner.rb +1 -1
  639. data/lib/repull/models/upload_airbnb_listing_photos_request_photos_inner_listing_id.rb +1 -1
  640. data/lib/repull/models/usage_quota_warning_event.rb +1 -1
  641. data/lib/repull/models/usage_quota_warning_payload.rb +1 -1
  642. data/lib/repull/models/usage_quota_warning_payload_top_operation.rb +1 -1
  643. data/lib/repull/models/vrbo_import_status.rb +1 -1
  644. data/lib/repull/models/vrbo_listing.rb +1 -1
  645. data/lib/repull/models/vrbo_login200_response.rb +1 -1
  646. data/lib/repull/models/vrbo_login_request.rb +1 -1
  647. data/lib/repull/models/vrbo_reservation.rb +1 -1
  648. data/lib/repull/models/vrbo_reservation_list_response.rb +1 -1
  649. data/lib/repull/models/webhook_delivery.rb +1 -1
  650. data/lib/repull/models/webhook_delivery_detail.rb +1 -1
  651. data/lib/repull/models/webhook_delivery_list_response.rb +1 -1
  652. data/lib/repull/models/webhook_event.rb +1 -1
  653. data/lib/repull/models/webhook_event_account.rb +1 -1
  654. data/lib/repull/models/webhook_event_catalog.rb +1 -1
  655. data/lib/repull/models/webhook_event_catalog_domains_inner.rb +1 -1
  656. data/lib/repull/models/webhook_event_catalog_entry.rb +1 -1
  657. data/lib/repull/models/webhook_event_type.rb +1 -1
  658. data/lib/repull/models/webhook_list_response.rb +1 -1
  659. data/lib/repull/models/webhook_subscription.rb +1 -1
  660. data/lib/repull/models/withdraw_conversation_preapproval200_response.rb +1 -1
  661. data/lib/repull/models/withdraw_conversation_special_offer200_response.rb +1 -1
  662. data/lib/repull/version.rb +2 -2
  663. data/lib/repull.rb +28 -5
  664. data/openapi/v1.json +2254 -156
  665. data/scripts/regen.sh +1 -1
  666. metadata +29 -6
@@ -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_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`.
4
+ #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_live_YOUR_API_KEY ``` ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resetsAt` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | unlimited (10 included, then billed per listing) | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
5
 
6
6
  The version of the OpenAPI document: 1.0.0
7
7
 
@@ -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_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`.
4
+ #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_live_YOUR_API_KEY ``` ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resetsAt` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | unlimited (10 included, then billed per listing) | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
5
 
6
6
  The version of the OpenAPI document: 1.0.0
7
7
 
@@ -97,7 +97,7 @@ module Repull
97
97
  # @option opts [String] :cursor Opaque cursor returned in the previous response's `pagination.nextCursor`. Omit to fetch the first page.
98
98
  # @option opts [Integer] :offset First-class alias for cursor-based pagination. Mutually exclusive with `cursor` — passing both returns 422. Accepts integers in `[0, 10000]`; deeper walks must use `cursor` (constant per-page cost). The response always includes `pagination.nextCursor` so consumers can switch from offset → cursor mid-walk for deep pagination without re-keying. (default to 0)
99
99
  # @option opts [String] :q Case-insensitive substring search on name, street, or city.
100
- # @option opts [String] :status Filter by status. Default returns active only; pass `inactive` to invert or `all` to include both. Inactive properties carry identity fields only — `id`, `name`, `status`, `lifecycleStatus`, `channels` and `updatedAt` — never `address`, `city` or `currency`. (default to 'active')
100
+ # @option opts [String] :status Filter by status. Default returns active only; pass `inactive` to invert or `all` to include both. Inactive properties carry identity fields only — `id`, `name`, `city`, `status`, `inactiveReason` (`plan_limit`, `unlisted_on_airbnb` or `deactivated`), `lifecycleStatus`, `channels` and `updatedAt` — never `address` or `currency`. (default to 'active')
101
101
  # @option opts [String] :lifecycle_status Filter by lifecycle status (e.g. `live`, `draft`, `archived`). Pass `all` to disable the filter.
102
102
  # @option opts [String] :channel Filter to properties with an active link on the given OTA/channel (airbnb, booking, vrbo). Omit to include every channel. Each property also returns a `channels` array listing the OTAs it is published on.
103
103
  # @option opts [Time] :updated_since Incremental sync: return only records whose `updatedAt` is at or after this instant. This is the only filter on record **mutation** time — every `check_*` filter targets guest **stay** dates. **Accepted formats.** ISO 8601, with `Z` or a numeric offset — both work: - `2026-08-01T00:00:00Z` - `2026-08-01T00:00:00.123Z` - `2026-08-01T00:00:00+00:00` - `2026-08-01T02:30:00-07:00` (offset colon optional: `-0700`) - `2026-08-01T00:00` (seconds optional) - `2026-08-01T00:00:00` — no zone designator, interpreted as **UTC** - `2026-08-01` — date only, means midnight UTC Anything else returns 422 `invalid_params` naming the field; the value is never silently ignored. **Ordering changes when you pass this.** Results are ordered `updatedAt ASC, id ASC` (instead of the endpoint default) and the cursor keys on the same pair. That is required for correctness: under the default ordering a record amended mid-walk can move behind the cursor and never be emitted — which is exactly the event you are polling for. Ascending mutation time is monotonic with the cursor, so anything touched during a walk resurfaces later in it or on the next poll. **Cursors are not interchangeable between the two orderings.** Keep `updated_since` on every page of an incremental walk; replaying a cursor from the other ordering returns 422 rather than a page that silently skips rows. **Watermark.** The bound is inclusive (`updatedAt >= value`), so the last row of the final page is the watermark for the next poll — re-polling with it re-emits that row. Delivery is at-least-once; upsert by `id`.
@@ -116,7 +116,7 @@ module Repull
116
116
  # @option opts [String] :cursor Opaque cursor returned in the previous response's `pagination.nextCursor`. Omit to fetch the first page.
117
117
  # @option opts [Integer] :offset First-class alias for cursor-based pagination. Mutually exclusive with `cursor` — passing both returns 422. Accepts integers in `[0, 10000]`; deeper walks must use `cursor` (constant per-page cost). The response always includes `pagination.nextCursor` so consumers can switch from offset → cursor mid-walk for deep pagination without re-keying. (default to 0)
118
118
  # @option opts [String] :q Case-insensitive substring search on name, street, or city.
119
- # @option opts [String] :status Filter by status. Default returns active only; pass `inactive` to invert or `all` to include both. Inactive properties carry identity fields only — `id`, `name`, `status`, `lifecycleStatus`, `channels` and `updatedAt` — never `address`, `city` or `currency`. (default to 'active')
119
+ # @option opts [String] :status Filter by status. Default returns active only; pass `inactive` to invert or `all` to include both. Inactive properties carry identity fields only — `id`, `name`, `city`, `status`, `inactiveReason` (`plan_limit`, `unlisted_on_airbnb` or `deactivated`), `lifecycleStatus`, `channels` and `updatedAt` — never `address` or `currency`. (default to 'active')
120
120
  # @option opts [String] :lifecycle_status Filter by lifecycle status (e.g. `live`, `draft`, `archived`). Pass `all` to disable the filter.
121
121
  # @option opts [String] :channel Filter to properties with an active link on the given OTA/channel (airbnb, booking, vrbo). Omit to include every channel. Each property also returns a `channels` array listing the OTAs it is published on.
122
122
  # @option opts [Time] :updated_since Incremental sync: return only records whose `updatedAt` is at or after this instant. This is the only filter on record **mutation** time — every `check_*` filter targets guest **stay** dates. **Accepted formats.** ISO 8601, with `Z` or a numeric offset — both work: - `2026-08-01T00:00:00Z` - `2026-08-01T00:00:00.123Z` - `2026-08-01T00:00:00+00:00` - `2026-08-01T02:30:00-07:00` (offset colon optional: `-0700`) - `2026-08-01T00:00` (seconds optional) - `2026-08-01T00:00:00` — no zone designator, interpreted as **UTC** - `2026-08-01` — date only, means midnight UTC Anything else returns 422 `invalid_params` naming the field; the value is never silently ignored. **Ordering changes when you pass this.** Results are ordered `updatedAt ASC, id ASC` (instead of the endpoint default) and the cursor keys on the same pair. That is required for correctness: under the default ordering a record amended mid-walk can move behind the cursor and never be emitted — which is exactly the event you are polling for. Ascending mutation time is monotonic with the cursor, so anything touched during a walk resurfaces later in it or on the next poll. **Cursors are not interchangeable between the two orderings.** Keep `updated_since` on every page of an incremental walk; replaying a cursor from the other ordering returns 422 rather than a page that silently skips rows. **Watermark.** The bound is inclusive (`updatedAt >= value`), so the last row of the final page is the watermark for the next poll — re-polling with it re-emits that row. Delivery is at-least-once; upsert by `id`.
@@ -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_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`.
4
+ #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_live_YOUR_API_KEY ``` ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resetsAt` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | unlimited (10 included, then billed per listing) | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
5
 
6
6
  The version of the OpenAPI document: 1.0.0
7
7
 
@@ -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_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`.
4
+ #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_live_YOUR_API_KEY ``` ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resetsAt` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | unlimited (10 included, then billed per listing) | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
5
 
6
6
  The version of the OpenAPI document: 1.0.0
7
7
 
@@ -90,9 +90,11 @@ module Repull
90
90
  end
91
91
 
92
92
  # Cancel a reservation
93
- # Cancels a reservation where it lives. - **Mews or Cloudbeds** (hotel-model PMS): cancelled in the PMS, then read back, so Repull and the PMS agree. No cancellation fee is charged. - **Direct, website or owner bookings**: cancelled in Repull — the nights are released and `reservation.cancelled` fires. - **A channel booking** (Airbnb, Booking.com, VRBO) or a booking owned by another PMS: `409 reservation_owned_by_channel`. Cancel it there; the cancellation reaches Repull with the next sync. Cancelling an already-cancelled reservation is not an error: the response carries `alreadyCancelled: true`. Returns `403 listing_inactive` when the listing is inactive.
93
+ # Cancels a reservation where it lives. - **A booking managed in a connected PMS** (Mews, Cloudbeds, Hostaway, Guesty, Beds24, BookingSync, Lodgify, Smoobu, Hospitable, iGMS): cancelled in the PMS, then read back, so Repull and the PMS agree. No cancellation fee is charged. Lodgify *declines* the booking rather than deleting it. **OwnerRez's API cannot cancel** — `422 pms_write_unsupported`; cancel it in OwnerRez. `GET /v1/listings/{id}` → `capabilities.reservations.cancel` says which applies. - **Direct, website or owner bookings**: cancelled in Repull — the nights are released and `reservation.cancelled` fires. - **A channel booking** (Airbnb, Booking.com, VRBO), including one that came in through a PMS: `409 reservation_owned_by_channel`. Cancel it on the channel; the cancellation reaches Repull with the next sync. Cancelling an already-cancelled reservation is not an error: the response carries `alreadyCancelled: true`. PMS integrations other than Mews and Cloudbeds are verified against the vendor's API documentation only. `X-Account-Id` restricts the reservation to one connected account. Returns `403 listing_inactive` when the listing is inactive.
94
94
  # @param id [Integer] Reservation id.
95
95
  # @param [Hash] opts the optional parameters
96
+ # @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged `Idempotency-Status: cached` — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → `409 idempotency_key_in_use`. - Same key with a DIFFERENT payload → `422 idempotency_key_reused`. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status >= 500, `408`, `425` and `429`, and the refusals that happen before anything is done and tell you to fix something outside the request first — `connection_reauth_required`, `listing_inactive`, and the rate/daily limits. Every other answer, including a final refusal such as `422 airbnb_rejected`, is stored and replayed.
97
+ # @option opts [String] :x_account_id Restrict the request to one connected account (a Repull connection id, `GET /v1/connect` → `id`). A listing or reservation outside that account answers `404 not_found`. Omit it to act workspace-wide.
96
98
  # @option opts [CancelReservationRequest] :cancel_reservation_request
97
99
  # @return [CancelReservation200Response]
98
100
  def cancel_reservation(id, opts = {})
@@ -101,9 +103,11 @@ module Repull
101
103
  end
102
104
 
103
105
  # Cancel a reservation
104
- # Cancels a reservation where it lives. - **Mews or Cloudbeds** (hotel-model PMS): cancelled in the PMS, then read back, so Repull and the PMS agree. No cancellation fee is charged. - **Direct, website or owner bookings**: cancelled in Repull — the nights are released and `reservation.cancelled` fires. - **A channel booking** (Airbnb, Booking.com, VRBO) or a booking owned by another PMS: `409 reservation_owned_by_channel`. Cancel it there; the cancellation reaches Repull with the next sync. Cancelling an already-cancelled reservation is not an error: the response carries `alreadyCancelled: true`. Returns `403 listing_inactive` when the listing is inactive.
106
+ # Cancels a reservation where it lives. - **A booking managed in a connected PMS** (Mews, Cloudbeds, Hostaway, Guesty, Beds24, BookingSync, Lodgify, Smoobu, Hospitable, iGMS): cancelled in the PMS, then read back, so Repull and the PMS agree. No cancellation fee is charged. Lodgify *declines* the booking rather than deleting it. **OwnerRez's API cannot cancel** — `422 pms_write_unsupported`; cancel it in OwnerRez. `GET /v1/listings/{id}` → `capabilities.reservations.cancel` says which applies. - **Direct, website or owner bookings**: cancelled in Repull — the nights are released and `reservation.cancelled` fires. - **A channel booking** (Airbnb, Booking.com, VRBO), including one that came in through a PMS: `409 reservation_owned_by_channel`. Cancel it on the channel; the cancellation reaches Repull with the next sync. Cancelling an already-cancelled reservation is not an error: the response carries `alreadyCancelled: true`. PMS integrations other than Mews and Cloudbeds are verified against the vendor's API documentation only. `X-Account-Id` restricts the reservation to one connected account. Returns `403 listing_inactive` when the listing is inactive.
105
107
  # @param id [Integer] Reservation id.
106
108
  # @param [Hash] opts the optional parameters
109
+ # @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged `Idempotency-Status: cached` — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → `409 idempotency_key_in_use`. - Same key with a DIFFERENT payload → `422 idempotency_key_reused`. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status >= 500, `408`, `425` and `429`, and the refusals that happen before anything is done and tell you to fix something outside the request first — `connection_reauth_required`, `listing_inactive`, and the rate/daily limits. Every other answer, including a final refusal such as `422 airbnb_rejected`, is stored and replayed.
110
+ # @option opts [String] :x_account_id Restrict the request to one connected account (a Repull connection id, `GET /v1/connect` → `id`). A listing or reservation outside that account answers `404 not_found`. Omit it to act workspace-wide.
107
111
  # @option opts [CancelReservationRequest] :cancel_reservation_request
108
112
  # @return [Array<(CancelReservation200Response, Integer, Hash)>] CancelReservation200Response data, response status code and response headers
109
113
  def cancel_reservation_with_http_info(id, opts = {})
@@ -114,6 +118,10 @@ module Repull
114
118
  if @api_client.config.client_side_validation && id.nil?
115
119
  fail ArgumentError, "Missing the required parameter 'id' when calling ReservationsApi.cancel_reservation"
116
120
  end
121
+ if @api_client.config.client_side_validation && !opts[:'idempotency_key'].nil? && opts[:'idempotency_key'].to_s.length > 255
122
+ fail ArgumentError, 'invalid value for "opts[:"idempotency_key"]" when calling ReservationsApi.cancel_reservation, the character length must be smaller than or equal to 255.'
123
+ end
124
+
117
125
  # resource path
118
126
  local_var_path = '/v1/reservations/{id}/cancel'.sub('{id}', CGI.escape(id.to_s))
119
127
 
@@ -129,6 +137,8 @@ module Repull
129
137
  if !content_type.nil?
130
138
  header_params['Content-Type'] = content_type
131
139
  end
140
+ header_params[:'Idempotency-Key'] = opts[:'idempotency_key'] if !opts[:'idempotency_key'].nil?
141
+ header_params[:'X-Account-Id'] = opts[:'x_account_id'] if !opts[:'x_account_id'].nil?
132
142
 
133
143
  # form parameters
134
144
  form_params = opts[:form_params] || {}
@@ -160,10 +170,11 @@ module Repull
160
170
  end
161
171
 
162
172
  # Create a reservation
163
- # Creates a reservation and everything that hangs off one: the guest, the conversation thread, the dashboard item, the calendar block, and the `reservation.created` fan-out that issues the door code and starts the messaging automations. **Platform is restricted to `direct`, `website` and `owner`.** Reservations on Airbnb, Booking.com and Vrbo are owned by the channel and arrive through sync — creating one here would mint a local booking the channel has never heard of, which then fights the next sync. Create those on the channel. **Dates are validated** (`YYYY-MM-DD`, and `checkOut` must be after `checkIn`), and an unrecognised field is rejected by name rather than silently ignored. **This endpoint does not set the price.** There is no `totalPrice` field: the reservation pipeline derives the price breakdown from the property's own rates and overwrites anything supplied, so accepting a total would be taking a value and discarding it. A reservation created here is priced by that engine (`0` when the property has no rates for the range). `currency` IS honoured. Quote a stay with `GET /v1/quotes` before booking if you need the figure up front. **Availability is NOT checked.** This creates the reservation you asked for even if the dates overlap an existing booking. Call `GET /v1/availability/{propertyId}` first if that matters. Send `Idempotency-Key` — a network timeout here is exactly the case it exists for: without it, a retry books the guest twice. 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.
173
+ # Creates a reservation — in the listing's PMS when it has one, otherwise as a direct booking in Repull. ### Where the booking is made - **A listing managed in a connected PMS** (Mews, Cloudbeds, Hostaway, Guesty, Beds24, BookingSync, Lodgify, Smoobu, Hospitable, iGMS, OwnerRez, Track): the booking is created **in the PMS first**, then recorded in Repull from the PMS's own record, so the next sync lands on the same confirmation code and nothing is duplicated. A booking is **never** created only in Repull for such a listing — the PMS would keep selling the dates. What the PMS cannot do is refused (`422 pms_write_unsupported`), never faked. The PMS checks availability: taken dates answer `409 pms_unavailable`. - **Any other listing**: a direct booking made in Repull, with everything that hangs off one — the guest, the conversation, the calendar block and the `reservation.created` fan-out that issues the door code and starts the messaging automations. Priced by the listing's own rates; **availability is NOT checked** (call `GET /v1/availability/{propertyId}` first if that matters). `GET /v1/listings/{id}` → `capabilities.reservations` says which applies to a listing and exactly what it supports (`create`, `modify`, `cancel`, `quote`, `customPrice`, plus `notes`). ### Fields by listing kind | Field | PMS listing | Direct-booking listing | |---|---|---| | `listingId`, `checkIn`, `checkOut`, `guest`, `guestCount`, `adults`, `children` | ✓ | ✓ | | `status` | `confirmed` (default) or `tentative` | ✓ | | `totalPrice` | ✓ where `capabilities.reservations.customPrice`; otherwise the PMS prices the stay | `422 unsupported_field` (priced from the listing's rates) | | `notes`, `unitId`, `sendConfirmationEmail` | ✓ | `422 unsupported_field` | | `checkInTime`, `checkOutTime`, `currency`, `guestId` | `422 unsupported_field` (the PMS's own settings apply) | ✓ | | `platform` | `direct` or `website` (`owner` → `422 pms_write_unsupported`; block owner stays in the PMS) | `direct`, `website` or `owner` | A field a listing cannot take is refused by name, never silently dropped. `platform` never accepts `airbnb` / `booking` / `vrbo`: those reservations are owned by the channel and arrive through sync. ### Per-PMS limits | PMS | create | change | cancel | quote | `totalPrice` | Limits | |---|---|---|---|---|---|---| | Mews | ✓ | ✓ | ✓ | – | ✓ | — | | Cloudbeds | ✓ | ✓ | ✓ | – | – | Books at the rate plan's price; group bookings supported. | | Hostaway | ✓ | ✓ | ✓ | ✓ | ✓ | Direct-channel bookings only; a specific unit is refused; a date change keeps the booked total. | | Guesty | ✓ | ✓ | ✓ | ✓ | ✓ | Cancels direct and Vrbo bookings; other channel bookings are cancelled on the channel. | | Beds24 | ✓ | ✓ | ✓ | ✓ | ✓ | Needs the `write:bookings` scope; a multi-room property needs `unitId`. | | BookingSync | ✓ | ✓ | ✓ | ✓ | ✓ | Needs `bookings_write`; fees and taxes are not itemized; no guest email. | | Lodgify | ✓ | ✓ | ✓ (declines) | ✓ | ✓ | Cancel declines the booking; single-room bookings. | | Smoobu | ✓ | ✓ (no dates) | ✓ | ✓ | ✓ | Dates cannot be changed through Smoobu's API — cancel and rebook, or change them in Smoobu. | | Hospitable | ✓ | ✓ | ✓ | ✓ (Direct plan) | ✓ | Manual reservations only; needs `reservation:write`; adds no fees or taxes. | | iGMS | ✓ | ✓ | ✓ | – | ✓ (required) | iGMS direct bookings only; a price is required; no tentative holds. | | OwnerRez | ✓ | ✓ | – | ✓ | – | No cancel through OwnerRez's API; priced by the property's own rates; needs the `full` scope. | | Track | ✓ | ✓ | ✓ | ✓ | ✓ | Track decides Hold vs Confirmed from the property's channel mode; a set price on a Channel Key needs \"Allow Custom Pricing\"; a unit change needs `moveReasonId` on the connection; a date change re-prices at Track's current rates. | Every PMS except Cloudbeds refuses group bookings, and every vacation-rental PMS refuses to change or cancel a booking that came from a channel (Airbnb, Booking.com, Vrbo…) — that is done on the channel. **Verification.** Mews and Cloudbeds were run end to end on their vendors' sandboxes. Every other PMS is **verified against the vendor's API documentation only** — no live account has been written to yet. `capabilities.reservations.verifiedAgainst` says which. ### Idempotency **Send `Idempotency-Key`.** A network timeout here is exactly the case it exists for. The key is also sent to the PMS as the booking's reference, so even a retry that reaches the PMS again finds the booking instead of making a second one (`409 pms_duplicate` with `existing`, or the existing booking returned). A completed answer is replayed with `Idempotency-Status: cached` and the PMS is not called again. `502 pms_error` (the PMS could not be reached) is NOT stored — retry with the same key. `502 reservation_created_in_pms_only` IS stored, unlike every other 5xx: the booking exists in the PMS and arrives with the next sync, so a retry replays that answer rather than booking twice. ### Partial success When the PMS created the booking but a follow-up step did not apply (for example the notes, or a tentative state), the response is still `201`, with `pms.partial: true` and the steps in `pms.failedSections`. The booking exists — do not create it again. `X-Account-Id` restricts the listing to one connected account. Returns `403 listing_inactive` when the listing is inactive.
164
174
  # @param reservation_create_request [ReservationCreateRequest]
165
175
  # @param [Hash] opts the optional parameters
166
176
  # @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged &#x60;Idempotency-Status: cached&#x60; — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → &#x60;409 idempotency_key_in_use&#x60;. - Same key with a DIFFERENT payload → &#x60;422 idempotency_key_reused&#x60;. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status &gt;&#x3D; 500, &#x60;408&#x60;, &#x60;425&#x60; and &#x60;429&#x60;, and the refusals that happen before anything is done and tell you to fix something outside the request first — &#x60;connection_reauth_required&#x60;, &#x60;listing_inactive&#x60;, and the rate/daily limits. Every other answer, including a final refusal such as &#x60;422 airbnb_rejected&#x60;, is stored and replayed.
177
+ # @option opts [String] :x_account_id Restrict the request to one connected account (a Repull connection id, &#x60;GET /v1/connect&#x60; → &#x60;id&#x60;). A listing or reservation outside that account answers &#x60;404 not_found&#x60;. Omit it to act workspace-wide.
167
178
  # @return [ReservationCreateResponse]
168
179
  def create_reservation(reservation_create_request, opts = {})
169
180
  data, _status_code, _headers = create_reservation_with_http_info(reservation_create_request, opts)
@@ -171,10 +182,11 @@ module Repull
171
182
  end
172
183
 
173
184
  # Create a reservation
174
- # Creates a reservation and everything that hangs off one: the guest, the conversation thread, the dashboard item, the calendar block, and the &#x60;reservation.created&#x60; fan-out that issues the door code and starts the messaging automations. **Platform is restricted to &#x60;direct&#x60;, &#x60;website&#x60; and &#x60;owner&#x60;.** Reservations on Airbnb, Booking.com and Vrbo are owned by the channel and arrive through sync — creating one here would mint a local booking the channel has never heard of, which then fights the next sync. Create those on the channel. **Dates are validated** (&#x60;YYYY-MM-DD&#x60;, and &#x60;checkOut&#x60; must be after &#x60;checkIn&#x60;), and an unrecognised field is rejected by name rather than silently ignored. **This endpoint does not set the price.** There is no &#x60;totalPrice&#x60; field: the reservation pipeline derives the price breakdown from the property&#39;s own rates and overwrites anything supplied, so accepting a total would be taking a value and discarding it. A reservation created here is priced by that engine (&#x60;0&#x60; when the property has no rates for the range). &#x60;currency&#x60; IS honoured. Quote a stay with &#x60;GET /v1/quotes&#x60; before booking if you need the figure up front. **Availability is NOT checked.** This creates the reservation you asked for even if the dates overlap an existing booking. Call &#x60;GET /v1/availability/{propertyId}&#x60; first if that matters. Send &#x60;Idempotency-Key&#x60; — a network timeout here is exactly the case it exists for: without it, a retry books the guest twice. 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.
185
+ # Creates a reservation — in the listing&#39;s PMS when it has one, otherwise as a direct booking in Repull. ### Where the booking is made - **A listing managed in a connected PMS** (Mews, Cloudbeds, Hostaway, Guesty, Beds24, BookingSync, Lodgify, Smoobu, Hospitable, iGMS, OwnerRez, Track): the booking is created **in the PMS first**, then recorded in Repull from the PMS&#39;s own record, so the next sync lands on the same confirmation code and nothing is duplicated. A booking is **never** created only in Repull for such a listing — the PMS would keep selling the dates. What the PMS cannot do is refused (&#x60;422 pms_write_unsupported&#x60;), never faked. The PMS checks availability: taken dates answer &#x60;409 pms_unavailable&#x60;. - **Any other listing**: a direct booking made in Repull, with everything that hangs off one — the guest, the conversation, the calendar block and the &#x60;reservation.created&#x60; fan-out that issues the door code and starts the messaging automations. Priced by the listing&#39;s own rates; **availability is NOT checked** (call &#x60;GET /v1/availability/{propertyId}&#x60; first if that matters). &#x60;GET /v1/listings/{id}&#x60; → &#x60;capabilities.reservations&#x60; says which applies to a listing and exactly what it supports (&#x60;create&#x60;, &#x60;modify&#x60;, &#x60;cancel&#x60;, &#x60;quote&#x60;, &#x60;customPrice&#x60;, plus &#x60;notes&#x60;). ### Fields by listing kind | Field | PMS listing | Direct-booking listing | |---|---|---| | &#x60;listingId&#x60;, &#x60;checkIn&#x60;, &#x60;checkOut&#x60;, &#x60;guest&#x60;, &#x60;guestCount&#x60;, &#x60;adults&#x60;, &#x60;children&#x60; | ✓ | ✓ | | &#x60;status&#x60; | &#x60;confirmed&#x60; (default) or &#x60;tentative&#x60; | ✓ | | &#x60;totalPrice&#x60; | ✓ where &#x60;capabilities.reservations.customPrice&#x60;; otherwise the PMS prices the stay | &#x60;422 unsupported_field&#x60; (priced from the listing&#39;s rates) | | &#x60;notes&#x60;, &#x60;unitId&#x60;, &#x60;sendConfirmationEmail&#x60; | ✓ | &#x60;422 unsupported_field&#x60; | | &#x60;checkInTime&#x60;, &#x60;checkOutTime&#x60;, &#x60;currency&#x60;, &#x60;guestId&#x60; | &#x60;422 unsupported_field&#x60; (the PMS&#39;s own settings apply) | ✓ | | &#x60;platform&#x60; | &#x60;direct&#x60; or &#x60;website&#x60; (&#x60;owner&#x60; → &#x60;422 pms_write_unsupported&#x60;; block owner stays in the PMS) | &#x60;direct&#x60;, &#x60;website&#x60; or &#x60;owner&#x60; | A field a listing cannot take is refused by name, never silently dropped. &#x60;platform&#x60; never accepts &#x60;airbnb&#x60; / &#x60;booking&#x60; / &#x60;vrbo&#x60;: those reservations are owned by the channel and arrive through sync. ### Per-PMS limits | PMS | create | change | cancel | quote | &#x60;totalPrice&#x60; | Limits | |---|---|---|---|---|---|---| | Mews | ✓ | ✓ | ✓ | – | ✓ | — | | Cloudbeds | ✓ | ✓ | ✓ | – | – | Books at the rate plan&#39;s price; group bookings supported. | | Hostaway | ✓ | ✓ | ✓ | ✓ | ✓ | Direct-channel bookings only; a specific unit is refused; a date change keeps the booked total. | | Guesty | ✓ | ✓ | ✓ | ✓ | ✓ | Cancels direct and Vrbo bookings; other channel bookings are cancelled on the channel. | | Beds24 | ✓ | ✓ | ✓ | ✓ | ✓ | Needs the &#x60;write:bookings&#x60; scope; a multi-room property needs &#x60;unitId&#x60;. | | BookingSync | ✓ | ✓ | ✓ | ✓ | ✓ | Needs &#x60;bookings_write&#x60;; fees and taxes are not itemized; no guest email. | | Lodgify | ✓ | ✓ | ✓ (declines) | ✓ | ✓ | Cancel declines the booking; single-room bookings. | | Smoobu | ✓ | ✓ (no dates) | ✓ | ✓ | ✓ | Dates cannot be changed through Smoobu&#39;s API — cancel and rebook, or change them in Smoobu. | | Hospitable | ✓ | ✓ | ✓ | ✓ (Direct plan) | ✓ | Manual reservations only; needs &#x60;reservation:write&#x60;; adds no fees or taxes. | | iGMS | ✓ | ✓ | ✓ | – | ✓ (required) | iGMS direct bookings only; a price is required; no tentative holds. | | OwnerRez | ✓ | ✓ | – | ✓ | – | No cancel through OwnerRez&#39;s API; priced by the property&#39;s own rates; needs the &#x60;full&#x60; scope. | | Track | ✓ | ✓ | ✓ | ✓ | ✓ | Track decides Hold vs Confirmed from the property&#39;s channel mode; a set price on a Channel Key needs \&quot;Allow Custom Pricing\&quot;; a unit change needs &#x60;moveReasonId&#x60; on the connection; a date change re-prices at Track&#39;s current rates. | Every PMS except Cloudbeds refuses group bookings, and every vacation-rental PMS refuses to change or cancel a booking that came from a channel (Airbnb, Booking.com, Vrbo…) — that is done on the channel. **Verification.** Mews and Cloudbeds were run end to end on their vendors&#39; sandboxes. Every other PMS is **verified against the vendor&#39;s API documentation only** — no live account has been written to yet. &#x60;capabilities.reservations.verifiedAgainst&#x60; says which. ### Idempotency **Send &#x60;Idempotency-Key&#x60;.** A network timeout here is exactly the case it exists for. The key is also sent to the PMS as the booking&#39;s reference, so even a retry that reaches the PMS again finds the booking instead of making a second one (&#x60;409 pms_duplicate&#x60; with &#x60;existing&#x60;, or the existing booking returned). A completed answer is replayed with &#x60;Idempotency-Status: cached&#x60; and the PMS is not called again. &#x60;502 pms_error&#x60; (the PMS could not be reached) is NOT stored — retry with the same key. &#x60;502 reservation_created_in_pms_only&#x60; IS stored, unlike every other 5xx: the booking exists in the PMS and arrives with the next sync, so a retry replays that answer rather than booking twice. ### Partial success When the PMS created the booking but a follow-up step did not apply (for example the notes, or a tentative state), the response is still &#x60;201&#x60;, with &#x60;pms.partial: true&#x60; and the steps in &#x60;pms.failedSections&#x60;. The booking exists — do not create it again. &#x60;X-Account-Id&#x60; restricts the listing to one connected account. Returns &#x60;403 listing_inactive&#x60; when the listing is inactive.
175
186
  # @param reservation_create_request [ReservationCreateRequest]
176
187
  # @param [Hash] opts the optional parameters
177
188
  # @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged &#x60;Idempotency-Status: cached&#x60; — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → &#x60;409 idempotency_key_in_use&#x60;. - Same key with a DIFFERENT payload → &#x60;422 idempotency_key_reused&#x60;. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status &gt;&#x3D; 500, &#x60;408&#x60;, &#x60;425&#x60; and &#x60;429&#x60;, and the refusals that happen before anything is done and tell you to fix something outside the request first — &#x60;connection_reauth_required&#x60;, &#x60;listing_inactive&#x60;, and the rate/daily limits. Every other answer, including a final refusal such as &#x60;422 airbnb_rejected&#x60;, is stored and replayed.
189
+ # @option opts [String] :x_account_id Restrict the request to one connected account (a Repull connection id, &#x60;GET /v1/connect&#x60; → &#x60;id&#x60;). A listing or reservation outside that account answers &#x60;404 not_found&#x60;. Omit it to act workspace-wide.
178
190
  # @return [Array<(ReservationCreateResponse, Integer, Hash)>] ReservationCreateResponse data, response status code and response headers
179
191
  def create_reservation_with_http_info(reservation_create_request, opts = {})
180
192
  if @api_client.config.debugging
@@ -204,6 +216,7 @@ module Repull
204
216
  header_params['Content-Type'] = content_type
205
217
  end
206
218
  header_params[:'Idempotency-Key'] = opts[:'idempotency_key'] if !opts[:'idempotency_key'].nil?
219
+ header_params[:'X-Account-Id'] = opts[:'x_account_id'] if !opts[:'x_account_id'].nil?
207
220
 
208
221
  # form parameters
209
222
  form_params = opts[:form_params] || {}
@@ -518,12 +531,84 @@ module Repull
518
531
  return data, status_code, headers
519
532
  end
520
533
 
534
+ # Quote a reservation in the PMS
535
+ # Prices a stay and checks its availability **in the PMS that manages the listing**, without booking anything. It is the same check `POST /v1/reservations` makes before booking when no `totalPrice` is sent, so `available: true` with a `total` is what that create would be priced at (dates can still be taken in between). `available: false` is an answer, not an error: the PMS's reasons are in `restrictions` (minimum stay, closed to arrival, taken dates…). - A listing **not managed in a PMS** answers `422 pms_not_linked`. Book it directly with `POST /v1/reservations`, or price it with `GET /v1/quotes`. - A PMS **without a quote API** (Mews, Cloudbeds, iGMS) answers `422 pms_write_unsupported`. You can still create the booking; on iGMS a `totalPrice` is required. `GET /v1/listings/{id}` → `capabilities.reservations.quote` says whether a listing can be quoted. ### Per-PMS limits | PMS | create | change | cancel | quote | `totalPrice` | Limits | |---|---|---|---|---|---|---| | Mews | ✓ | ✓ | ✓ | – | ✓ | — | | Cloudbeds | ✓ | ✓ | ✓ | – | – | Books at the rate plan's price; group bookings supported. | | Hostaway | ✓ | ✓ | ✓ | ✓ | ✓ | Direct-channel bookings only; a specific unit is refused; a date change keeps the booked total. | | Guesty | ✓ | ✓ | ✓ | ✓ | ✓ | Cancels direct and Vrbo bookings; other channel bookings are cancelled on the channel. | | Beds24 | ✓ | ✓ | ✓ | ✓ | ✓ | Needs the `write:bookings` scope; a multi-room property needs `unitId`. | | BookingSync | ✓ | ✓ | ✓ | ✓ | ✓ | Needs `bookings_write`; fees and taxes are not itemized; no guest email. | | Lodgify | ✓ | ✓ | ✓ (declines) | ✓ | ✓ | Cancel declines the booking; single-room bookings. | | Smoobu | ✓ | ✓ (no dates) | ✓ | ✓ | ✓ | Dates cannot be changed through Smoobu's API — cancel and rebook, or change them in Smoobu. | | Hospitable | ✓ | ✓ | ✓ | ✓ (Direct plan) | ✓ | Manual reservations only; needs `reservation:write`; adds no fees or taxes. | | iGMS | ✓ | ✓ | ✓ | – | ✓ (required) | iGMS direct bookings only; a price is required; no tentative holds. | | OwnerRez | ✓ | ✓ | – | ✓ | – | No cancel through OwnerRez's API; priced by the property's own rates; needs the `full` scope. | | Track | ✓ | ✓ | ✓ | ✓ | ✓ | Track decides Hold vs Confirmed from the property's channel mode; a set price on a Channel Key needs \"Allow Custom Pricing\"; a unit change needs `moveReasonId` on the connection; a date change re-prices at Track's current rates. | Every PMS except Cloudbeds refuses group bookings, and every vacation-rental PMS refuses to change or cancel a booking that came from a channel (Airbnb, Booking.com, Vrbo…) — that is done on the channel. **Verification.** Mews and Cloudbeds were run end to end on their vendors' sandboxes. Every other PMS is **verified against the vendor's API documentation only** — no live account has been written to yet. `capabilities.reservations.verifiedAgainst` says which. `X-Account-Id` restricts the listing to one connected account. Returns `403 listing_inactive` when the listing is inactive.
536
+ # @param reservation_quote_request [ReservationQuoteRequest]
537
+ # @param [Hash] opts the optional parameters
538
+ # @option opts [String] :x_account_id Restrict the request to one connected account (a Repull connection id, &#x60;GET /v1/connect&#x60; → &#x60;id&#x60;). A listing or reservation outside that account answers &#x60;404 not_found&#x60;. Omit it to act workspace-wide.
539
+ # @return [ReservationQuoteResponse]
540
+ def quote_reservation(reservation_quote_request, opts = {})
541
+ data, _status_code, _headers = quote_reservation_with_http_info(reservation_quote_request, opts)
542
+ data
543
+ end
544
+
545
+ # Quote a reservation in the PMS
546
+ # Prices a stay and checks its availability **in the PMS that manages the listing**, without booking anything. It is the same check &#x60;POST /v1/reservations&#x60; makes before booking when no &#x60;totalPrice&#x60; is sent, so &#x60;available: true&#x60; with a &#x60;total&#x60; is what that create would be priced at (dates can still be taken in between). &#x60;available: false&#x60; is an answer, not an error: the PMS&#39;s reasons are in &#x60;restrictions&#x60; (minimum stay, closed to arrival, taken dates…). - A listing **not managed in a PMS** answers &#x60;422 pms_not_linked&#x60;. Book it directly with &#x60;POST /v1/reservations&#x60;, or price it with &#x60;GET /v1/quotes&#x60;. - A PMS **without a quote API** (Mews, Cloudbeds, iGMS) answers &#x60;422 pms_write_unsupported&#x60;. You can still create the booking; on iGMS a &#x60;totalPrice&#x60; is required. &#x60;GET /v1/listings/{id}&#x60; → &#x60;capabilities.reservations.quote&#x60; says whether a listing can be quoted. ### Per-PMS limits | PMS | create | change | cancel | quote | &#x60;totalPrice&#x60; | Limits | |---|---|---|---|---|---|---| | Mews | ✓ | ✓ | ✓ | – | ✓ | — | | Cloudbeds | ✓ | ✓ | ✓ | – | – | Books at the rate plan&#39;s price; group bookings supported. | | Hostaway | ✓ | ✓ | ✓ | ✓ | ✓ | Direct-channel bookings only; a specific unit is refused; a date change keeps the booked total. | | Guesty | ✓ | ✓ | ✓ | ✓ | ✓ | Cancels direct and Vrbo bookings; other channel bookings are cancelled on the channel. | | Beds24 | ✓ | ✓ | ✓ | ✓ | ✓ | Needs the &#x60;write:bookings&#x60; scope; a multi-room property needs &#x60;unitId&#x60;. | | BookingSync | ✓ | ✓ | ✓ | ✓ | ✓ | Needs &#x60;bookings_write&#x60;; fees and taxes are not itemized; no guest email. | | Lodgify | ✓ | ✓ | ✓ (declines) | ✓ | ✓ | Cancel declines the booking; single-room bookings. | | Smoobu | ✓ | ✓ (no dates) | ✓ | ✓ | ✓ | Dates cannot be changed through Smoobu&#39;s API — cancel and rebook, or change them in Smoobu. | | Hospitable | ✓ | ✓ | ✓ | ✓ (Direct plan) | ✓ | Manual reservations only; needs &#x60;reservation:write&#x60;; adds no fees or taxes. | | iGMS | ✓ | ✓ | ✓ | – | ✓ (required) | iGMS direct bookings only; a price is required; no tentative holds. | | OwnerRez | ✓ | ✓ | – | ✓ | – | No cancel through OwnerRez&#39;s API; priced by the property&#39;s own rates; needs the &#x60;full&#x60; scope. | | Track | ✓ | ✓ | ✓ | ✓ | ✓ | Track decides Hold vs Confirmed from the property&#39;s channel mode; a set price on a Channel Key needs \&quot;Allow Custom Pricing\&quot;; a unit change needs &#x60;moveReasonId&#x60; on the connection; a date change re-prices at Track&#39;s current rates. | Every PMS except Cloudbeds refuses group bookings, and every vacation-rental PMS refuses to change or cancel a booking that came from a channel (Airbnb, Booking.com, Vrbo…) — that is done on the channel. **Verification.** Mews and Cloudbeds were run end to end on their vendors&#39; sandboxes. Every other PMS is **verified against the vendor&#39;s API documentation only** — no live account has been written to yet. &#x60;capabilities.reservations.verifiedAgainst&#x60; says which. &#x60;X-Account-Id&#x60; restricts the listing to one connected account. Returns &#x60;403 listing_inactive&#x60; when the listing is inactive.
547
+ # @param reservation_quote_request [ReservationQuoteRequest]
548
+ # @param [Hash] opts the optional parameters
549
+ # @option opts [String] :x_account_id Restrict the request to one connected account (a Repull connection id, &#x60;GET /v1/connect&#x60; → &#x60;id&#x60;). A listing or reservation outside that account answers &#x60;404 not_found&#x60;. Omit it to act workspace-wide.
550
+ # @return [Array<(ReservationQuoteResponse, Integer, Hash)>] ReservationQuoteResponse data, response status code and response headers
551
+ def quote_reservation_with_http_info(reservation_quote_request, opts = {})
552
+ if @api_client.config.debugging
553
+ @api_client.config.logger.debug 'Calling API: ReservationsApi.quote_reservation ...'
554
+ end
555
+ # verify the required parameter 'reservation_quote_request' is set
556
+ if @api_client.config.client_side_validation && reservation_quote_request.nil?
557
+ fail ArgumentError, "Missing the required parameter 'reservation_quote_request' when calling ReservationsApi.quote_reservation"
558
+ end
559
+ # resource path
560
+ local_var_path = '/v1/reservations/quote'
561
+
562
+ # query parameters
563
+ query_params = opts[:query_params] || {}
564
+
565
+ # header parameters
566
+ header_params = opts[:header_params] || {}
567
+ # HTTP header 'Accept' (if needed)
568
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
569
+ # HTTP header 'Content-Type'
570
+ content_type = @api_client.select_header_content_type(['application/json'])
571
+ if !content_type.nil?
572
+ header_params['Content-Type'] = content_type
573
+ end
574
+ header_params[:'X-Account-Id'] = opts[:'x_account_id'] if !opts[:'x_account_id'].nil?
575
+
576
+ # form parameters
577
+ form_params = opts[:form_params] || {}
578
+
579
+ # http body (model)
580
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(reservation_quote_request)
581
+
582
+ # return_type
583
+ return_type = opts[:debug_return_type] || 'ReservationQuoteResponse'
584
+
585
+ # auth_names
586
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
587
+
588
+ new_options = opts.merge(
589
+ :operation => :"ReservationsApi.quote_reservation",
590
+ :header_params => header_params,
591
+ :query_params => query_params,
592
+ :form_params => form_params,
593
+ :body => post_body,
594
+ :auth_names => auth_names,
595
+ :return_type => return_type
596
+ )
597
+
598
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
599
+ if @api_client.config.debugging
600
+ @api_client.config.logger.debug "API called: ReservationsApi#quote_reservation\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
601
+ end
602
+ return data, status_code, headers
603
+ end
604
+
521
605
  # Update a reservation
522
- # Changes the dates, the occupancy, or the unit. Drives the same command path the dashboard does, so the side effects come with it: the change audit is appended, bound task due dates re-sync, the old calendar dates unblock and the new ones block, the conversation's cached listing is invalidated, and `reservation.updated` fires — which is what revokes and re-issues the door code. Supply at least one field; an empty body returns 422 rather than a 200 that changed nothing. **Moving and re-dating in one call is one operation.** Send `listingId` together with `checkIn`/`checkOut` and it is applied as a single move, so the access code is re-issued once rather than twice. ### Fields this endpoint deliberately does NOT accept Each is rejected by name with the reason, never accepted and ignored: | Field | Why | |---|---| | `guest` / `guestDetails` | Guest name, email and phone live on the guest record. The underlying command has no branch for them, so accepting them would return a success that changed nothing. | | `pricing` / `totalPrice` / `currency` | Repricing writes the price breakdown, the pricing row and a pricing-history entry. It belongs to its own endpoint. | | `status` | Not a field. Cancelling, confirming and checking out are separate operations with materially different side effects — cancellation issues a credit refund and revokes access codes. | | `platform` | Immutable: it records where the booking actually originated. | | `notes` | `internal_notes` is an append-only audit trail the system writes on every change. | **Availability is NOT checked.** A date change that overlaps another booking will be written. Call `GET /v1/availability/{propertyId}` first if that matters. Returns `403 listing_inactive` when the reservation is on an inactive listing, or when a `listingId` move targets one; nothing is changed.
606
+ # Changes the dates, the occupancy, or the unit. **A stay managed in a connected PMS is changed in the PMS first**, then Repull's copy is refreshed from the PMS's record — changing only Repull's copy would be reverted by the next sync. On such a stay, `checkIn`, `checkOut` and `guestCount` are changed; moving it to another listing and changing its check-in/check-out times are done in the PMS (`422 pms_write_unsupported`), as is anything the PMS's API cannot change (for example dates on Smoobu). A channel booking that came in through the PMS (Airbnb, Booking.com, …) is changed on the channel (`409 reservation_owned_by_channel`). The PMS checks availability: taken dates answer `409 pms_unavailable`. The PMS's outcome comes back as `pms`. `GET /v1/listings/{id}` → `capabilities.reservations.modify` says whether a listing's PMS supports changes. **Any other stay** drives the same command path the dashboard does, so the side effects come with it: the change audit is appended, bound task due dates re-sync, the old calendar dates unblock and the new ones block, the conversation's cached listing is invalidated, and `reservation.updated` fires — which is what revokes and re-issues the door code. Supply at least one field; an empty body returns 422 rather than a 200 that changed nothing. **Moving and re-dating in one call is one operation.** Send `listingId` together with `checkIn`/`checkOut` and it is applied as a single move, so the access code is re-issued once rather than twice. ### Fields this endpoint deliberately does NOT accept Each is rejected by name with the reason, never accepted and ignored: | Field | Why | |---|---| | `guest` / `guestDetails` | Guest name, email and phone live on the guest record. The underlying command has no branch for them, so accepting them would return a success that changed nothing. | | `pricing` / `totalPrice` / `currency` | Repricing writes the price breakdown, the pricing row and a pricing-history entry. It belongs to its own endpoint. | | `status` | Not a field. Cancelling, confirming and checking out are separate operations with materially different side effects — cancellation issues a credit refund and revokes access codes. | | `platform` | Immutable: it records where the booking actually originated. | | `notes` | `internal_notes` is an append-only audit trail the system writes on every change. | **Availability is NOT checked for stays outside a PMS.** A date change that overlaps another booking will be written. Call `GET /v1/availability/{propertyId}` first if that matters. `X-Account-Id` restricts the reservation (and a listing it is moved to) to one connected account. Returns `403 listing_inactive` when the reservation is on an inactive listing, or when a `listingId` move targets one; nothing is changed.
523
607
  # @param id [Integer] Internal Repull reservation ID.
524
608
  # @param reservation_update_request [ReservationUpdateRequest]
525
609
  # @param [Hash] opts the optional parameters
526
610
  # @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged &#x60;Idempotency-Status: cached&#x60; — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → &#x60;409 idempotency_key_in_use&#x60;. - Same key with a DIFFERENT payload → &#x60;422 idempotency_key_reused&#x60;. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status &gt;&#x3D; 500, &#x60;408&#x60;, &#x60;425&#x60; and &#x60;429&#x60;, and the refusals that happen before anything is done and tell you to fix something outside the request first — &#x60;connection_reauth_required&#x60;, &#x60;listing_inactive&#x60;, and the rate/daily limits. Every other answer, including a final refusal such as &#x60;422 airbnb_rejected&#x60;, is stored and replayed.
611
+ # @option opts [String] :x_account_id Restrict the request to one connected account (a Repull connection id, &#x60;GET /v1/connect&#x60; → &#x60;id&#x60;). A listing or reservation outside that account answers &#x60;404 not_found&#x60;. Omit it to act workspace-wide.
527
612
  # @return [ReservationUpdateResponse]
528
613
  def update_reservation(id, reservation_update_request, opts = {})
529
614
  data, _status_code, _headers = update_reservation_with_http_info(id, reservation_update_request, opts)
@@ -531,11 +616,12 @@ module Repull
531
616
  end
532
617
 
533
618
  # Update a reservation
534
- # Changes the dates, the occupancy, or the unit. Drives the same command path the dashboard does, so the side effects come with it: the change audit is appended, bound task due dates re-sync, the old calendar dates unblock and the new ones block, the conversation&#39;s cached listing is invalidated, and &#x60;reservation.updated&#x60; fires — which is what revokes and re-issues the door code. Supply at least one field; an empty body returns 422 rather than a 200 that changed nothing. **Moving and re-dating in one call is one operation.** Send &#x60;listingId&#x60; together with &#x60;checkIn&#x60;/&#x60;checkOut&#x60; and it is applied as a single move, so the access code is re-issued once rather than twice. ### Fields this endpoint deliberately does NOT accept Each is rejected by name with the reason, never accepted and ignored: | Field | Why | |---|---| | &#x60;guest&#x60; / &#x60;guestDetails&#x60; | Guest name, email and phone live on the guest record. The underlying command has no branch for them, so accepting them would return a success that changed nothing. | | &#x60;pricing&#x60; / &#x60;totalPrice&#x60; / &#x60;currency&#x60; | Repricing writes the price breakdown, the pricing row and a pricing-history entry. It belongs to its own endpoint. | | &#x60;status&#x60; | Not a field. Cancelling, confirming and checking out are separate operations with materially different side effects — cancellation issues a credit refund and revokes access codes. | | &#x60;platform&#x60; | Immutable: it records where the booking actually originated. | | &#x60;notes&#x60; | &#x60;internal_notes&#x60; is an append-only audit trail the system writes on every change. | **Availability is NOT checked.** A date change that overlaps another booking will be written. Call &#x60;GET /v1/availability/{propertyId}&#x60; first if that matters. Returns &#x60;403 listing_inactive&#x60; when the reservation is on an inactive listing, or when a &#x60;listingId&#x60; move targets one; nothing is changed.
619
+ # Changes the dates, the occupancy, or the unit. **A stay managed in a connected PMS is changed in the PMS first**, then Repull&#39;s copy is refreshed from the PMS&#39;s record — changing only Repull&#39;s copy would be reverted by the next sync. On such a stay, &#x60;checkIn&#x60;, &#x60;checkOut&#x60; and &#x60;guestCount&#x60; are changed; moving it to another listing and changing its check-in/check-out times are done in the PMS (&#x60;422 pms_write_unsupported&#x60;), as is anything the PMS&#39;s API cannot change (for example dates on Smoobu). A channel booking that came in through the PMS (Airbnb, Booking.com, …) is changed on the channel (&#x60;409 reservation_owned_by_channel&#x60;). The PMS checks availability: taken dates answer &#x60;409 pms_unavailable&#x60;. The PMS&#39;s outcome comes back as &#x60;pms&#x60;. &#x60;GET /v1/listings/{id}&#x60; → &#x60;capabilities.reservations.modify&#x60; says whether a listing&#39;s PMS supports changes. **Any other stay** drives the same command path the dashboard does, so the side effects come with it: the change audit is appended, bound task due dates re-sync, the old calendar dates unblock and the new ones block, the conversation&#39;s cached listing is invalidated, and &#x60;reservation.updated&#x60; fires — which is what revokes and re-issues the door code. Supply at least one field; an empty body returns 422 rather than a 200 that changed nothing. **Moving and re-dating in one call is one operation.** Send &#x60;listingId&#x60; together with &#x60;checkIn&#x60;/&#x60;checkOut&#x60; and it is applied as a single move, so the access code is re-issued once rather than twice. ### Fields this endpoint deliberately does NOT accept Each is rejected by name with the reason, never accepted and ignored: | Field | Why | |---|---| | &#x60;guest&#x60; / &#x60;guestDetails&#x60; | Guest name, email and phone live on the guest record. The underlying command has no branch for them, so accepting them would return a success that changed nothing. | | &#x60;pricing&#x60; / &#x60;totalPrice&#x60; / &#x60;currency&#x60; | Repricing writes the price breakdown, the pricing row and a pricing-history entry. It belongs to its own endpoint. | | &#x60;status&#x60; | Not a field. Cancelling, confirming and checking out are separate operations with materially different side effects — cancellation issues a credit refund and revokes access codes. | | &#x60;platform&#x60; | Immutable: it records where the booking actually originated. | | &#x60;notes&#x60; | &#x60;internal_notes&#x60; is an append-only audit trail the system writes on every change. | **Availability is NOT checked for stays outside a PMS.** A date change that overlaps another booking will be written. Call &#x60;GET /v1/availability/{propertyId}&#x60; first if that matters. &#x60;X-Account-Id&#x60; restricts the reservation (and a listing it is moved to) to one connected account. Returns &#x60;403 listing_inactive&#x60; when the reservation is on an inactive listing, or when a &#x60;listingId&#x60; move targets one; nothing is changed.
535
620
  # @param id [Integer] Internal Repull reservation ID.
536
621
  # @param reservation_update_request [ReservationUpdateRequest]
537
622
  # @param [Hash] opts the optional parameters
538
623
  # @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged &#x60;Idempotency-Status: cached&#x60; — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → &#x60;409 idempotency_key_in_use&#x60;. - Same key with a DIFFERENT payload → &#x60;422 idempotency_key_reused&#x60;. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status &gt;&#x3D; 500, &#x60;408&#x60;, &#x60;425&#x60; and &#x60;429&#x60;, and the refusals that happen before anything is done and tell you to fix something outside the request first — &#x60;connection_reauth_required&#x60;, &#x60;listing_inactive&#x60;, and the rate/daily limits. Every other answer, including a final refusal such as &#x60;422 airbnb_rejected&#x60;, is stored and replayed.
624
+ # @option opts [String] :x_account_id Restrict the request to one connected account (a Repull connection id, &#x60;GET /v1/connect&#x60; → &#x60;id&#x60;). A listing or reservation outside that account answers &#x60;404 not_found&#x60;. Omit it to act workspace-wide.
539
625
  # @return [Array<(ReservationUpdateResponse, Integer, Hash)>] ReservationUpdateResponse data, response status code and response headers
540
626
  def update_reservation_with_http_info(id, reservation_update_request, opts = {})
541
627
  if @api_client.config.debugging
@@ -569,6 +655,7 @@ module Repull
569
655
  header_params['Content-Type'] = content_type
570
656
  end
571
657
  header_params[:'Idempotency-Key'] = opts[:'idempotency_key'] if !opts[:'idempotency_key'].nil?
658
+ header_params[:'X-Account-Id'] = opts[:'x_account_id'] if !opts[:'x_account_id'].nil?
572
659
 
573
660
  # form parameters
574
661
  form_params = opts[:form_params] || {}
@@ -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_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`.
4
+ #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_live_YOUR_API_KEY ``` ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resetsAt` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | unlimited (10 included, then billed per listing) | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
5
 
6
6
  The version of the OpenAPI document: 1.0.0
7
7
 
@@ -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_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`.
4
+ #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_live_YOUR_API_KEY ``` ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resetsAt` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | unlimited (10 included, then billed per listing) | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
5
 
6
6
  The version of the OpenAPI document: 1.0.0
7
7
 
@@ -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_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`.
4
+ #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_live_YOUR_API_KEY ``` ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resetsAt` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | unlimited (10 included, then billed per listing) | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
5
 
6
6
  The version of the OpenAPI document: 1.0.0
7
7