repull 0.2.7 → 0.2.9

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 (285) hide show
  1. checksums.yaml +4 -4
  2. data/lib/repull/api/airbnb_api.rb +117 -130
  3. data/lib/repull/api/atlas_api.rb +1 -1
  4. data/lib/repull/api/billing_api.rb +1 -56
  5. data/lib/repull/api/booking_com_api.rb +20 -119
  6. data/lib/repull/api/connect_api.rb +1 -1
  7. data/lib/repull/api/conversations_api.rb +1 -1
  8. data/lib/repull/api/guests_api.rb +1 -1
  9. data/lib/repull/api/kv_api.rb +1 -1
  10. data/lib/repull/api/listings_api.rb +212 -1
  11. data/lib/repull/api/markets_api.rb +1 -1
  12. data/lib/repull/api/plumguide_api.rb +1 -1
  13. data/lib/repull/api/pricing_api.rb +1 -1
  14. data/lib/repull/api/properties_api.rb +1 -1
  15. data/lib/repull/api/reservations_api.rb +1 -198
  16. data/lib/repull/api/reviews_api.rb +1 -1
  17. data/lib/repull/api/{availability_api.rb → sandbox_api.rb} +36 -67
  18. data/lib/repull/api/schema_api.rb +1 -1
  19. data/lib/repull/api/system_api.rb +1 -1
  20. data/lib/repull/api/vrbo_api.rb +1 -127
  21. data/lib/repull/api/webhooks_api.rb +1 -1
  22. data/lib/repull/api_client.rb +1 -1
  23. data/lib/repull/api_error.rb +1 -1
  24. data/lib/repull/api_model_base.rb +1 -1
  25. data/lib/repull/configuration.rb +1 -1
  26. data/lib/repull/models/account_created_event.rb +1 -1
  27. data/lib/repull/models/account_created_payload.rb +1 -1
  28. data/lib/repull/models/account_disconnected_event.rb +1 -1
  29. data/lib/repull/models/account_disconnected_payload.rb +1 -1
  30. data/lib/repull/models/ai_operation.rb +1 -1
  31. data/lib/repull/models/ai_operation_completed_event.rb +1 -1
  32. data/lib/repull/models/ai_operation_completed_payload.rb +1 -1
  33. data/lib/repull/models/ai_operation_failed_event.rb +1 -1
  34. data/lib/repull/models/ai_operation_failed_payload.rb +1 -1
  35. data/lib/repull/models/ai_operation_failed_payload_error.rb +1 -1
  36. data/lib/repull/models/{create_studio_project_request.rb → airbnb_availability_write_request.rb} +39 -53
  37. data/lib/repull/models/{create_studio_deployment201_response_data.rb → airbnb_calendar_operation.rb} +109 -58
  38. data/lib/repull/models/airbnb_connection.rb +1 -1
  39. data/lib/repull/models/airbnb_connection_accessibility_amenities_inner.rb +1 -1
  40. data/lib/repull/models/airbnb_connection_amenities_inner.rb +1 -1
  41. data/lib/repull/models/airbnb_connection_host.rb +1 -1
  42. data/lib/repull/models/airbnb_connection_response.rb +1 -1
  43. data/lib/repull/models/airbnb_connection_summary.rb +1 -1
  44. data/lib/repull/models/airbnb_data_freshness.rb +1 -1
  45. data/lib/repull/models/airbnb_listing.rb +1 -1
  46. data/lib/repull/models/{update_studio_project_request.rb → airbnb_listing_action_request.rb} +56 -48
  47. data/lib/repull/models/airbnb_listing_list_response.rb +1 -1
  48. data/lib/repull/models/{update_availability_request.rb → airbnb_pricing_write_request.rb} +101 -12
  49. data/lib/repull/models/airbnb_reservation.rb +1 -1
  50. data/lib/repull/models/airbnb_reservation_list_response.rb +1 -1
  51. data/lib/repull/models/airbnb_review.rb +1 -1
  52. data/lib/repull/models/airbnb_review_list_response.rb +1 -1
  53. data/lib/repull/models/airbnb_thread.rb +1 -1
  54. data/lib/repull/models/airbnb_thread_list_response.rb +1 -1
  55. data/lib/repull/models/{create_studio_project201_response_data.rb → booking_availability_update.rb} +126 -49
  56. data/lib/repull/models/{list_studio_deployments200_response.rb → booking_availability_update_request.rb} +91 -19
  57. data/lib/repull/models/{generate_studio_completion_request_project_id.rb → booking_availability_update_request_property_id.rb} +3 -3
  58. data/lib/repull/models/{get_studio_deployment200_response.rb → booking_availability_update_request_updates_inner.rb} +75 -118
  59. data/lib/repull/models/booking_connect_listing_option.rb +1 -1
  60. data/lib/repull/models/booking_connect_room.rb +1 -1
  61. data/lib/repull/models/booking_connect_rooms_response.rb +1 -1
  62. data/lib/repull/models/booking_conversation.rb +1 -1
  63. data/lib/repull/models/booking_conversation_list_response.rb +1 -1
  64. data/lib/repull/models/booking_pricing_rate_update.rb +2 -1
  65. data/lib/repull/models/booking_pricing_rate_update_date_range.rb +1 -1
  66. data/lib/repull/models/booking_pricing_rate_update_restrictions.rb +66 -7
  67. data/lib/repull/models/booking_pricing_response.rb +1 -1
  68. data/lib/repull/models/booking_pricing_update_request.rb +1 -1
  69. data/lib/repull/models/booking_pricing_update_response.rb +1 -1
  70. data/lib/repull/models/booking_property.rb +1 -1
  71. data/lib/repull/models/booking_property_list_response.rb +1 -1
  72. data/lib/repull/models/booking_room_mapping.rb +1 -1
  73. data/lib/repull/models/booking_verify_hotel_request.rb +1 -1
  74. data/lib/repull/models/booking_verify_hotel_response.rb +1 -1
  75. data/lib/repull/models/bulk_pricing_failure.rb +1 -1
  76. data/lib/repull/models/bulk_pricing_item.rb +1 -1
  77. data/lib/repull/models/bulk_pricing_request.rb +1 -1
  78. data/lib/repull/models/bulk_pricing_response.rb +1 -1
  79. data/lib/repull/models/calendar_day.rb +1 -1
  80. data/lib/repull/models/calendar_response.rb +1 -1
  81. data/lib/repull/models/calendar_updated_event.rb +1 -1
  82. data/lib/repull/models/calendar_updated_payload.rb +1 -1
  83. data/lib/repull/models/calendar_updated_payload_range.rb +1 -1
  84. data/lib/repull/models/clear_kv200_response.rb +1 -1
  85. data/lib/repull/models/connect_host.rb +1 -1
  86. data/lib/repull/models/connect_provider.rb +1 -1
  87. data/lib/repull/models/connect_provider_list_response.rb +1 -1
  88. data/lib/repull/models/connect_session.rb +1 -1
  89. data/lib/repull/models/connect_status.rb +1 -1
  90. data/lib/repull/models/connection.rb +1 -1
  91. data/lib/repull/models/connection_list_response.rb +1 -1
  92. data/lib/repull/models/conversation.rb +1 -1
  93. data/lib/repull/models/conversation_detail.rb +1 -1
  94. data/lib/repull/models/conversation_guest.rb +1 -1
  95. data/lib/repull/models/conversation_guest_contact.rb +1 -1
  96. data/lib/repull/models/conversation_host.rb +1 -1
  97. data/lib/repull/models/conversation_list_response.rb +1 -1
  98. data/lib/repull/models/conversation_message_attachment.rb +1 -1
  99. data/lib/repull/models/create_billing_checkout_request.rb +1 -1
  100. data/lib/repull/models/create_connect_session_request.rb +1 -1
  101. data/lib/repull/models/create_connection_request.rb +1 -1
  102. data/lib/repull/models/create_webhook_request.rb +1 -1
  103. data/lib/repull/models/custom_schema.rb +1 -1
  104. data/lib/repull/models/custom_schema_create.rb +1 -1
  105. data/lib/repull/models/custom_schema_create_response.rb +1 -1
  106. data/lib/repull/models/custom_schema_delete_response.rb +1 -1
  107. data/lib/repull/models/custom_schema_list_response.rb +1 -1
  108. data/lib/repull/models/custom_schema_summary.rb +1 -1
  109. data/lib/repull/models/custom_schema_update.rb +1 -1
  110. data/lib/repull/models/delete_kv200_response.rb +1 -1
  111. data/lib/repull/models/error.rb +1 -1
  112. data/lib/repull/models/error_error.rb +1 -1
  113. data/lib/repull/models/error_error_support.rb +1 -1
  114. data/lib/repull/models/get_health200_response.rb +1 -1
  115. data/lib/repull/models/guest.rb +1 -1
  116. data/lib/repull/models/guest_contact.rb +1 -1
  117. data/lib/repull/models/guest_flag.rb +1 -1
  118. data/lib/repull/models/guest_list_response.rb +1 -1
  119. data/lib/repull/models/guest_note.rb +1 -1
  120. data/lib/repull/models/guest_profile.rb +1 -1
  121. data/lib/repull/models/guest_reservations_summary.rb +1 -1
  122. data/lib/repull/models/list_kv200_response.rb +1 -1
  123. data/lib/repull/models/list_kv200_response_data_inner.rb +1 -1
  124. data/lib/repull/models/list_kv200_response_pagination.rb +1 -1
  125. data/lib/repull/models/listing.rb +1 -1
  126. data/lib/repull/models/{create_studio_project_generation_request.rb → listing_active_request.rb} +21 -21
  127. data/lib/repull/models/{delete_studio_project200_response_data.rb → listing_active_response.rb} +13 -11
  128. data/lib/repull/models/listing_address.rb +1 -1
  129. data/lib/repull/models/listing_amenity.rb +1 -1
  130. data/lib/repull/models/listing_channel.rb +1 -1
  131. data/lib/repull/models/listing_comp.rb +1 -1
  132. data/lib/repull/models/listing_comp_nightly.rb +1 -1
  133. data/lib/repull/models/listing_comp_ratings.rb +1 -1
  134. data/lib/repull/models/listing_comps_response.rb +1 -1
  135. data/lib/repull/models/listing_content.rb +1 -1
  136. data/lib/repull/models/{get_studio_project200_response.rb → listing_content_update_request.rb} +107 -11
  137. data/lib/repull/models/{upsert_studio_project_file200_response.rb → listing_content_update_request_address.rb} +54 -11
  138. data/lib/repull/models/listing_content_update_request_amenities.rb +105 -0
  139. data/lib/repull/models/{create_studio_deployment_request.rb → listing_content_update_request_amenities_one_of_inner.rb} +52 -21
  140. data/lib/repull/models/{update_reservation_request.rb → listing_content_update_request_occupancy.rb} +34 -29
  141. data/lib/repull/{api/ai_api.rb → models/listing_content_update_request_photos_inner.rb} +78 -60
  142. data/lib/repull/models/{generate_studio_completion200_response_data.rb → listing_content_update_request_photos_inner_one_of.rb} +82 -67
  143. data/lib/repull/models/{generate_studio_completion200_response.rb → listing_content_update_request_policies.rb} +117 -11
  144. data/lib/repull/models/{create_ai_operation200_response.rb → listing_content_update_response.rb} +33 -17
  145. data/lib/repull/models/listing_create_request.rb +1 -1
  146. data/lib/repull/models/listing_create_response.rb +1 -1
  147. data/lib/repull/models/listing_created_event.rb +1 -1
  148. data/lib/repull/models/listing_created_payload.rb +1 -1
  149. data/lib/repull/models/listing_created_payload_address.rb +1 -1
  150. data/lib/repull/models/listing_deleted_event.rb +1 -1
  151. data/lib/repull/models/listing_deleted_payload.rb +1 -1
  152. data/lib/repull/models/listing_details.rb +1 -1
  153. data/lib/repull/models/listing_generate_content_request.rb +1 -1
  154. data/lib/repull/models/listing_generate_content_response.rb +1 -1
  155. data/lib/repull/models/listing_list_response.rb +1 -1
  156. data/lib/repull/models/listing_pricing_apply_request.rb +1 -1
  157. data/lib/repull/models/listing_pricing_apply_response.rb +1 -1
  158. data/lib/repull/models/listing_pricing_history_entry.rb +1 -1
  159. data/lib/repull/models/listing_pricing_history_response.rb +1 -1
  160. data/lib/repull/models/listing_pricing_recommendation.rb +1 -1
  161. data/lib/repull/models/listing_pricing_response.rb +1 -1
  162. data/lib/repull/models/listing_pricing_response_comp_summary.rb +1 -1
  163. data/lib/repull/models/listing_pricing_response_date_range.rb +1 -1
  164. data/lib/repull/models/listing_pricing_response_listing.rb +1 -1
  165. data/lib/repull/models/listing_pricing_strategy.rb +1 -1
  166. data/lib/repull/models/listing_pricing_strategy_input.rb +1 -1
  167. data/lib/repull/models/listing_publish_airbnb_request.rb +1 -1
  168. data/lib/repull/models/listing_publish_response.rb +1 -1
  169. data/lib/repull/models/listing_publish_status_channel.rb +1 -1
  170. data/lib/repull/models/listing_publish_status_connection.rb +1 -1
  171. data/lib/repull/models/listing_publish_status_response.rb +1 -1
  172. data/lib/repull/models/listing_quality_tier.rb +1 -1
  173. data/lib/repull/models/listing_segment.rb +1 -1
  174. data/lib/repull/models/listing_segment_recommendation.rb +1 -1
  175. data/lib/repull/models/listing_segments_response.rb +1 -1
  176. data/lib/repull/models/listing_segments_response_scope.rb +1 -1
  177. data/lib/repull/models/listing_updated_event.rb +1 -1
  178. data/lib/repull/models/listing_updated_payload.rb +1 -1
  179. data/lib/repull/models/map_airbnb_listing_request.rb +215 -0
  180. data/lib/repull/models/{create_reservation_request.rb → map_airbnb_listing_response.rb} +138 -117
  181. data/lib/repull/models/map_connect_booking_rooms_request.rb +1 -1
  182. data/lib/repull/models/map_connect_booking_rooms_response.rb +1 -1
  183. data/lib/repull/models/market_browse_category.rb +1 -1
  184. data/lib/repull/models/market_browse_entry.rb +1 -1
  185. data/lib/repull/models/market_browse_featured.rb +1 -1
  186. data/lib/repull/models/market_browse_response.rb +1 -1
  187. data/lib/repull/models/market_calendar_day.rb +1 -1
  188. data/lib/repull/models/market_calendar_day_events_inner.rb +1 -1
  189. data/lib/repull/models/market_calendar_response.rb +1 -1
  190. data/lib/repull/models/market_detail_response.rb +1 -1
  191. data/lib/repull/models/market_detail_response_price_distribution_inner.rb +1 -1
  192. data/lib/repull/models/market_detail_response_property_type_mix_inner.rb +1 -1
  193. data/lib/repull/models/market_detail_response_supply_trend_inner.rb +1 -1
  194. data/lib/repull/models/market_detail_response_top_comps.rb +1 -1
  195. data/lib/repull/models/market_event.rb +1 -1
  196. data/lib/repull/models/market_my_listing.rb +1 -1
  197. data/lib/repull/models/market_summary.rb +1 -1
  198. data/lib/repull/models/market_top_comp.rb +1 -1
  199. data/lib/repull/models/markets_overview_response.rb +1 -1
  200. data/lib/repull/models/markets_overview_response_browse.rb +1 -1
  201. data/lib/repull/models/markets_overview_response_subscriptions.rb +1 -1
  202. data/lib/repull/models/markets_overview_response_totals.rb +1 -1
  203. data/lib/repull/models/message.rb +1 -1
  204. data/lib/repull/models/message_list_response.rb +1 -1
  205. data/lib/repull/models/pagination.rb +1 -1
  206. data/lib/repull/models/payment_completed_event.rb +1 -1
  207. data/lib/repull/models/payment_completed_payload.rb +1 -1
  208. data/lib/repull/models/payment_refunded_event.rb +1 -1
  209. data/lib/repull/models/payment_refunded_payload.rb +1 -1
  210. data/lib/repull/models/plumguide_listing.rb +1 -1
  211. data/lib/repull/models/plumguide_listing_list_response.rb +1 -1
  212. data/lib/repull/models/property.rb +43 -70
  213. data/lib/repull/models/property_list_response.rb +1 -1
  214. data/lib/repull/models/reply_booking_review200_response.rb +1 -1
  215. data/lib/repull/models/reply_booking_review_request.rb +1 -1
  216. data/lib/repull/models/repull_ping_event.rb +1 -1
  217. data/lib/repull/models/repull_ping_payload.rb +1 -1
  218. data/lib/repull/models/reservation.rb +29 -2
  219. data/lib/repull/models/reservation_cancelled_event.rb +1 -1
  220. data/lib/repull/models/reservation_cancelled_payload.rb +1 -1
  221. data/lib/repull/models/reservation_created_event.rb +1 -1
  222. data/lib/repull/models/reservation_created_payload.rb +1 -1
  223. data/lib/repull/models/reservation_financials.rb +1 -1
  224. data/lib/repull/models/reservation_list_response.rb +1 -1
  225. data/lib/repull/models/reservation_message_received_event.rb +1 -1
  226. data/lib/repull/models/reservation_message_received_payload.rb +1 -1
  227. data/lib/repull/models/reservation_message_received_payload_from.rb +1 -1
  228. data/lib/repull/models/reservation_occupancy.rb +1 -1
  229. data/lib/repull/models/reservation_primary_guest.rb +1 -1
  230. data/lib/repull/models/reservation_updated_event.rb +1 -1
  231. data/lib/repull/models/reservation_updated_payload.rb +1 -1
  232. data/lib/repull/models/reservation_webhook_object.rb +1 -1
  233. data/lib/repull/models/respond_airbnb_review_request.rb +1 -1
  234. data/lib/repull/models/review.rb +1 -1
  235. data/lib/repull/models/review_category.rb +1 -1
  236. data/lib/repull/models/review_list_response.rb +1 -1
  237. data/lib/repull/models/review_response.rb +1 -1
  238. data/lib/repull/models/rotate_webhook_secret200_response.rb +1 -1
  239. data/lib/repull/models/{upsert_studio_project_file_request.rb → sandbox_fixture_ref.rb} +49 -21
  240. data/lib/repull/models/{delete_studio_deployment200_response_data.rb → sandbox_reset_result.rb} +73 -12
  241. data/lib/repull/models/sandbox_reset_result_deleted.rb +216 -0
  242. data/lib/repull/models/sandbox_seed_result.rb +278 -0
  243. data/lib/repull/models/select_connect_provider_request.rb +1 -1
  244. data/lib/repull/models/select_provider_response.rb +1 -1
  245. data/lib/repull/models/set_kv_request.rb +1 -1
  246. data/lib/repull/models/studio_deployment.rb +1 -1
  247. data/lib/repull/models/studio_error.rb +1 -1
  248. data/lib/repull/models/studio_error_error.rb +1 -1
  249. data/lib/repull/models/studio_file.rb +1 -1
  250. data/lib/repull/models/studio_generation.rb +1 -1
  251. data/lib/repull/models/studio_project.rb +1 -1
  252. data/lib/repull/models/test_webhook_request.rb +1 -1
  253. data/lib/repull/models/update_listing_pricing_strategy200_response.rb +1 -1
  254. data/lib/repull/models/update_webhook_request.rb +1 -1
  255. data/lib/repull/models/vrbo_listing.rb +1 -1
  256. data/lib/repull/models/vrbo_listing_list_response.rb +1 -1
  257. data/lib/repull/models/vrbo_reservation.rb +1 -1
  258. data/lib/repull/models/vrbo_reservation_list_response.rb +1 -1
  259. data/lib/repull/models/webhook_delivery.rb +1 -1
  260. data/lib/repull/models/webhook_delivery_detail.rb +1 -1
  261. data/lib/repull/models/webhook_delivery_list_response.rb +1 -1
  262. data/lib/repull/models/webhook_event.rb +1 -1
  263. data/lib/repull/models/webhook_event_catalog.rb +1 -1
  264. data/lib/repull/models/webhook_event_catalog_domains_inner.rb +1 -1
  265. data/lib/repull/models/webhook_event_catalog_entry.rb +1 -1
  266. data/lib/repull/models/webhook_event_type.rb +1 -1
  267. data/lib/repull/models/webhook_list_response.rb +1 -1
  268. data/lib/repull/models/webhook_subscription.rb +1 -1
  269. data/lib/repull/version.rb +2 -2
  270. data/lib/repull.rb +27 -36
  271. data/openapi/v1.json +3604 -4346
  272. metadata +28 -37
  273. data/lib/repull/api/studio_api.rb +0 -1094
  274. data/lib/repull/models/create_studio_deployment201_response.rb +0 -147
  275. data/lib/repull/models/create_studio_project201_response.rb +0 -147
  276. data/lib/repull/models/create_studio_project_generation201_response.rb +0 -147
  277. data/lib/repull/models/create_studio_project_generation201_response_data.rb +0 -165
  278. data/lib/repull/models/delete_studio_deployment200_response.rb +0 -147
  279. data/lib/repull/models/delete_studio_project200_response.rb +0 -147
  280. data/lib/repull/models/delete_studio_project_file200_response.rb +0 -147
  281. data/lib/repull/models/delete_studio_project_file200_response_data.rb +0 -156
  282. data/lib/repull/models/generate_studio_completion_request.rb +0 -305
  283. data/lib/repull/models/list_studio_project_files200_response.rb +0 -149
  284. data/lib/repull/models/list_studio_projects200_response.rb +0 -149
  285. data/lib/repull/models/upsert_studio_project_file200_response_data.rb +0 -147
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
  #Repull API
