repull 0.2.35 → 0.2.37

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/lib/repull/api/connect_api.rb +70 -2
  3. data/lib/repull/api/conversations_api.rb +2 -2
  4. data/lib/repull/api/listings_api.rb +8 -8
  5. data/lib/repull/api/migrate_api.rb +68 -0
  6. data/lib/repull/api/reservations_api.rb +4 -4
  7. data/lib/repull/models/account_disconnected_payload.rb +16 -4
  8. data/lib/repull/models/account_disconnected_payload_listings_inner.rb +157 -0
  9. data/lib/repull/models/airbnb_calendar_operation.rb +12 -12
  10. data/lib/repull/models/booking_unacknowledged_event.rb +281 -0
  11. data/lib/repull/models/booking_unacknowledged_payload.rb +229 -0
  12. data/lib/repull/models/channel_degraded_event.rb +279 -0
  13. data/lib/repull/models/channel_degraded_payload.rb +174 -0
  14. data/lib/repull/models/channel_degraded_payload_object.rb +262 -0
  15. data/lib/repull/models/channel_sync_failed_event.rb +280 -0
  16. data/lib/repull/models/channel_sync_failure_payload.rb +214 -0
  17. data/lib/repull/models/channel_sync_failure_payload_failures_inner.rb +213 -0
  18. data/lib/repull/models/channel_sync_failure_payload_object.rb +289 -0
  19. data/lib/repull/models/charge_per.rb +42 -0
  20. data/lib/repull/models/create_connect_session_request.rb +2 -2
  21. data/lib/repull/models/create_connection_request.rb +1 -1
  22. data/lib/repull/models/import_from_channex200_response.rb +147 -0
  23. data/lib/repull/models/import_from_channex200_response_data.rb +324 -0
  24. data/lib/repull/models/import_from_channex200_response_data_channels_inner.rb +263 -0
  25. data/lib/repull/models/import_from_channex200_response_data_properties_inner.rb +222 -0
  26. data/lib/repull/models/import_from_channex200_response_data_summary.rb +201 -0
  27. data/lib/repull/models/import_from_channex200_response_data_summary_bookings.rb +165 -0
  28. data/lib/repull/models/import_from_channex200_response_data_summary_properties.rb +165 -0
  29. data/lib/repull/models/import_from_channex_request.rb +223 -0
  30. data/lib/repull/models/inquiry_webhook_object.rb +10 -1
  31. data/lib/repull/models/inquiry_webhook_object_guest.rb +159 -0
  32. data/lib/repull/models/list_inquiries200_response_data_inner.rb +27 -1
  33. data/lib/repull/models/list_inquiries200_response_data_inner_guest.rb +160 -0
  34. data/lib/repull/models/listing.rb +82 -1
  35. data/lib/repull/models/listing_channel.rb +15 -4
  36. data/lib/repull/models/listing_content_photo.rb +206 -0
  37. data/lib/repull/models/listing_fee.rb +229 -0
  38. data/lib/repull/models/listing_policies.rb +257 -0
  39. data/lib/repull/models/listing_policies_check_in.rb +179 -0
  40. data/lib/repull/models/listing_policies_check_out.rb +148 -0
  41. data/lib/repull/models/listing_policies_quiet_hours.rb +156 -0
  42. data/lib/repull/models/listing_pricing_settings.rb +233 -0
  43. data/lib/repull/models/listing_room.rb +190 -0
  44. data/lib/repull/models/listing_room_beds_inner.rb +156 -0
  45. data/lib/repull/models/listing_rules.rb +212 -0
  46. data/lib/repull/models/listing_tax.rb +241 -0
  47. data/lib/repull/models/listing_webhook_object_channels_inner.rb +16 -5
  48. data/lib/repull/models/reservation.rb +25 -1
  49. data/lib/repull/models/reservation_access_code.rb +301 -0
  50. data/lib/repull/models/reservation_access_code_locks_inner.rb +190 -0
  51. data/lib/repull/models/reservation_thread_assigned_event.rb +279 -0
  52. data/lib/repull/models/reservation_thread_assigned_payload.rb +174 -0
  53. data/lib/repull/models/reservation_thread_assigned_payload_object.rb +249 -0
  54. data/lib/repull/models/submit_ciirus_credentials200_response.rb +213 -0
  55. data/lib/repull/models/submit_ciirus_credentials200_response_account_info.rb +159 -0
  56. data/lib/repull/models/submit_ciirus_credentials_request.rb +184 -0
  57. data/lib/repull/models/submit_ciirus_credentials_request_credentials.rb +203 -0
  58. data/lib/repull/models/webhook_event.rb +8 -0
  59. data/lib/repull/models/webhook_event_type.rb +5 -1
  60. data/lib/repull/version.rb +1 -1
  61. data/lib/repull.rb +41 -0
  62. data/openapi/v1.json +1937 -32
  63. data/scripts/regen.sh +1 -1
  64. metadata +43 -4
  65. data/spec/api/plumguide_api_spec.rb +0 -85
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3dd1b14c70b71a270a2738f370441e46162ee0810eaa4ea90df885938bc6ff4f
4
- data.tar.gz: 86146a261bcd64bf93ded286fd2f9d10d0515713b6eb2c6ba0c8419cf498b0bb
3
+ metadata.gz: dd95b6f41fc43994008cdf19153e5d46dc2344917765a9f347515aa6621c89d3
4
+ data.tar.gz: c3b6e119eabe3edeabe2e47193ab20451b6e8d6c2fe260c27ae1289d3a1c660d
5
5
  SHA512:
6
- metadata.gz: '093ca68ae94804a08972248fefaa9138cee9d8032cc6f9b09bd0b8b649fbb406577e439b93b07283d4b8c27db71554c1ee5acd2a3325bd9a4d12d0df7f70dd9c'
7
- data.tar.gz: 9681728ae90f98c2effa583ba82a9925b920dcdfcca0e2f0daae376f0468256beacdc56806c4bdb0c5503a195bca732ff33d853e045a0ad29959473bebfb3d8e
6
+ metadata.gz: c16c5c6feb701118133399a5c88ab107ad464f0493c2d913f8c7159874af9cebd2a40bbaa3355e07ce138aab1f7c5fdc666b1c6d2d61b1e1634c4298243a87f5
7
+ data.tar.gz: bd9b01e452b8264001d5ab150d686cf04bca97ef111f95821f9863fe355d6f1667dd1355abcc28a48cc7545dca01a439867a4dd871137b48fa4bd3ccf13fdffb
@@ -226,7 +226,7 @@ module Repull
226
226
  end
227
227
 
228
228
  # Disconnect provider
229
- # Disconnect ONE connected account of a provider from this workspace. Supported for `airbnb` and `booking`. **Which account.** Pass `accountId` — for Airbnb the host id (`accounts[].externalAccountId` from `GET /v1/connect/airbnb`), for Booking.com the hotel id. It is optional only when the workspace has exactly one account for the provider. With several and no `accountId`, the call returns `422` with the account ids in `valid_values` instead of guessing. An `accountId` that is not connected to this workspace returns `404`. Disconnecting one account leaves the others connected. **What happens.** The account's stored authorization is removed and it stops syncing. Its listings are **deactivated**, not deleted: they stop counting toward your plan's listing limit, their data is kept, and they are returned in `listingsDeactivated`. A listing that is still connected through another account or channel stays active. Reconnect the account, then activate the listings with `POST /v1/listings/status`. The change is all or nothing. For Airbnb, the host can also revoke access on Airbnb's side (Account → Privacy & sharing → Connected apps); that alone does not update this workspace, so call this endpoint as well. Other providers return `501 not_implemented` with instructions for disconnecting on the provider's side. That answer depends only on the provider, not on your workspace: an unsupported provider returns `501` whether or not you have a connection to it. `404 not_found` on a supported provider means this workspace has no connection to it (or, with `accountId`, that the account is not connected here).
229
+ # Disconnect ONE connected account of a provider from this workspace. Supported for `airbnb`, `booking`, `vrbo-login` and every PMS (`guesty`, `hostaway`, `hospitable`, …). **Which account.** Pass `accountId` — for Airbnb the host id (`accounts[].externalAccountId` from `GET /v1/connect/airbnb`), for Booking.com the hotel id, for `vrbo-login` the sign-in's `accounts[].externalAccountId` from `GET /v1/connect/vrbo-login`. It is optional only when the workspace has exactly one account for the provider. With several and no `accountId`, the call returns `422` with the account ids in `valid_values` instead of guessing. An `accountId` that is not connected to this workspace returns `404`. Disconnecting one account leaves the others connected. **What happens.** The account's stored authorization is removed and it stops syncing. Its listings are **deactivated**, not deleted: they stop counting toward your plan's listing limit, their data is kept, and they are returned in `listingsDeactivated`. A listing that is still connected through another account or channel stays active. Reconnect the account, then activate the listings with `POST /v1/listings/status`. The change is all or nothing. For Airbnb, the host can also revoke access on Airbnb's side (Account → Privacy & sharing → Connected apps); that alone does not update this workspace, so call this endpoint as well. **PMS.** A workspace has one connection per PMS, so no `accountId` is needed. Disconnecting stops syncing, clears the stored credentials and deactivates the connection's listings; nothing is deleted, and reservations and messages stay. The response also carries `connectionId`. The PMS's own webhook subscription is left in place, because the same PMS account can be connected to another workspace (such as a Repull Migrate workspace). Reconnect with a new Connect session. Other providers return `501 not_implemented` with instructions for disconnecting on the provider's side. That answer depends only on the provider, not on your workspace: an unsupported provider returns `501` whether or not you have a connection to it. `404 not_found` on a supported provider means this workspace has no connection to it (or, with `accountId`, that the account is not connected here).
230
230
  # @param provider [String] PMS provider slug (e.g., hostaway, guesty, ownerrez)
231
231
  # @param [Hash] opts the optional parameters
232
232
  # @option opts [String] :account_id The account to disconnect: the Airbnb host id (`accounts[].externalAccountId` on `GET /v1/connect/airbnb`) or the Booking.com hotel id. Required when the workspace has more than one connected account for the provider. Not the same as the `X-Account-Id` header.
@@ -237,7 +237,7 @@ module Repull
237
237
  end
238
238
 
239
239
  # Disconnect provider
240
- # Disconnect ONE connected account of a provider from this workspace. Supported for `airbnb` and `booking`. **Which account.** Pass `accountId` — for Airbnb the host id (`accounts[].externalAccountId` from `GET /v1/connect/airbnb`), for Booking.com the hotel id. It is optional only when the workspace has exactly one account for the provider. With several and no `accountId`, the call returns `422` with the account ids in `valid_values` instead of guessing. An `accountId` that is not connected to this workspace returns `404`. Disconnecting one account leaves the others connected. **What happens.** The account's stored authorization is removed and it stops syncing. Its listings are **deactivated**, not deleted: they stop counting toward your plan's listing limit, their data is kept, and they are returned in `listingsDeactivated`. A listing that is still connected through another account or channel stays active. Reconnect the account, then activate the listings with `POST /v1/listings/status`. The change is all or nothing. For Airbnb, the host can also revoke access on Airbnb's side (Account → Privacy & sharing → Connected apps); that alone does not update this workspace, so call this endpoint as well. Other providers return `501 not_implemented` with instructions for disconnecting on the provider's side. That answer depends only on the provider, not on your workspace: an unsupported provider returns `501` whether or not you have a connection to it. `404 not_found` on a supported provider means this workspace has no connection to it (or, with `accountId`, that the account is not connected here).
240
+ # Disconnect ONE connected account of a provider from this workspace. Supported for `airbnb`, `booking`, `vrbo-login` and every PMS (`guesty`, `hostaway`, `hospitable`, …). **Which account.** Pass `accountId` — for Airbnb the host id (`accounts[].externalAccountId` from `GET /v1/connect/airbnb`), for Booking.com the hotel id, for `vrbo-login` the sign-in's `accounts[].externalAccountId` from `GET /v1/connect/vrbo-login`. It is optional only when the workspace has exactly one account for the provider. With several and no `accountId`, the call returns `422` with the account ids in `valid_values` instead of guessing. An `accountId` that is not connected to this workspace returns `404`. Disconnecting one account leaves the others connected. **What happens.** The account's stored authorization is removed and it stops syncing. Its listings are **deactivated**, not deleted: they stop counting toward your plan's listing limit, their data is kept, and they are returned in `listingsDeactivated`. A listing that is still connected through another account or channel stays active. Reconnect the account, then activate the listings with `POST /v1/listings/status`. The change is all or nothing. For Airbnb, the host can also revoke access on Airbnb's side (Account → Privacy & sharing → Connected apps); that alone does not update this workspace, so call this endpoint as well. **PMS.** A workspace has one connection per PMS, so no `accountId` is needed. Disconnecting stops syncing, clears the stored credentials and deactivates the connection's listings; nothing is deleted, and reservations and messages stay. The response also carries `connectionId`. The PMS's own webhook subscription is left in place, because the same PMS account can be connected to another workspace (such as a Repull Migrate workspace). Reconnect with a new Connect session. Other providers return `501 not_implemented` with instructions for disconnecting on the provider's side. That answer depends only on the provider, not on your workspace: an unsupported provider returns `501` whether or not you have a connection to it. `404 not_found` on a supported provider means this workspace has no connection to it (or, with `accountId`, that the account is not connected here).
241
241
  # @param provider [String] PMS provider slug (e.g., hostaway, guesty, ownerrez)
242
242
  # @param [Hash] opts the optional parameters