3
3
 
4
- #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_test_YOUR_API_KEY ``` Sandbox keys start with `sk_test_`, production with `sk_live_`. ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resets_at` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 5 | | `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_test_YOUR_API_KEY ``` Sandbox keys start with `sk_test_`, production with `sk_live_`. ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resets_at` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | 50 | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
5
 
6
6
  The version of the OpenAPI document: 1.0.0
7
7
  Contact: ivan@vanio.ai
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
  #Repull API
3
3
 
4
- #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_test_YOUR_API_KEY ``` Sandbox keys start with `sk_test_`, production with `sk_live_`. ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resets_at` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 5 | | `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_test_YOUR_API_KEY ``` Sandbox keys start with `sk_test_`, production with `sk_live_`. ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resets_at` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | 50 | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
5
 
6
6
  The version of the OpenAPI document: 1.0.0
7
7
  Contact: ivan@vanio.ai
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
  #Repull API
3
3
 
4
- #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_test_YOUR_API_KEY ``` Sandbox keys start with `sk_test_`, production with `sk_live_`. ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resets_at` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 5 | | `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_test_YOUR_API_KEY ``` Sandbox keys start with `sk_test_`, production with `sk_live_`. ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resets_at` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | 50 | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
5
 
6
6
  The version of the OpenAPI document: 1.0.0