243
243
  # @option opts [String] :account_id The account to disconnect: the Airbnb host id (`accounts[].externalAccountId` on `GET /v1/connect/airbnb`) or the Booking.com hotel id. Required when the workspace has more than one connected account for the provider. Not the same as the `X-Account-Id` header.
@@ -1488,6 +1488,74 @@ module Repull
1488
1488
  return data, status_code, headers
1489
1489
  end
1490
1490
 
1491
+ # Submit CiiRUS credentials for a Connect session
1492
+ # Completes a credentials-pattern connection for CiiRUS with the property manager's CiiRUS API username and password. **What syncs.** Units become listings (with descriptions, photos, amenities, rooms and house rules); reservations (with their charge and tax breakdown and payments) and reviews are imported, then polled for changes. Bookings can be created, quoted, changed and cancelled in CiiRUS — see `capabilities.reservations` on `GET /v1/connect/ciirus`. Guest messages are not available through CiiRUS's API. **Where the credentials come from.** The CiiRUS API Explorer gives the API username and password after signing in with the CiiRUS MC username and company password; CiiRUS support can also issue them. Credentials that see several suppliers (management companies) also need `managementCompanyUserId`. **IP whitelist.** CiiRUS only accepts calls from whitelisted IP addresses, and answers a wrong password and a non-whitelisted address the same way. When this returns `invalid_credentials` with correct credentials, ask CiiRUS support to whitelist Repull for the API user. The credentials are validated against CiiRUS before anything is stored, so invalid ones return `invalid_credentials` rather than creating a dead connection. On success only the credential fields below are stored, and the first sync of listings and reservations is queued. CiiRUS has no webhooks: after the first sync, reservation changes are picked up by polling about once a minute. Reconnecting replaces the stored credentials on the workspace's existing CiiRUS connection — the `pmsConnectionId` stays the same. No API key required when called with a `sessionId` — the session is the capability token.
1493
+ # @param submit_ciirus_credentials_request [SubmitCiirusCredentialsRequest]
1494
+ # @param [Hash] opts the optional parameters
1495
+ # @return [SubmitCiirusCredentials200Response]
1496
+ def submit_ciirus_credentials(submit_ciirus_credentials_request, opts = {})
1497
+ data, _status_code, _headers = submit_ciirus_credentials_with_http_info(submit_ciirus_credentials_request, opts)
1498
+ data
1499
+ end
1500
+
1501
+ # Submit CiiRUS credentials for a Connect session
1502
+ # Completes a credentials-pattern connection for CiiRUS with the property manager's CiiRUS API username and password. **What syncs.** Units become listings (with descriptions, photos, amenities, rooms and house rules); reservations (with their charge and tax breakdown and payments) and reviews are imported, then polled for changes. Bookings can be created, quoted, changed and cancelled in CiiRUS — see `capabilities.reservations` on `GET /v1/connect/ciirus`. Guest messages are not available through CiiRUS's API. **Where the credentials come from.** The CiiRUS API Explorer gives the API username and password after signing in with the CiiRUS MC username and company password; CiiRUS support can also issue them. Credentials that see several suppliers (management companies) also need `managementCompanyUserId`. **IP whitelist.** CiiRUS only accepts calls from whitelisted IP addresses, and answers a wrong password and a non-whitelisted address the same way. When this returns `invalid_credentials` with correct credentials, ask CiiRUS support to whitelist Repull for the API user. The credentials are validated against CiiRUS before anything is stored, so invalid ones return `invalid_credentials` rather than creating a dead connection. On success only the credential fields below are stored, and the first sync of listings and reservations is queued. CiiRUS has no webhooks: after the first sync, reservation changes are picked up by polling about once a minute. Reconnecting replaces the stored credentials on the workspace's existing CiiRUS connection — the `pmsConnectionId` stays the same. No API key required when called with a `sessionId` — the session is the capability token.
1503
+ # @param submit_ciirus_credentials_request [SubmitCiirusCredentialsRequest]
1504
+ # @param [Hash] opts the optional parameters
1505
+ # @return [Array<(SubmitCiirusCredentials200Response, Integer, Hash)>] SubmitCiirusCredentials200Response data, response status code and response headers
1506
+ def submit_ciirus_credentials_with_http_info(submit_ciirus_credentials_request, opts = {})
1507
+ if @api_client.config.debugging
1508
+ @api_client.config.logger.debug 'Calling API: ConnectApi.submit_ciirus_credentials ...'
1509
+ end
1510
+ # verify the required parameter 'submit_ciirus_credentials_request' is set
1511
+ if @api_client.config.client_side_validation && submit_ciirus_credentials_request.nil?
1512
+ fail ArgumentError, "Missing the required parameter 'submit_ciirus_credentials_request' when calling ConnectApi.submit_ciirus_credentials"
1513
+ end
1514
+ # resource path
1515
+ local_var_path = '/v1/connect/ciirus/credentials'
1516
+
1517
+ # query parameters
1518
+ query_params = opts[:query_params] || {}
1519
+
1520
+ # header parameters
1521
+ header_params = opts[:header_params] || {}
1522
+ # HTTP header 'Accept' (if needed)
1523
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
1524
+ # HTTP header 'Content-Type'
1525
+ content_type = @api_client.select_header_content_type(['application/json'])
1526
+ if !content_type.nil?
1527
+ header_params['Content-Type'] = content_type
1528
+ end
1529
+
1530
+ # form parameters
1531
+ form_params = opts[:form_params] || {}
1532
+
1533
+ # http body (model)
1534
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(submit_ciirus_credentials_request)
1535
+
1536
+ # return_type
1537
+ return_type = opts[:debug_return_type] || 'SubmitCiirusCredentials200Response'
1538
+
1539
+ # auth_names
1540
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
1541
+
1542
+ new_options = opts.merge(
1543
+ :operation => :"ConnectApi.submit_ciirus_credentials",
1544
+ :header_params => header_params,
1545
+ :query_params => query_params,
1546
+ :form_params => form_params,
1547
+ :body => post_body,
1548
+ :auth_names => auth_names,
1549
+ :return_type => return_type
1550
+ )
1551
+
1552
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
1553
+ if @api_client.config.debugging
1554
+ @api_client.config.logger.debug "API called: ConnectApi#submit_ciirus_credentials\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
1555
+ end
1556
+ return data, status_code, headers
1557
+ end
1558
+
1491
1559
  # Submit Cloudbeds credentials for a Connect session
1492
1560
  # Completes a credentials-pattern connection for Cloudbeds with a property (or organization) API key, created in Cloudbeds under Apps & Marketplace → API Credentials. In Cloudbeds a listing is a room type and its rooms are units. A booking with several rooms becomes one reservation per room. The key is validated and the properties it can see are read before anything is stored. On success Repull subscribes to the property's Cloudbeds webhooks (reservations, guests, room blocks) and queues the first sync. Cloudbeds keys expire if unused for 30 days; the connection's regular sync keeps them alive. No API key required when called with a `sessionId` — the session is the capability token.