7
7
  Contact: ivan@vanio.ai
@@ -11,5 +11,5 @@ Generator version: 7.22.0
11
11
  =end
12
12
 
13
13
  module Repull
14
- VERSION = '0.2.7'
14
+ VERSION = '0.2.9'
15
15
  end
data/lib/repull.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
  #Repull API
3
3
 
4
- #The unified API for vacation rental tech. Connect to 50+ PMS platforms and 4 OTA channels through one REST API. Built-in AI operations for guest communication, pricing, and listing optimization. ## Designed for AI agents Every error response on this API includes machine-parseable fields so an LLM (Claude in MCP, Cursor, Cline, GPT, etc.) can self-recover without escalating to a human: - `error.code` — stable string identifier (e.g. `invalid_params`, `rate_limit_exceeded`) - `error.message` — human-readable cause - `error.fix` — exact recovery steps (e.g. \"Pass `check_in_after` as ISO 8601: `?check_in_after=2026-01-15`\") - `error.docs_url` — link to the canonical write-up at `https://repull.dev/docs/errors/{code}` - `error.request_id` — id to correlate with server-side logs - `error.field` / `error.value_received` / `error.valid_values` / `error.did_you_mean` — when the error is parameter-specific - `error.retry_after` — seconds to wait before retrying (rate-limit + transient upstream) `Access-Control-Expose-Headers` lists `x-request-id` and the `X-RateLimit-*` family so browsers can read them on cross-origin responses. ## Quick Start 1. Get an API key at https://repull.dev/dashboard 2. Connect a PMS: `POST /v1/connect/{provider}` 3. List properties: `GET /v1/properties` 4. Get reservations: `GET /v1/reservations` ## Authentication All requests require a Bearer token: ``` Authorization: Bearer sk_test_YOUR_API_KEY ``` Sandbox keys start with `sk_test_`, production with `sk_live_`. ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resets_at` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 5 | | `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_test_YOUR_API_KEY ``` Sandbox keys start with `sk_test_`, production with `sk_live_`. ## Request Correlation (X-Request-ID) Every response carries an `X-Request-ID` header, e.g. `X-Request-ID: req_01HXY...`. Include this id in support tickets and bug reports — we can trace the full request lifecycle (auth, rate limit, handler, downstream calls, log row) from a single id. You may set the header on the inbound request to forward your own trace id; we will echo it back instead of generating a new one. Accepted format: `^[\\\\w.-]{1,128}$`. The id is also embedded in error envelopes as `request_id` so server-side log diffs work even when the response headers are stripped by an intermediate proxy. ## Rate Limits The public API enforces a per-API-key sliding-window rate limit on top of the per-tier monthly + daily-AI quotas. **Default policy:** 600 requests per 60 seconds, per API key. Sliding window — there is no fixed-minute boundary you can burst across. Every response includes: | Header | Meaning | |---|---| | `X-RateLimit-Limit` | Requests permitted in the current window. | | `X-RateLimit-Remaining` | Requests left in the current window after this call. | | `X-RateLimit-Reset` | Unix epoch (seconds) when the next slot opens. | | `X-RateLimit-Policy` | Machine-readable policy descriptor, e.g. `600;w=60`. | | `Retry-After` | Seconds to wait before retrying. **Only present on 429 responses.** | **On 429 (rate_limit_exceeded):** the response body matches the standard error envelope with `code: \"rate_limit_exceeded\"`, plus `limit`, `window_seconds`, `retry_after`, and `request_id` fields. SDKs MUST honor `Retry-After` and use exponential backoff with jitter on subsequent retries — never a tight loop. Recommended backoff: ``` sleep_ms = (Retry-After * 1000) + random(0..250) ``` Monthly + daily-AI tier quotas (`free`, `starter`, `custom`) are enforced separately and also surface as 429s; they include `tier`, `scope`, and `resets_at` fields. ## Plan Limits (402 — `listings_limit_exceeded`) The Repull API also enforces a per-tier cap on **active listings**: | Tier | Active listings cap | |---|---| | `free` | 3 | | `starter` | 50 | | `custom` | unlimited | When a customer's active-listing count is above their tier cap, the API returns **`402 Payment Required`** with `error.code = \"listings_limit_exceeded\"` on every route EXCEPT: - `/v1/health` — uptime probes are never gated. - `/v1/usage/*` — so dashboards can render the over-cap state. - Any `DELETE` — so the customer can trim listings to get back under the cap without paying. Unlike 429, 402 is NOT a \"wait and retry\" condition — `Retry-After` is not set. The only paths back to 200 are: 1. `DELETE` enough listings to come back under the cap, or 2. Upgrade at `https://repull.dev/dashboard/billing`. The server-side usage cache is 60s, so the first 200 after an upgrade may take up to a minute. The envelope mirrors `rate_limit_exceeded` for SDK ergonomics: `tier`, `limit`, `active_listings`, `upgrade_url`, plus the standard `code` / `message` / `fix` / `docs_url` / `request_id`.
5
5
 