1493
1561
  # @param submit_cloudbeds_credentials_request [SubmitCloudbedsCredentialsRequest]
@@ -101,7 +101,7 @@ module Repull
101
101
  end
102
102
 
103
103
  # Get conversation detail
104
- # Returns one thread (the same shape as the list-row `Conversation`) plus expanded `host` (from `airbnb_hosts` for the thread's `host_id`) and `guest` (resolved via the thread's `reservation_id`, with up to 50 contacts) blocks. A conversation that belongs to an inactive listing (by the thread's listing or its reservation's listing) returns `403 listing_inactive`. Inactive listings keep syncing; activate the listing to use it here.
104
+ # Returns one thread (the same shape as the list-row `Conversation`) plus expanded `host` (from `airbnb_hosts` for the thread's `host_id`) and `guest` (resolved via the thread's `reservation_id`, with up to 50 contacts) blocks. On an inquiry (no reservation yet) `guest` carries the first name Airbnb shares with the inquiry; contacts such as the phone number arrive once the guest books. A conversation that belongs to an inactive listing (by the thread's listing or its reservation's listing) returns `403 listing_inactive`. Inactive listings keep syncing; activate the listing to use it here.
105
105
  # @param id [Integer] Internal Repull thread id.
106
106
  # @param [Hash] opts the optional parameters
107
107
  # @option opts [String] :x_schema Apply a custom or built-in schema to transform the response. Built-in: &#x60;native&#x60; (default), &#x60;calry&#x60;, &#x60;calry-v1&#x60;. Custom: any schema name created via &#x60;POST /v1/schema/custom&#x60;. Unknown / inactive schema names fall back to &#x60;native&#x60;.
@@ -112,7 +112,7 @@ module Repull
112
112
  end
113
113
 
114
114
  # Get conversation detail
115
- # Returns one thread (the same shape as the list-row &#x60;Conversation&#x60;) plus expanded &#x60;host&#x60; (from &#x60;airbnb_hosts&#x60; for the thread&#39;s &#x60;host_id&#x60;) and &#x60;guest&#x60; (resolved via the thread&#39;s &#x60;reservation_id&#x60;, with up to 50 contacts) blocks. A conversation that belongs to an inactive listing (by the thread&#39;s listing or its reservation&#39;s listing) returns &#x60;403 listing_inactive&#x60;. Inactive listings keep syncing; activate the listing to use it here.
115
+ # Returns one thread (the same shape as the list-row &#x60;Conversation&#x60;) plus expanded &#x60;host&#x60; (from &#x60;airbnb_hosts&#x60; for the thread&#39;s &#x60;host_id&#x60;) and &#x60;guest&#x60; (resolved via the thread&#39;s &#x60;reservation_id&#x60;, with up to 50 contacts) blocks. On an inquiry (no reservation yet) &#x60;guest&#x60; carries the first name Airbnb shares with the inquiry; contacts such as the phone number arrive once the guest books. A conversation that belongs to an inactive listing (by the thread&#39;s listing or its reservation&#39;s listing) returns &#x60;403 listing_inactive&#x60;. Inactive listings keep syncing; activate the listing to use it here.
116
116
  # @param id [Integer] Internal Repull thread id.
117
117
  # @param [Hash] opts the optional parameters
118
118
  # @option opts [String] :x_schema Apply a custom or built-in schema to transform the response. Built-in: &#x60;native&#x60; (default), &#x60;calry&#x60;, &#x60;calry-v1&#x60;. Custom: any schema name created via &#x60;POST /v1/schema/custom&#x60;. Unknown / inactive schema names fall back to &#x60;native&#x60;.
@@ -369,11 +369,11 @@ module Repull
369
369
  end
370
370
 
371
371
  # Get a listing
372
- # Fetch a single listing by id. Returns the same shape as one element of the `GET /v1/listings` response, so you can bind the result to the same model. Cross-tenant access (a listing that belongs to a different workspace) returns 404 — never 403, never reveals the listing's existence. **Optional expansions:** Pass `?include=amenities` to enrich the response with the listing's amenity rows (`[]` when the listing has none). Pass `?include=content` for the rich content slab (summary, description, space, house rules, etc. — sourced from `listings_descriptions` for the `en` locale; `null` when no row is stored). Pass `?include=details` for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.; `null` when no row is stored). Combine comma-separated, e.g. `?include=amenities,content,details`. The default response stays lean; consumers must opt in. Returns `403 listing_inactive` when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
372
+ # Fetch a single listing by id. Returns the same shape as one element of the `GET /v1/listings` response, so you can bind the result to the same model. Cross-tenant access (a listing that belongs to a different workspace) returns 404 — never 403, never reveals the listing's existence. **Optional expansions:** Pass `?include=amenities` to enrich the response with the listing's amenity rows (`[]` when the listing has none). Pass `?include=content` for the rich content slab (summary, description, space, house rules, etc. — sourced from `listings_descriptions` for the `en` locale; `null` when no row is stored). Pass `?include=details` for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.; `null` when no row is stored). Pass `?include=rooms` for rooms and beds, `policies` for cancellation, house rules, check-in/out and guest rules, `rules` for stay rules (min/max nights, booking window, notice, preparation time), `pricing` for standing prices and discounts, `fees` and `taxes` for every fee and tax in one shape whatever channel or PMS the listing comes from, and `photos`. Combine comma-separated, e.g. `?include=content,details,rooms,policies,pricing,fees,taxes`. The default response stays lean; consumers must opt in. Returns `403 listing_inactive` when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
373
373
  # @param id [Integer] Repull listing id
374
374
  # @param [Hash] opts the optional parameters
375
375
  # @option opts [String] :x_schema Apply a custom or built-in schema to transform the response. Built-in: &#x60;native&#x60; (default), &#x60;calry&#x60;, &#x60;calry-v1&#x60;. Custom: any schema name created via &#x60;POST /v1/schema/custom&#x60;. Unknown / inactive schema names fall back to &#x60;native&#x60;.
376
- # @option opts [String] :include Comma-separated optional expansions. Currently supported: &#x60;amenities&#x60;, &#x60;content&#x60;, &#x60;details&#x60;. Unknown values return 422 with a &#x60;valid_values&#x60; envelope.
376
+ # @option opts [String] :include Comma-separated optional expansions. Currently supported: &#x60;amenities&#x60;, &#x60;content&#x60;, &#x60;details&#x60;, &#x60;rooms&#x60;, &#x60;policies&#x60;, &#x60;rules&#x60;, &#x60;pricing&#x60;, &#x60;fees&#x60;, &#x60;taxes&#x60;, &#x60;photos&#x60;. Unknown values return 422 with a &#x60;valid_values&#x60; envelope.
377
377
  # @return [Listing]
378
378
  def get_listing(id, opts = {})
379
379
  data, _status_code, _headers = get_listing_with_http_info(id, opts)
@@ -381,11 +381,11 @@ module Repull
381
381
  end
382
382
 