6
6
  The version of the OpenAPI document: 1.0.0
7
7
  Contact: ivan@vanio.ai
@@ -28,6 +28,8 @@ require 'repull/models/ai_operation_completed_payload'
28
28
  require 'repull/models/ai_operation_failed_event'
29
29
  require 'repull/models/ai_operation_failed_payload'
30
30
  require 'repull/models/ai_operation_failed_payload_error'
31
+ require 'repull/models/airbnb_availability_write_request'
32
+ require 'repull/models/airbnb_calendar_operation'
31
33
  require 'repull/models/airbnb_connection'
32
34
  require 'repull/models/airbnb_connection_accessibility_amenities_inner'
33
35
  require 'repull/models/airbnb_connection_amenities_inner'
@@ -36,13 +38,19 @@ require 'repull/models/airbnb_connection_response'
36
38
  require 'repull/models/airbnb_connection_summary'
37
39
  require 'repull/models/airbnb_data_freshness'
38
40
  require 'repull/models/airbnb_listing'
41
+ require 'repull/models/airbnb_listing_action_request'
39
42
  require 'repull/models/airbnb_listing_list_response'
43
+ require 'repull/models/airbnb_pricing_write_request'
40
44
  require 'repull/models/airbnb_reservation'
41
45
  require 'repull/models/airbnb_reservation_list_response'