383
383
  # Get a listing
384
- # Fetch a single listing by id. Returns the same shape as one element of the &#x60;GET /v1/listings&#x60; response, so you can bind the result to the same model. Cross-tenant access (a listing that belongs to a different workspace) returns 404 — never 403, never reveals the listing&#39;s existence. **Optional expansions:** Pass &#x60;?include&#x3D;amenities&#x60; to enrich the response with the listing&#39;s amenity rows (&#x60;[]&#x60; when the listing has none). Pass &#x60;?include&#x3D;content&#x60; for the rich content slab (summary, description, space, house rules, etc. — sourced from &#x60;listings_descriptions&#x60; for the &#x60;en&#x60; locale; &#x60;null&#x60; when no row is stored). Pass &#x60;?include&#x3D;details&#x60; for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.; &#x60;null&#x60; when no row is stored). Combine comma-separated, e.g. &#x60;?include&#x3D;amenities,content,details&#x60;. The default response stays lean; consumers must opt in. Returns &#x60;403 listing_inactive&#x60; when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
384
+ # Fetch a single listing by id. Returns the same shape as one element of the &#x60;GET /v1/listings&#x60; response, so you can bind the result to the same model. Cross-tenant access (a listing that belongs to a different workspace) returns 404 — never 403, never reveals the listing&#39;s existence. **Optional expansions:** Pass &#x60;?include&#x3D;amenities&#x60; to enrich the response with the listing&#39;s amenity rows (&#x60;[]&#x60; when the listing has none). Pass &#x60;?include&#x3D;content&#x60; for the rich content slab (summary, description, space, house rules, etc. — sourced from &#x60;listings_descriptions&#x60; for the &#x60;en&#x60; locale; &#x60;null&#x60; when no row is stored). Pass &#x60;?include&#x3D;details&#x60; for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.; &#x60;null&#x60; when no row is stored). Pass &#x60;?include&#x3D;rooms&#x60; for rooms and beds, &#x60;policies&#x60; for cancellation, house rules, check-in/out and guest rules, &#x60;rules&#x60; for stay rules (min/max nights, booking window, notice, preparation time), &#x60;pricing&#x60; for standing prices and discounts, &#x60;fees&#x60; and &#x60;taxes&#x60; for every fee and tax in one shape whatever channel or PMS the listing comes from, and &#x60;photos&#x60;. Combine comma-separated, e.g. &#x60;?include&#x3D;content,details,rooms,policies,pricing,fees,taxes&#x60;. The default response stays lean; consumers must opt in. Returns &#x60;403 listing_inactive&#x60; when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
385
385
  # @param id [Integer] Repull listing id
386
386
  # @param [Hash] opts the optional parameters
387
387
  # @option opts [String] :x_schema Apply a custom or built-in schema to transform the response. Built-in: &#x60;native&#x60; (default), &#x60;calry&#x60;, &#x60;calry-v1&#x60;. Custom: any schema name created via &#x60;POST /v1/schema/custom&#x60;. Unknown / inactive schema names fall back to &#x60;native&#x60;.
388
- # @option opts [String] :include Comma-separated optional expansions. Currently supported: &#x60;amenities&#x60;, &#x60;content&#x60;, &#x60;details&#x60;. Unknown values return 422 with a &#x60;valid_values&#x60; envelope.
388
+ # @option opts [String] :include Comma-separated optional expansions. Currently supported: &#x60;amenities&#x60;, &#x60;content&#x60;, &#x60;details&#x60;, &#x60;rooms&#x60;, &#x60;policies&#x60;, &#x60;rules&#x60;, &#x60;pricing&#x60;, &#x60;fees&#x60;, &#x60;taxes&#x60;, &#x60;photos&#x60;. Unknown values return 422 with a &#x60;valid_values&#x60; envelope.
389
389
  # @return [Array<(Listing, Integer, Hash)>] Listing data, response status code and response headers
390
390
  def get_listing_with_http_info(id, opts = {})
391
391
  if @api_client.config.debugging
@@ -753,7 +753,7 @@ module Repull
753
753
  end
754
754
 
755
755
  # List listings
756
- # Cursor-paginated list of listings owned by the authenticated workspace. Use `pagination.nextCursor` from one response as the `cursor` query param of the next request to walk the full set. `?offset=` is also accepted as a first-class alias for shallow paging (0..10000) — see the `offset` parameter below. Mutually exclusive with `cursor`. Filters: `q` (substring on name/street/city), `status`, `channel`. **Optional expansions:** Pass `?include=content` to enrich each row with the rich content slab (summary, description, space, house rules, etc. — sourced from `listings_descriptions` for the `en` locale). Pass `?include=details` for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.). Both default to `null` per row when the underlying `listings_descriptions` / `listings_details` row is missing — distinct from the field being absent (which signals the expansion was not requested). Pass `?include=thumbnail` to guarantee `thumbnailUrl` on every returned row — including the reduced inactive ones. Combine comma-separated, e.g. `?include=content,thumbnail`. The default response stays lean; consumers must opt in. **Inactive listings:** by default only active listings are returned. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated, so when `status` asks for inactive ones they carry only `id`, `name`, `status` and `channels` — enough to choose what to activate with `PATCH /v1/listings/{id}`. The `content` and `details` expansions are not applied to them. `?include=thumbnail` is the one exception: it adds `thumbnailUrl` to an inactive row so a single request can render an active/inactive selection screen with pictures, instead of one follow-up call per listing (which an inactive listing would answer with `403 listing_inactive` anyway).
756
+ # Cursor-paginated list of listings owned by the authenticated workspace. Use `pagination.nextCursor` from one response as the `cursor` query param of the next request to walk the full set. `?offset=` is also accepted as a first-class alias for shallow paging (0..10000) — see the `offset` parameter below. Mutually exclusive with `cursor`. Filters: `q` (substring on name/street/city), `status`, `channel`. **Optional expansions:** Pass `?include=content` to enrich each row with the rich content slab (summary, description, space, house rules, etc. — sourced from `listings_descriptions` for the `en` locale). Pass `?include=details` for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.). Both default to `null` per row when the underlying `listings_descriptions` / `listings_details` row is missing — distinct from the field being absent (which signals the expansion was not requested). Pass `?include=thumbnail` to guarantee `thumbnailUrl` on every returned row — including the reduced inactive ones. Pass `rooms`, `policies`, `rules`, `pricing`, `fees`, `taxes` or `photos` for the same sections as `GET /v1/listings/{id}`, loaded for the whole page in one go. Combine comma-separated, e.g. `?include=content,thumbnail`. The default response stays lean; consumers must opt in. **Inactive listings:** by default only active listings are returned. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated, so when `status` asks for inactive ones they carry only `id`, `name`, `status` and `channels` — enough to choose what to activate with `PATCH /v1/listings/{id}`. The `content` and `details` expansions are not applied to them. `?include=thumbnail` is the one exception: it adds `thumbnailUrl` to an inactive row so a single request can render an active/inactive selection screen with pictures, instead of one follow-up call per listing (which an inactive listing would answer with `403 listing_inactive` anyway).
757
757
  # @param [Hash] opts the optional parameters