42
46
  require 'repull/models/airbnb_review'
43
47
  require 'repull/models/airbnb_review_list_response'
44
48
  require 'repull/models/airbnb_thread'
45
49
  require 'repull/models/airbnb_thread_list_response'
50
+ require 'repull/models/booking_availability_update'
51
+ require 'repull/models/booking_availability_update_request'
52
+ require 'repull/models/booking_availability_update_request_property_id'
53
+ require 'repull/models/booking_availability_update_request_updates_inner'
46
54
  require 'repull/models/booking_connect_listing_option'
47
55
  require 'repull/models/booking_connect_room'
48
56
  require 'repull/models/booking_connect_rooms_response'
@@ -83,20 +91,9 @@ require 'repull/models/conversation_guest_contact'
83
91
  require 'repull/models/conversation_host'
84
92
  require 'repull/models/conversation_list_response'
85
93
  require 'repull/models/conversation_message_attachment'
86
- require 'repull/models/create_ai_operation200_response'
87
94
  require 'repull/models/create_billing_checkout_request'
88
95
  require 'repull/models/create_connect_session_request'
89
96
  require 'repull/models/create_connection_request'
90
- require 'repull/models/create_reservation_request'
91
- require 'repull/models/create_studio_deployment201_response'
92
- require 'repull/models/create_studio_deployment201_response_data'
93
- require 'repull/models/create_studio_deployment_request'
94
- require 'repull/models/create_studio_project201_response'
95
- require 'repull/models/create_studio_project201_response_data'
96
- require 'repull/models/create_studio_project_generation201_response'
97
- require 'repull/models/create_studio_project_generation201_response_data'
98
- require 'repull/models/create_studio_project_generation_request'
99
- require 'repull/models/create_studio_project_request'
100
97
  require 'repull/models/create_webhook_request'