758
758
  # @option opts [String] :x_schema Apply a custom or built-in schema to transform the response. Built-in: &#x60;native&#x60; (default), &#x60;calry&#x60;, &#x60;calry-v1&#x60;. Custom: any schema name created via &#x60;POST /v1/schema/custom&#x60;. Unknown / inactive schema names fall back to &#x60;native&#x60;.
759
759
  # @option opts [String] :cursor Opaque cursor returned in the previous response&#39;s &#x60;pagination.nextCursor&#x60;. Omit to fetch the first page.
@@ -762,7 +762,7 @@ module Repull
762
762
  # @option opts [String] :q Case-insensitive substring search on name, street, or city.
763
763
  # @option opts [String] :status Filter by listing status. Defaults to &#x60;active&#x60;. Pass &#x60;inactive&#x60; to list the listings you can activate, &#x60;archived&#x60; for archived ones, or &#x60;all&#x60; for every status. Inactive listings are returned with identity fields only — &#x60;id&#x60;, &#x60;name&#x60;, &#x60;status&#x60;, &#x60;inactiveReason&#x60; (&#x60;plan_limit&#x60;, &#x60;unlisted_on_airbnb&#x60; or &#x60;deactivated&#x60;), &#x60;address.city&#x60; and &#x60;channels&#x60; — and never with the street, &#x60;content&#x60; or &#x60;details&#x60;; activate one to see the rest. The only field you can add to an inactive row is &#x60;thumbnailUrl&#x60;, via &#x60;?include&#x3D;thumbnail&#x60;. (default to 'active')
764
764
  # @option opts [String] :channel Restrict to listings published on the given channel (&#x60;airbnb&#x60;, &#x60;booking&#x60;, &#x60;vrbo&#x60;, etc.). Joins through &#x60;listing_platform_links&#x60; and matches active links only.
765
- # @option opts [String] :include Comma-separated optional expansions. Currently supported: &#x60;content&#x60;, &#x60;details&#x60;, &#x60;thumbnail&#x60;. &#x60;thumbnail&#x60; guarantees &#x60;thumbnailUrl&#x60; on every row and is the only expansion that applies to inactive listings. Unknown values return 422 with a &#x60;valid_values&#x60; envelope. (Note: &#x60;amenities&#x60; is not yet supported on the list endpoint — use the detail endpoint to fetch amenity rows for a single listing.)
765
+ # @option opts [String] :include Comma-separated optional expansions. Currently supported: &#x60;content&#x60;, &#x60;details&#x60;, &#x60;thumbnail&#x60;, &#x60;rooms&#x60;, &#x60;policies&#x60;, &#x60;rules&#x60;, &#x60;pricing&#x60;, &#x60;fees&#x60;, &#x60;taxes&#x60;, &#x60;photos&#x60; (the last seven are described on &#x60;GET /v1/listings/{id}&#x60;; read for the whole page at once). &#x60;thumbnail&#x60; guarantees &#x60;thumbnailUrl&#x60; on every row and is the only expansion that applies to inactive listings. Unknown values return 422 with a &#x60;valid_values&#x60; envelope. (Note: &#x60;amenities&#x60; is not yet supported on the list endpoint — use the detail endpoint to fetch amenity rows for a single listing.)
766
766
  # @return [ListingListResponse]
767
767
  def list_listings(opts = {})
768
768
  data, _status_code, _headers = list_listings_with_http_info(opts)
@@ -770,7 +770,7 @@ module Repull
770
770
  end
771
771
 
772
772
  # List listings
773
- # Cursor-paginated list of listings owned by the authenticated workspace. Use &#x60;pagination.nextCursor&#x60; from one response as the &#x60;cursor&#x60; query param of the next request to walk the full set. &#x60;?offset&#x3D;&#x60; is also accepted as a first-class alias for shallow paging (0..10000) — see the &#x60;offset&#x60; parameter below. Mutually exclusive with &#x60;cursor&#x60;. Filters: &#x60;q&#x60; (substring on name/street/city), &#x60;status&#x60;, &#x60;channel&#x60;. **Optional expansions:** Pass &#x60;?include&#x3D;content&#x60; to enrich each row with the rich content slab (summary, description, space, house rules, etc. — sourced from &#x60;listings_descriptions&#x60; for the &#x60;en&#x60; locale). Pass &#x60;?include&#x3D;details&#x60; for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.). Both default to &#x60;null&#x60; per row when the underlying &#x60;listings_descriptions&#x60; / &#x60;listings_details&#x60; row is missing — distinct from the field being absent (which signals the expansion was not requested). Pass &#x60;?include&#x3D;thumbnail&#x60; to guarantee &#x60;thumbnailUrl&#x60; on every returned row — including the reduced inactive ones. Combine comma-separated, e.g. &#x60;?include&#x3D;content,thumbnail&#x60;. The default response stays lean; consumers must opt in. **Inactive listings:** by default only active listings are returned. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated, so when &#x60;status&#x60; asks for inactive ones they carry only &#x60;id&#x60;, &#x60;name&#x60;, &#x60;status&#x60; and &#x60;channels&#x60; — enough to choose what to activate with &#x60;PATCH /v1/listings/{id}&#x60;. The &#x60;content&#x60; and &#x60;details&#x60; expansions are not applied to them. &#x60;?include&#x3D;thumbnail&#x60; is the one exception: it adds &#x60;thumbnailUrl&#x60; to an inactive row so a single request can render an active/inactive selection screen with pictures, instead of one follow-up call per listing (which an inactive listing would answer with &#x60;403 listing_inactive&#x60; anyway).
773
+ # Cursor-paginated list of listings owned by the authenticated workspace. Use &#x60;pagination.nextCursor&#x60; from one response as the &#x60;cursor&#x60; query param of the next request to walk the full set. &#x60;?offset&#x3D;&#x60; is also accepted as a first-class alias for shallow paging (0..10000) — see the &#x60;offset&#x60; parameter below. Mutually exclusive with &#x60;cursor&#x60;. Filters: &#x60;q&#x60; (substring on name/street/city), &#x60;status&#x60;, &#x60;channel&#x60;. **Optional expansions:** Pass &#x60;?include&#x3D;content&#x60; to enrich each row with the rich content slab (summary, description, space, house rules, etc. — sourced from &#x60;listings_descriptions&#x60; for the &#x60;en&#x60; locale). Pass &#x60;?include&#x3D;details&#x60; for the structural slab (bedrooms, bathrooms, person capacity, check-in window, wifi, house manual, etc.). Both default to &#x60;null&#x60; per row when the underlying &#x60;listings_descriptions&#x60; / &#x60;listings_details&#x60; row is missing — distinct from the field being absent (which signals the expansion was not requested). Pass &#x60;?include&#x3D;thumbnail&#x60; to guarantee &#x60;thumbnailUrl&#x60; on every returned row — including the reduced inactive ones. Pass &#x60;rooms&#x60;, &#x60;policies&#x60;, &#x60;rules&#x60;, &#x60;pricing&#x60;, &#x60;fees&#x60;, &#x60;taxes&#x60; or &#x60;photos&#x60; for the same sections as &#x60;GET /v1/listings/{id}&#x60;, loaded for the whole page in one go. Combine comma-separated, e.g. &#x60;?include&#x3D;content,thumbnail&#x60;. The default response stays lean; consumers must opt in. **Inactive listings:** by default only active listings are returned. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated, so when &#x60;status&#x60; asks for inactive ones they carry only &#x60;id&#x60;, &#x60;name&#x60;, &#x60;status&#x60; and &#x60;channels&#x60; — enough to choose what to activate with &#x60;PATCH /v1/listings/{id}&#x60;. The &#x60;content&#x60; and &#x60;details&#x60; expansions are not applied to them. &#x60;?include&#x3D;thumbnail&#x60; is the one exception: it adds &#x60;thumbnailUrl&#x60; to an inactive row so a single request can render an active/inactive selection screen with pictures, instead of one follow-up call per listing (which an inactive listing would answer with &#x60;403 listing_inactive&#x60; anyway).
774
774
  # @param [Hash] opts the optional parameters