101
98
  require 'repull/models/custom_schema'
102
99
  require 'repull/models/custom_schema_create'
@@ -106,22 +103,10 @@ require 'repull/models/custom_schema_list_response'
106
103
  require 'repull/models/custom_schema_summary'
107
104
  require 'repull/models/custom_schema_update'
108
105
  require 'repull/models/delete_kv200_response'
109
- require 'repull/models/delete_studio_deployment200_response'
110
- require 'repull/models/delete_studio_deployment200_response_data'
111
- require 'repull/models/delete_studio_project200_response'
112
- require 'repull/models/delete_studio_project200_response_data'
113
- require 'repull/models/delete_studio_project_file200_response'
114
- require 'repull/models/delete_studio_project_file200_response_data'
115
106
  require 'repull/models/error'
116
107
  require 'repull/models/error_error'
117
108
  require 'repull/models/error_error_support'
118
- require 'repull/models/generate_studio_completion200_response'
119
- require 'repull/models/generate_studio_completion200_response_data'
120
- require 'repull/models/generate_studio_completion_request'
121
- require 'repull/models/generate_studio_completion_request_project_id'
122
109
  require 'repull/models/get_health200_response'
123
- require 'repull/models/get_studio_deployment200_response'
124
- require 'repull/models/get_studio_project200_response'
125
110
  require 'repull/models/guest'