775
775
  # @option opts [String] :x_schema Apply a custom or built-in schema to transform the response. Built-in: &#x60;native&#x60; (default), &#x60;calry&#x60;, &#x60;calry-v1&#x60;. Custom: any schema name created via &#x60;POST /v1/schema/custom&#x60;. Unknown / inactive schema names fall back to &#x60;native&#x60;.
776
776
  # @option opts [String] :cursor Opaque cursor returned in the previous response&#39;s &#x60;pagination.nextCursor&#x60;. Omit to fetch the first page.
@@ -779,7 +779,7 @@ module Repull
779
779
  # @option opts [String] :q Case-insensitive substring search on name, street, or city.
780
780
  # @option opts [String] :status Filter by listing status. Defaults to &#x60;active&#x60;. Pass &#x60;inactive&#x60; to list the listings you can activate, &#x60;archived&#x60; for archived ones, or &#x60;all&#x60; for every status. Inactive listings are returned with identity fields only — &#x60;id&#x60;, &#x60;name&#x60;, &#x60;status&#x60;, &#x60;inactiveReason&#x60; (&#x60;plan_limit&#x60;, &#x60;unlisted_on_airbnb&#x60; or &#x60;deactivated&#x60;), &#x60;address.city&#x60; and &#x60;channels&#x60; — and never with the street, &#x60;content&#x60; or &#x60;details&#x60;; activate one to see the rest. The only field you can add to an inactive row is &#x60;thumbnailUrl&#x60;, via &#x60;?include&#x3D;thumbnail&#x60;. (default to 'active')
781
781
  # @option opts [String] :channel Restrict to listings published on the given channel (&#x60;airbnb&#x60;, &#x60;booking&#x60;, &#x60;vrbo&#x60;, etc.). Joins through &#x60;listing_platform_links&#x60; and matches active links only.
782
- # @option opts [String] :include Comma-separated optional expansions. Currently supported: &#x60;content&#x60;, &#x60;details&#x60;, &#x60;thumbnail&#x60;. &#x60;thumbnail&#x60; guarantees &#x60;thumbnailUrl&#x60; on every row and is the only expansion that applies to inactive listings. Unknown values return 422 with a &#x60;valid_values&#x60; envelope. (Note: &#x60;amenities&#x60; is not yet supported on the list endpoint — use the detail endpoint to fetch amenity rows for a single listing.)
782
+ # @option opts [String] :include Comma-separated optional expansions. Currently supported: &#x60;content&#x60;, &#x60;details&#x60;, &#x60;thumbnail&#x60;, &#x60;rooms&#x60;, &#x60;policies&#x60;, &#x60;rules&#x60;, &#x60;pricing&#x60;, &#x60;fees&#x60;, &#x60;taxes&#x60;, &#x60;photos&#x60; (the last seven are described on &#x60;GET /v1/listings/{id}&#x60;; read for the whole page at once). &#x60;thumbnail&#x60; guarantees &#x60;thumbnailUrl&#x60; on every row and is the only expansion that applies to inactive listings. Unknown values return 422 with a &#x60;valid_values&#x60; envelope. (Note: &#x60;amenities&#x60; is not yet supported on the list endpoint — use the detail endpoint to fetch amenity rows for a single listing.)
783
783
  # @return [Array<(ListingListResponse, Integer, Hash)>] ListingListResponse data, response status code and response headers
784
784
  def list_listings_with_http_info(opts = {})
785
785
  if @api_client.config.debugging
@@ -408,6 +408,74 @@ module Repull
408
408
  return data, status_code, headers
409
409
  end
410
410
 
411
+ # Import from Channex
412
+ # Move a workspace off Channex without changing a single id on your side. Pass your Channex API key: Repull reads your Channex properties, room types, rate plans, webhooks, signing keys, channels and upcoming bookings through Channex's own API (read-only — nothing is written to Channex, and the key is not stored). Each Channex property is matched to your Repull listing or hotel (by Booking.com hotel/room and Airbnb/Vrbo listing ids, then by title and address) or created; every Channex id then resolves, and is returned, unchanged on the Channex-compatible API at `/channex/api/v1`. Webhooks are recreated inactive; activate them with `POST /channex/api/v1/migration/cutover`. Safe to re-run: a run that hits its time budget returns `complete: false` and the next run continues.
413
+ # @param import_from_channex_request [ImportFromChannexRequest]
414
+ # @param [Hash] opts the optional parameters
415
+ # @return [ImportFromChannex200Response]
416
+ def import_from_channex(import_from_channex_request, opts = {})
417
+ data, _status_code, _headers = import_from_channex_with_http_info(import_from_channex_request, opts)
418
+ data
419
+ end
420
+
421
+ # Import from Channex
422
+ # Move a workspace off Channex without changing a single id on your side. Pass your Channex API key: Repull reads your Channex properties, room types, rate plans, webhooks, signing keys, channels and upcoming bookings through Channex&#39;s own API (read-only — nothing is written to Channex, and the key is not stored). Each Channex property is matched to your Repull listing or hotel (by Booking.com hotel/room and Airbnb/Vrbo listing ids, then by title and address) or created; every Channex id then resolves, and is returned, unchanged on the Channex-compatible API at &#x60;/channex/api/v1&#x60;. Webhooks are recreated inactive; activate them with &#x60;POST /channex/api/v1/migration/cutover&#x60;. Safe to re-run: a run that hits its time budget returns &#x60;complete: false&#x60; and the next run continues.
423
+ # @param import_from_channex_request [ImportFromChannexRequest]
424
+ # @param [Hash] opts the optional parameters
425
+ # @return [Array<(ImportFromChannex200Response, Integer, Hash)>] ImportFromChannex200Response data, response status code and response headers
426
+ def import_from_channex_with_http_info(import_from_channex_request, opts = {})
427
+ if @api_client.config.debugging
428
+ @api_client.config.logger.debug 'Calling API: MigrateApi.import_from_channex ...'
429
+ end
430
+ # verify the required parameter 'import_from_channex_request' is set
431
+ if @api_client.config.client_side_validation && import_from_channex_request.nil?
432
+ fail ArgumentError, "Missing the required parameter 'import_from_channex_request' when calling MigrateApi.import_from_channex"
433
+ end
434
+ # resource path
435
+ local_var_path = '/v1/migrations/channex'
436
+
437
+ # query parameters
438
+ query_params = opts[:query_params] || {}
439
+
440
+ # header parameters
441
+ header_params = opts[:header_params] || {}
442
+ # HTTP header 'Accept' (if needed)
443
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
444
+ # HTTP header 'Content-Type'
445
+ content_type = @api_client.select_header_content_type(['application/json'])
446
+ if !content_type.nil?
447
+ header_params['Content-Type'] = content_type
448
+ end
449
+
450
+ # form parameters
451
+ form_params = opts[:form_params] || {}
452
+
453
+ # http body (model)
454
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(import_from_channex_request)
455
+
456
+ # return_type
457
+ return_type = opts[:debug_return_type] || 'ImportFromChannex200Response'
458
+
459
+ # auth_names
460
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
461
+
462
+ new_options = opts.merge(
463
+ :operation => :"MigrateApi.import_from_channex",
464
+ :header_params => header_params,
465
+ :query_params => query_params,
466
+ :form_params => form_params,
467
+ :body => post_body,
468
+ :auth_names => auth_names,
469
+ :return_type => return_type
470
+ )
471
+
472
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
473
+ if @api_client.config.debugging
474
+ @api_client.config.logger.debug "API called: MigrateApi#import_from_channex\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
475
+ end
476
+ return data, status_code, headers
477
+ end
478
+
411
479
  # List migrations
412
480
  # Every property manager your workspace has moved through Repull Migrate, newest first, each with where it stands. Page with `pagination.nextCursor`.
413
481
  # @param [Hash] opts the optional parameters
@@ -170,7 +170,7 @@ module Repull
170
170
  end
171
171
 
172
172
  # Create a reservation
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.
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, CiiRUS): 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. | | CiiRUS | ✓ | ✓ | ✓ | ✓ | ✓ | A set price is the rent, with CiiRUS adding its taxes; no tentative holds. | 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.
174
174
  # @param reservation_create_request [ReservationCreateRequest]
175
175
  # @param [Hash] opts the optional parameters
176
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.
@@ -182,7 +182,7 @@ module Repull
182
182
  end
183
183
 
184
184
  # Create a reservation
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.
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, CiiRUS): 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. | | CiiRUS | ✓ | ✓ | ✓ | ✓ | ✓ | A set price is the rent, with CiiRUS adding its taxes; no tentative holds. | 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.
186
186
  # @param reservation_create_request [ReservationCreateRequest]
187
187
  # @param [Hash] opts the optional parameters
188
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.
@@ -532,7 +532,7 @@ module Repull
532
532
  end
533
533
 
534
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.
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. | | CiiRUS | ✓ | ✓ | ✓ | ✓ | ✓ | A set price is the rent, with CiiRUS adding its taxes; no tentative holds. | 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
536
  # @param reservation_quote_request [ReservationQuoteRequest]
537
537
  # @param [Hash] opts the optional parameters
538
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.
@@ -543,7 +543,7 @@ module Repull
543
543
  end
544
544
 
545
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.
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. | | CiiRUS | ✓ | ✓ | ✓ | ✓ | ✓ | A set price is the rent, with CiiRUS adding its taxes; no tentative holds. | 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
547
  # @param reservation_quote_request [ReservationQuoteRequest]
548
548
  # @param [Hash] opts the optional parameters
549
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.
@@ -30,6 +30,9 @@ module Repull
30
30
  # Why the connection was lost. `refresh_token_rejected` — upstream OAuth refresh endpoint returned a hard rejection. `manual_disconnect` — host/admin disconnected via the dashboard. `auth_expired` — credentials aged out without ever being used. `revoked_upstream` — provider notified us the user revoked access.
31
31
  attr_accessor :reason
32
32
 
33
+ # The listings this account holds in your workspace — the ones that stop syncing until it is reconnected. Identity only; inactive listings included. Matches `channels[].account` on `GET /v1/listings`. Empty when the account has no listings here.
34
+ attr_accessor :listings
35
+
33
36
  # Attribute mapping from ruby-style variable name to JSON key.
34
37
  def self.attribute_map
35
38
  {
@@ -38,7 +41,8 @@ module Repull
38
41
  :'connection_id' => :'connectionId',
39
42
  :'provider' => :'provider',
40
43
  :'disconnected_at' => :'disconnectedAt',
41
- :'reason' => :'reason'
44
+ :'reason' => :'reason',
45
+ :'listings' => :'listings'
42
46
  }
43
47
  end
44
48
 
@@ -60,7 +64,8 @@ module Repull
60
64
  :'connection_id' => :'String',
61
65
  :'provider' => :'String',
62
66
  :'disconnected_at' => :'Time',
63
- :'reason' => :'String'
67
+ :'reason' => :'String',
68
+ :'listings' => :'Array<AccountDisconnectedPayloadListingsInner>'
64
69
  }
65
70
  end
66
71
 
@@ -110,6 +115,12 @@ module Repull
110
115
  if attributes.key?(:'reason')
111
116
  self.reason = attributes[:'reason']
112
117
  end
118
+
119
+ if attributes.key?(:'listings')
120
+ if (value = attributes[:'listings']).is_a?(Array)
121
+ self.listings = value
122
+ end
123
+ end
113
124
  end
114
125
 
115
126
  # Show invalid properties with the reasons. Usually used together with valid?
@@ -137,7 +148,8 @@ module Repull
137
148
  connection_id == o.connection_id &&
138
149
  provider == o.provider &&
139
150
  disconnected_at == o.disconnected_at &&
140
- reason == o.reason
151
+ reason == o.reason &&
152
+ listings == o.listings
141
153
  end
142
154
 
143
155
  # @see the `==` method
@@ -149,7 +161,7 @@ module Repull
149
161
  # Calculates hash code according to all attributes.
150
162
  # @return [Integer] Hash code
151
163
  def hash
152
- [workspace_id, account_id, connection_id, provider, disconnected_at, reason].hash
164
+ [workspace_id, account_id, connection_id, provider, disconnected_at, reason, listings].hash
153
165
  end
154
166
 
155
167
  # Builds the object from hash