126
111
  require 'repull/models/guest_contact'
127
112
  require 'repull/models/guest_flag'
@@ -132,10 +117,9 @@ require 'repull/models/guest_reservations_summary'
132
117
  require 'repull/models/list_kv200_response'
133
118
  require 'repull/models/list_kv200_response_data_inner'
134
119
  require 'repull/models/list_kv200_response_pagination'
135
- require 'repull/models/list_studio_deployments200_response'
136
- require 'repull/models/list_studio_project_files200_response'
137
- require 'repull/models/list_studio_projects200_response'
138
120
  require 'repull/models/listing'
121
+ require 'repull/models/listing_active_request'
122
+ require 'repull/models/listing_active_response'
139
123
  require 'repull/models/listing_address'
140
124
  require 'repull/models/listing_amenity'
141
125
  require 'repull/models/listing_channel'
@@ -144,6 +128,15 @@ require 'repull/models/listing_comp_nightly'
144
128
  require 'repull/models/listing_comp_ratings'
145
129
  require 'repull/models/listing_comps_response'
146
130
  require 'repull/models/listing_content'
131
+ require 'repull/models/listing_content_update_request'
132
+ require 'repull/models/listing_content_update_request_address'
133
+ require 'repull/models/listing_content_update_request_amenities'
134
+ require 'repull/models/listing_content_update_request_amenities_one_of_inner'
135
+ require 'repull/models/listing_content_update_request_occupancy'
136
+ require 'repull/models/listing_content_update_request_photos_inner'
137
+ require 'repull/models/listing_content_update_request_photos_inner_one_of'
138
+ require 'repull/models/listing_content_update_request_policies'
139
+ require 'repull/models/listing_content_update_response'
147
140
  require 'repull/models/listing_create_request'
148
141
  require 'repull/models/listing_create_response'
149
142
  require 'repull/models/listing_created_event'
@@ -178,6 +171,8 @@ require 'repull/models/listing_segments_response'
178
171
  require 'repull/models/listing_segments_response_scope'
179
172
  require 'repull/models/listing_updated_event'
180
173
  require 'repull/models/listing_updated_payload'
174
+ require 'repull/models/map_airbnb_listing_request'
175
+ require 'repull/models/map_airbnb_listing_response'
181
176
  require 'repull/models/map_connect_booking_rooms_request'
182
177
  require 'repull/models/map_connect_booking_rooms_response'
183
178
  require 'repull/models/market_browse_category'
@@ -236,6 +231,10 @@ require 'repull/models/review_category'
236
231
  require 'repull/models/review_list_response'
237
232
  require 'repull/models/review_response'
238
233
  require 'repull/models/rotate_webhook_secret200_response'
234
+ require 'repull/models/sandbox_fixture_ref'
235
+ require 'repull/models/sandbox_reset_result'
236
+ require 'repull/models/sandbox_reset_result_deleted'
237
+ require 'repull/models/sandbox_seed_result'
239
238
  require 'repull/models/select_connect_provider_request'
240
239
  require 'repull/models/select_provider_response'
241
240
  require 'repull/models/set_kv_request'
@@ -246,14 +245,8 @@ require 'repull/models/studio_file'
246
245
  require 'repull/models/studio_generation'
247
246
  require 'repull/models/studio_project'
248
247
  require 'repull/models/test_webhook_request'
249
- require 'repull/models/update_availability_request'
250
248
  require 'repull/models/update_listing_pricing_strategy200_response'
251
- require 'repull/models/update_reservation_request'
252
- require 'repull/models/update_studio_project_request'
253
249
  require 'repull/models/update_webhook_request'
254
- require 'repull/models/upsert_studio_project_file200_response'
255
- require 'repull/models/upsert_studio_project_file200_response_data'
256
- require 'repull/models/upsert_studio_project_file_request'
257
250
  require 'repull/models/vrbo_listing'
258
251
  require 'repull/models/vrbo_listing_list_response'
259
252
  require 'repull/models/vrbo_reservation'
@@ -270,10 +263,8 @@ require 'repull/models/webhook_list_response'
270
263
  require 'repull/models/webhook_subscription'
271
264
 
272
265
  # APIs
273
- require 'repull/api/ai_api'
274
266
  require 'repull/api/airbnb_api'
275
267
  require 'repull/api/atlas_api'
276
- require 'repull/api/availability_api'
277
268
  require 'repull/api/billing_api'
278
269
  require 'repull/api/booking_com_api'
279
270
  require 'repull/api/connect_api'
@@ -287,8 +278,8 @@ require 'repull/api/pricing_api'
287
278
  require 'repull/api/properties_api'
288
279
  require 'repull/api/reservations_api'
289
280
  require 'repull/api/reviews_api'
281
+ require 'repull/api/sandbox_api'
290
282
  require 'repull/api/schema_api'
291
- require 'repull/api/studio_api'
292
283
  require 'repull/api/system_api'
293
284
  require 'repull/api/vrbo_api'
294
285
  require 'repull/api/webhooks_api'