repull 0.2.16 → 0.2.17
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.
- checksums.yaml +4 -4
- data/lib/repull/api/airbnb_api.rb +6 -6
- data/lib/repull/api/booking_com_api.rb +86 -2
- data/lib/repull/api/conversations_api.rb +8 -8
- data/lib/repull/api/listings_api.rb +182 -12
- data/lib/repull/api/reservations_api.rb +4 -4
- data/lib/repull/models/airbnb_publish_result.rb +41 -2
- data/lib/repull/models/booking_property_action_request.rb +176 -0
- data/lib/repull/models/booking_property_action_response.rb +281 -0
- data/lib/repull/models/booking_publish_result.rb +245 -0
- data/lib/repull/models/booking_publish_section_error.rb +220 -0
- data/lib/repull/models/booking_setup_request.rb +44 -5
- data/lib/repull/models/booking_setup_request_legal_entity.rb +235 -0
- data/lib/repull/models/channel_market_state_item.rb +291 -0
- data/lib/repull/models/error_error.rb +11 -1
- data/lib/repull/models/inquiry_updated_payload.rb +1 -1
- data/lib/repull/models/list_inquiries200_response_data_inner.rb +1 -1
- data/lib/repull/models/listing_address_readiness.rb +171 -0
- data/lib/repull/models/listing_content_update_request_address.rb +40 -3
- data/lib/repull/models/listing_create_request.rb +48 -2
- data/lib/repull/models/listing_market_state_request.rb +149 -0
- data/lib/repull/models/listing_market_state_response.rb +221 -0
- data/lib/repull/models/listing_publish_booking_request.rb +149 -0
- data/lib/repull/models/{listing_publish_response.rb → listing_publish_booking_response.rb} +4 -5
- data/lib/repull/models/listing_publish_status_channel.rb +32 -1
- data/lib/repull/models/listing_publish_status_connection.rb +17 -5
- data/lib/repull/models/listing_publish_status_response.rb +13 -1
- data/lib/repull/models/reservation_request_updated_payload.rb +1 -1
- data/lib/repull/version.rb +1 -1
- data/lib/repull.rb +11 -1
- data/openapi/v1.json +855 -72
- data/scripts/regen.sh +1 -1
- metadata +13 -3
|
@@ -438,7 +438,7 @@ module Repull
|
|
|
438
438
|
end
|
|
439
439
|
|
|
440
440
|
# Per-channel publish status
|
|
441
|
-
# Returns connection state and sync activity per channel. `channels` is sync activity (empty until first push). `connections` is connection state (populated as soon as a channel is linked). Recommended polling cadence: at most once per 30s per listing — for bulk views, prefer `GET /v1/listings` and filter client-side. Returns `403 listing_inactive` when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
|
|
441
|
+
# Returns connection state and sync activity per channel. `channels` is sync activity (empty until first push). `connections` is connection state (populated as soon as a channel is linked). Recommended polling cadence: at most once per 30s per listing — for bulk views, prefer `GET /v1/listings` and filter client-side. **When a push fails, this endpoint says why.** `channels[].pushError` carries the channel's own reason for the last failed push, verbatim — `\"Links and contact info can't be shared\"`, `\"Check-in start time must be before end time\"`, `\"property_type_group must be one of […]\"`. It is free text written by the channel, so render it next to the retry button rather than parsing it. `null` when the last push succeeded or none has run; pair it with `pushStatus` to tell those two apart. **It also says what you will not be allowed to change.** The `airbnb` entry in `connections` carries `lockedFields` — attributes Airbnb has locked on this listing. Airbnb does not refuse a write to one: it answers 200, reports the field as locked, and applies nothing, so a locked write is indistinguishable from a successful one unless you looked first. Read it before you let someone edit. Airbnb-only; no other channel has the concept, and no other entry carries the field. 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.
|
|
442
442
|
# @param id [Integer]
|
|
443
443
|
# @param [Hash] opts the optional parameters
|
|
444
444
|
# @return [ListingPublishStatusResponse]
|
|
@@ -448,7 +448,7 @@ module Repull
|
|
|
448
448
|
end
|
|
449
449
|
|
|
450
450
|
# Per-channel publish status
|
|
451
|
-
# Returns connection state and sync activity per channel. `channels` is sync activity (empty until first push). `connections` is connection state (populated as soon as a channel is linked). Recommended polling cadence: at most once per 30s per listing — for bulk views, prefer `GET /v1/listings` and filter client-side. Returns `403 listing_inactive` when the listing is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.
|
|
451
|
+
# Returns connection state and sync activity per channel. `channels` is sync activity (empty until first push). `connections` is connection state (populated as soon as a channel is linked). Recommended polling cadence: at most once per 30s per listing — for bulk views, prefer `GET /v1/listings` and filter client-side. **When a push fails, this endpoint says why.** `channels[].pushError` carries the channel's own reason for the last failed push, verbatim — `\"Links and contact info can't be shared\"`, `\"Check-in start time must be before end time\"`, `\"property_type_group must be one of […]\"`. It is free text written by the channel, so render it next to the retry button rather than parsing it. `null` when the last push succeeded or none has run; pair it with `pushStatus` to tell those two apart. **It also says what you will not be allowed to change.** The `airbnb` entry in `connections` carries `lockedFields` — attributes Airbnb has locked on this listing. Airbnb does not refuse a write to one: it answers 200, reports the field as locked, and applies nothing, so a locked write is indistinguishable from a successful one unless you looked first. Read it before you let someone edit. Airbnb-only; no other channel has the concept, and no other entry carries the field. 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.
|
|
452
452
|
# @param id [Integer]
|
|
453
453
|
# @param [Hash] opts the optional parameters
|
|
454
454
|
# @return [Array<(ListingPublishStatusResponse, Integer, Hash)>] ListingPublishStatusResponse data, response status code and response headers
|
|
@@ -665,7 +665,7 @@ module Repull
|
|
|
665
665
|
end
|
|
666
666
|
|
|
667
667
|
# Publish a listing to Airbnb
|
|
668
|
-
# Push a Repull listing's canonical content to Airbnb. Pass `airbnbConnectionId` to update an already-mapped Airbnb listing, or `hostId` to create a brand-new Airbnb listing under that host. **A publish is not one call to Airbnb.** It is up to eight independent ones — details, description, amenities, rooms, policies, photos, pricing, checkout_tasks — and each can fail on its own. `result.published` is true only when every attempted section landed; `result.sections` lists the ones that did and `result.errors[]` carries Airbnb's own reason, per section, for the ones that did not. **A partial publish is normal and is not rolled back**: what succeeded stays applied. Publish again once you have fixed the failing sections — a re-publish of an unchanged section is harmless. `result.lockedFields` names the fields Airbnb will not let this listing change at all. They are not retryable by anyone: Airbnb answers 200 and applies nothing. `GET /v1/channels/airbnb/listings/{id}` reports the same list up front. **Which fields this pushes** — title, description sections and house rules (English/primary locale), amenities, rooms and beds, photos, nightly price and fees, cancellation policy and guest controls, check-in/out times, quiet hours, property and room type, checkout tasks. **Not pushed by this endpoint:** non-primary locales (`PUT /v1/channels/airbnb/listings/{id}/descriptions`), guest-safety disclosures (`PUT …/safety-disclosures`), check-in method (`PUT …/details`), permits (`PUT …/permits`), and the calendar (`PUT …/availability`). `force: true` re-pushes every section, ignoring dirty-field tracking. Without it only the sections changed since the last successful publish are sent. Send `Idempotency-Key` to make a retry safe: a timeout on a publish otherwise leaves you unable to tell whether it ran. 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.
|
|
668
|
+
# Push a Repull listing's canonical content to Airbnb. Pass `airbnbConnectionId` to update an already-mapped Airbnb listing, or `hostId` to create a brand-new Airbnb listing under that host. **A publish is not one call to Airbnb.** It is up to eight independent ones — details, description, amenities, rooms, policies, photos, pricing, checkout_tasks — and each can fail on its own. `result.published` is true only when every attempted section landed; `result.sections` lists the ones that did and `result.errors[]` carries Airbnb's own reason, per section, for the ones that did not. **A partial publish is normal and is not rolled back**: what succeeded stays applied. Publish again once you have fixed the failing sections — a re-publish of an unchanged section is harmless. `result.live` is a different question from `result.published`. `published` is about CONTENT — every attempted section landed. `live` is about whether the listing takes bookings: it is true only when activation was actually performed and succeeded. A create can land all eight sections and still leave the listing inactive, because activation is skipped when instant-booking cannot be confirmed to be off — so `published: true` with `live: false` is a real and common outcome, and `result.warnings` says why. `live` is ABSENT, not `false`, when activation was never part of the operation: publishing to an already-mapped listing updates content and activates nothing. Only treat a listing as not-live when `live` is present and false. `result.warnings[]` lists steps that failed WITHOUT failing the publish — optional work the push carried on past. They were previously swallowed, so the only sign of one was a listing that was somehow not quite right afterwards. A publish can be `published: true` and still carry warnings; read them before concluding nothing needs doing. `result.lockedFields` names the fields Airbnb will not let this listing change at all. They are not retryable by anyone: Airbnb answers 200 and applies nothing. `GET /v1/channels/airbnb/listings/{id}` reports the same list up front. **Which fields this pushes** — title, description sections and house rules (English/primary locale), amenities, rooms and beds, photos, nightly price and fees, cancellation policy and guest controls, check-in/out times, quiet hours, property and room type, checkout tasks. **Not pushed by this endpoint:** non-primary locales (`PUT /v1/channels/airbnb/listings/{id}/descriptions`), guest-safety disclosures (`PUT …/safety-disclosures`), check-in method (`PUT …/details`), permits (`PUT …/permits`), and the calendar (`PUT …/availability`). `force: true` re-pushes every section, ignoring dirty-field tracking. Without it only the sections changed since the last successful publish are sent. Send `Idempotency-Key` to make a retry safe: a timeout on a publish otherwise leaves you unable to tell whether it ran. 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.
|
|
669
669
|
# @param id [Integer]
|
|
670
670
|
# @param [Hash] opts the optional parameters
|
|
671
671
|
# @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged `Idempotency-Status: cached` — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → `409 idempotency_key_in_use`. - Same key with a DIFFERENT payload → `422 idempotency_key_reused`. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status >= 500, `408`, `425` and `429`, and the refusals that happen before anything is done and tell you to fix something outside the request first — `connection_reauth_required`, `listing_inactive`, and the rate/daily limits. Every other answer, including a final refusal such as `422 airbnb_rejected`, is stored and replayed.
|
|
@@ -677,7 +677,7 @@ module Repull
|
|
|
677
677
|
end
|
|
678
678
|
|
|
679
679
|
# Publish a listing to Airbnb
|
|
680
|
-
# Push a Repull listing's canonical content to Airbnb. Pass `airbnbConnectionId` to update an already-mapped Airbnb listing, or `hostId` to create a brand-new Airbnb listing under that host. **A publish is not one call to Airbnb.** It is up to eight independent ones — details, description, amenities, rooms, policies, photos, pricing, checkout_tasks — and each can fail on its own. `result.published` is true only when every attempted section landed; `result.sections` lists the ones that did and `result.errors[]` carries Airbnb's own reason, per section, for the ones that did not. **A partial publish is normal and is not rolled back**: what succeeded stays applied. Publish again once you have fixed the failing sections — a re-publish of an unchanged section is harmless. `result.lockedFields` names the fields Airbnb will not let this listing change at all. They are not retryable by anyone: Airbnb answers 200 and applies nothing. `GET /v1/channels/airbnb/listings/{id}` reports the same list up front. **Which fields this pushes** — title, description sections and house rules (English/primary locale), amenities, rooms and beds, photos, nightly price and fees, cancellation policy and guest controls, check-in/out times, quiet hours, property and room type, checkout tasks. **Not pushed by this endpoint:** non-primary locales (`PUT /v1/channels/airbnb/listings/{id}/descriptions`), guest-safety disclosures (`PUT …/safety-disclosures`), check-in method (`PUT …/details`), permits (`PUT …/permits`), and the calendar (`PUT …/availability`). `force: true` re-pushes every section, ignoring dirty-field tracking. Without it only the sections changed since the last successful publish are sent. Send `Idempotency-Key` to make a retry safe: a timeout on a publish otherwise leaves you unable to tell whether it ran. 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.
|
|
680
|
+
# Push a Repull listing's canonical content to Airbnb. Pass `airbnbConnectionId` to update an already-mapped Airbnb listing, or `hostId` to create a brand-new Airbnb listing under that host. **A publish is not one call to Airbnb.** It is up to eight independent ones — details, description, amenities, rooms, policies, photos, pricing, checkout_tasks — and each can fail on its own. `result.published` is true only when every attempted section landed; `result.sections` lists the ones that did and `result.errors[]` carries Airbnb's own reason, per section, for the ones that did not. **A partial publish is normal and is not rolled back**: what succeeded stays applied. Publish again once you have fixed the failing sections — a re-publish of an unchanged section is harmless. `result.live` is a different question from `result.published`. `published` is about CONTENT — every attempted section landed. `live` is about whether the listing takes bookings: it is true only when activation was actually performed and succeeded. A create can land all eight sections and still leave the listing inactive, because activation is skipped when instant-booking cannot be confirmed to be off — so `published: true` with `live: false` is a real and common outcome, and `result.warnings` says why. `live` is ABSENT, not `false`, when activation was never part of the operation: publishing to an already-mapped listing updates content and activates nothing. Only treat a listing as not-live when `live` is present and false. `result.warnings[]` lists steps that failed WITHOUT failing the publish — optional work the push carried on past. They were previously swallowed, so the only sign of one was a listing that was somehow not quite right afterwards. A publish can be `published: true` and still carry warnings; read them before concluding nothing needs doing. `result.lockedFields` names the fields Airbnb will not let this listing change at all. They are not retryable by anyone: Airbnb answers 200 and applies nothing. `GET /v1/channels/airbnb/listings/{id}` reports the same list up front. **Which fields this pushes** — title, description sections and house rules (English/primary locale), amenities, rooms and beds, photos, nightly price and fees, cancellation policy and guest controls, check-in/out times, quiet hours, property and room type, checkout tasks. **Not pushed by this endpoint:** non-primary locales (`PUT /v1/channels/airbnb/listings/{id}/descriptions`), guest-safety disclosures (`PUT …/safety-disclosures`), check-in method (`PUT …/details`), permits (`PUT …/permits`), and the calendar (`PUT …/availability`). `force: true` re-pushes every section, ignoring dirty-field tracking. Without it only the sections changed since the last successful publish are sent. Send `Idempotency-Key` to make a retry safe: a timeout on a publish otherwise leaves you unable to tell whether it ran. 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.
|
|
681
681
|
# @param id [Integer]
|
|
682
682
|
# @param [Hash] opts the optional parameters
|
|
683
683
|
# @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged `Idempotency-Status: cached` — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → `409 idempotency_key_in_use`. - Same key with a DIFFERENT payload → `422 idempotency_key_reused`. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status >= 500, `408`, `425` and `429`, and the refusals that happen before anything is done and tell you to fix something outside the request first — `connection_reauth_required`, `listing_inactive`, and the rate/daily limits. Every other answer, including a final refusal such as `422 airbnb_rejected`, is stored and replayed.
|
|
@@ -742,20 +742,24 @@ module Repull
|
|
|
742
742
|
end
|
|
743
743
|
|
|
744
744
|
# Publish a listing to Booking.com
|
|
745
|
-
# Push a Repull listing to Booking.com. The listing must already be mapped to a Booking property + room
|
|
746
|
-
# @param id [Integer]
|
|
745
|
+
# Push a Repull listing's content to Booking.com. The listing must already be mapped to a Booking.com property + room — claim the hotel through the Connect Booking flow, then map its rooms with `POST /v1/connect/booking/map-rooms`. **Which property the content lands in.** A listing can be mapped to more than one Booking.com property; the same unit re-listed under a new property keeps its old mapping, and workspaces routinely sit on five or six. When the listing has exactly one property you need send nothing. When it has several, name one with `hotelId` in the body (or `?hotel_id=` — the same value, accepted either way, body wins if you send both). Omit it on such a listing and the push is refused with **`409 ambiguous_booking_mapping`**, listing the candidate ids: content pushed into a property chosen for you lands on the wrong listing and reports success, which is worse than a refusal. `GET /v1/channels/booking/properties` lists every property with the listings mapped under it. Naming a property this listing is not mapped to is a `404` that names the ones it is. The property that actually received the content comes back as `result.hotelId`. **A publish is not one call to Booking.com.** It is several independent Content API calls — details, description, amenities, rooms, photos, pricing — and each can fail on its own. `result.published` is true only when every attempted section landed; `result.sections` lists the ones that did and `result.errors[]` carries Booking.com's own reason, per section, for the ones that did not. A property whose Content API credentials do not cover a section answers 403 for that section alone. **A partial publish is normal and is not rolled back**: what succeeded stays applied. Fix the failing sections and publish again — re-publishing an unchanged section is harmless. A listing with no Booking.com property mapped at all is not an error: the call returns `result.published: false` with `result.reason` and `result.hotelId: null`, and nothing is pushed. 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.
|
|
746
|
+
# @param id [Integer] Repull listing id — NOT a Booking.com hotel id.
|
|
747
747
|
# @param [Hash] opts the optional parameters
|
|
748
|
-
# @
|
|
748
|
+
# @option opts [String] :hotel_id Booking.com property to publish into, for a listing mapped to more than one. The query-string spelling of the body's `hotelId`, accepted so this route reads the same as every other Booking listing-addressed route. The body wins when both are sent.
|
|
749
|
+
# @option opts [ListingPublishBookingRequest] :listing_publish_booking_request
|
|
750
|
+
# @return [ListingPublishBookingResponse]
|
|
749
751
|
def publish_listing_to_booking(id, opts = {})
|
|
750
752
|
data, _status_code, _headers = publish_listing_to_booking_with_http_info(id, opts)
|
|
751
753
|
data
|
|
752
754
|
end
|
|
753
755
|
|
|
754
756
|
# Publish a listing to Booking.com
|
|
755
|
-
# Push a Repull listing to Booking.com. The listing must already be mapped to a Booking property + room
|
|
756
|
-
# @param id [Integer]
|
|
757
|
+
# Push a Repull listing's content to Booking.com. The listing must already be mapped to a Booking.com property + room — claim the hotel through the Connect Booking flow, then map its rooms with `POST /v1/connect/booking/map-rooms`. **Which property the content lands in.** A listing can be mapped to more than one Booking.com property; the same unit re-listed under a new property keeps its old mapping, and workspaces routinely sit on five or six. When the listing has exactly one property you need send nothing. When it has several, name one with `hotelId` in the body (or `?hotel_id=` — the same value, accepted either way, body wins if you send both). Omit it on such a listing and the push is refused with **`409 ambiguous_booking_mapping`**, listing the candidate ids: content pushed into a property chosen for you lands on the wrong listing and reports success, which is worse than a refusal. `GET /v1/channels/booking/properties` lists every property with the listings mapped under it. Naming a property this listing is not mapped to is a `404` that names the ones it is. The property that actually received the content comes back as `result.hotelId`. **A publish is not one call to Booking.com.** It is several independent Content API calls — details, description, amenities, rooms, photos, pricing — and each can fail on its own. `result.published` is true only when every attempted section landed; `result.sections` lists the ones that did and `result.errors[]` carries Booking.com's own reason, per section, for the ones that did not. A property whose Content API credentials do not cover a section answers 403 for that section alone. **A partial publish is normal and is not rolled back**: what succeeded stays applied. Fix the failing sections and publish again — re-publishing an unchanged section is harmless. A listing with no Booking.com property mapped at all is not an error: the call returns `result.published: false` with `result.reason` and `result.hotelId: null`, and nothing is pushed. 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.
|
|
758
|
+
# @param id [Integer] Repull listing id — NOT a Booking.com hotel id.
|
|
757
759
|
# @param [Hash] opts the optional parameters
|
|
758
|
-
# @
|
|
760
|
+
# @option opts [String] :hotel_id Booking.com property to publish into, for a listing mapped to more than one. The query-string spelling of the body's `hotelId`, accepted so this route reads the same as every other Booking listing-addressed route. The body wins when both are sent.
|
|
761
|
+
# @option opts [ListingPublishBookingRequest] :listing_publish_booking_request
|
|
762
|
+
# @return [Array<(ListingPublishBookingResponse, Integer, Hash)>] ListingPublishBookingResponse data, response status code and response headers
|
|
759
763
|
def publish_listing_to_booking_with_http_info(id, opts = {})
|
|
760
764
|
if @api_client.config.debugging
|
|
761
765
|
@api_client.config.logger.debug 'Calling API: ListingsApi.publish_listing_to_booking ...'
|
|
@@ -769,20 +773,26 @@ module Repull
|
|
|
769
773
|
|
|
770
774
|
# query parameters
|
|
771
775
|
query_params = opts[:query_params] || {}
|
|
776
|
+
query_params[:'hotel_id'] = opts[:'hotel_id'] if !opts[:'hotel_id'].nil?
|
|
772
777
|
|
|
773
778
|
# header parameters
|
|
774
779
|
header_params = opts[:header_params] || {}
|
|
775
780
|
# HTTP header 'Accept' (if needed)
|
|
776
781
|
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
782
|
+
# HTTP header 'Content-Type'
|
|
783
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
784
|
+
if !content_type.nil?
|
|
785
|
+
header_params['Content-Type'] = content_type
|
|
786
|
+
end
|
|
777
787
|
|
|
778
788
|
# form parameters
|
|
779
789
|
form_params = opts[:form_params] || {}
|
|
780
790
|
|
|
781
791
|
# http body (model)
|
|
782
|
-
post_body = opts[:debug_body]
|
|
792
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(opts[:'listing_publish_booking_request'])
|
|
783
793
|
|
|
784
794
|
# return_type
|
|
785
|
-
return_type = opts[:debug_return_type] || '
|
|
795
|
+
return_type = opts[:debug_return_type] || 'ListingPublishBookingResponse'
|
|
786
796
|
|
|
787
797
|
# auth_names
|
|
788
798
|
auth_names = opts[:debug_auth_names] || ['bearerAuth']
|
|
@@ -942,6 +952,166 @@ module Repull
|
|
|
942
952
|
return data, status_code, headers
|
|
943
953
|
end
|
|
944
954
|
|
|
955
|
+
# Take a listing off the market
|
|
956
|
+
# Stop this listing being sold, on every channel it is connected to, in one call. What that means differs per channel and you do not have to know which is which. On **Airbnb** the live listing is deactivated with a valid deactivation reason and then READ BACK — Airbnb accepts some deactivations and leaves the listing up, so \"we sent the request\" is never reported as success. On **Booking.com** there is no unlist at all; the equivalent is closing the room's availability across the whole forward window, which is what happens. **This is not the same as deactivating the listing in Repull.** The two get confused because both sound like removal, and they have opposite consequences: | | Take offline (this endpoint) | Deactivate in Repull (`PATCH /v1/listings/{id}` `{\"active\": false}`) | |---|---|---| | The guest-facing listing | **Stops taking bookings** | Stays live and keeps taking bookings | | Billing and plan limits | Unchanged | No longer billed, no longer counts toward the cap | | API access to the listing | Unchanged — you can still read and write it | `403 listing_inactive` until reactivated | | Reverse it with | `POST /v1/listings/{id}/online` | `PATCH /v1/listings/{id}` `{\"active\": true}` | | Data kept | Yes | Yes, and it keeps syncing | Neither one deletes anything, on either side. **The answer is per channel item.** A listing can sit on several Airbnb connections and a Booking.com property at once; they fail independently and a partial result is the ordinary outcome, so every item reports its own `state`, `code` and `message` and there is no top-level success flag to mislead you. Nothing is rolled back — re-send the same request to retry the items that did not land. **Booking.com ambiguity is reported, not fanned out.** A listing mapped to more than one active Booking.com property comes back with that item refused (`ambiguous_booking_mapping`) while the Airbnb items still run: closing the wrong property's availability takes real inventory off sale, and taking a listing off Airbnb is not less urgent because its Booking.com mapping is untidy. Name the property with `hotelId` and send it again. 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.
|
|
957
|
+
# @param id [Integer] Repull listing id.
|
|
958
|
+
# @param [Hash] opts the optional parameters
|
|
959
|
+
# @option opts [String] :hotel_id Booking.com property to act on, for a listing mapped to more than one. The query-string spelling of the body's `hotelId`; the body wins when both are sent.
|
|
960
|
+
# @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged `Idempotency-Status: cached` — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → `409 idempotency_key_in_use`. - Same key with a DIFFERENT payload → `422 idempotency_key_reused`. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status >= 500, `408`, `425` and `429`, and the refusals that happen before anything is done and tell you to fix something outside the request first — `connection_reauth_required`, `listing_inactive`, and the rate/daily limits. Every other answer, including a final refusal such as `422 airbnb_rejected`, is stored and replayed.
|
|
961
|
+
# @option opts [ListingMarketStateRequest] :listing_market_state_request
|
|
962
|
+
# @return [ListingMarketStateResponse]
|
|
963
|
+
def take_listing_offline(id, opts = {})
|
|
964
|
+
data, _status_code, _headers = take_listing_offline_with_http_info(id, opts)
|
|
965
|
+
data
|
|
966
|
+
end
|
|
967
|
+
|
|
968
|
+
# Take a listing off the market
|
|
969
|
+
# Stop this listing being sold, on every channel it is connected to, in one call. What that means differs per channel and you do not have to know which is which. On **Airbnb** the live listing is deactivated with a valid deactivation reason and then READ BACK — Airbnb accepts some deactivations and leaves the listing up, so \"we sent the request\" is never reported as success. On **Booking.com** there is no unlist at all; the equivalent is closing the room's availability across the whole forward window, which is what happens. **This is not the same as deactivating the listing in Repull.** The two get confused because both sound like removal, and they have opposite consequences: | | Take offline (this endpoint) | Deactivate in Repull (`PATCH /v1/listings/{id}` `{\"active\": false}`) | |---|---|---| | The guest-facing listing | **Stops taking bookings** | Stays live and keeps taking bookings | | Billing and plan limits | Unchanged | No longer billed, no longer counts toward the cap | | API access to the listing | Unchanged — you can still read and write it | `403 listing_inactive` until reactivated | | Reverse it with | `POST /v1/listings/{id}/online` | `PATCH /v1/listings/{id}` `{\"active\": true}` | | Data kept | Yes | Yes, and it keeps syncing | Neither one deletes anything, on either side. **The answer is per channel item.** A listing can sit on several Airbnb connections and a Booking.com property at once; they fail independently and a partial result is the ordinary outcome, so every item reports its own `state`, `code` and `message` and there is no top-level success flag to mislead you. Nothing is rolled back — re-send the same request to retry the items that did not land. **Booking.com ambiguity is reported, not fanned out.** A listing mapped to more than one active Booking.com property comes back with that item refused (`ambiguous_booking_mapping`) while the Airbnb items still run: closing the wrong property's availability takes real inventory off sale, and taking a listing off Airbnb is not less urgent because its Booking.com mapping is untidy. Name the property with `hotelId` and send it again. 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.
|
|
970
|
+
# @param id [Integer] Repull listing id.
|
|
971
|
+
# @param [Hash] opts the optional parameters
|
|
972
|
+
# @option opts [String] :hotel_id Booking.com property to act on, for a listing mapped to more than one. The query-string spelling of the body's `hotelId`; the body wins when both are sent.
|
|
973
|
+
# @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged `Idempotency-Status: cached` — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → `409 idempotency_key_in_use`. - Same key with a DIFFERENT payload → `422 idempotency_key_reused`. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status >= 500, `408`, `425` and `429`, and the refusals that happen before anything is done and tell you to fix something outside the request first — `connection_reauth_required`, `listing_inactive`, and the rate/daily limits. Every other answer, including a final refusal such as `422 airbnb_rejected`, is stored and replayed.
|
|
974
|
+
# @option opts [ListingMarketStateRequest] :listing_market_state_request
|
|
975
|
+
# @return [Array<(ListingMarketStateResponse, Integer, Hash)>] ListingMarketStateResponse data, response status code and response headers
|
|
976
|
+
def take_listing_offline_with_http_info(id, opts = {})
|
|
977
|
+
if @api_client.config.debugging
|
|
978
|
+
@api_client.config.logger.debug 'Calling API: ListingsApi.take_listing_offline ...'
|
|
979
|
+
end
|
|
980
|
+
# verify the required parameter 'id' is set
|
|
981
|
+
if @api_client.config.client_side_validation && id.nil?
|
|
982
|
+
fail ArgumentError, "Missing the required parameter 'id' when calling ListingsApi.take_listing_offline"
|
|
983
|
+
end
|
|
984
|
+
if @api_client.config.client_side_validation && !opts[:'idempotency_key'].nil? && opts[:'idempotency_key'].to_s.length > 255
|
|
985
|
+
fail ArgumentError, 'invalid value for "opts[:"idempotency_key"]" when calling ListingsApi.take_listing_offline, the character length must be smaller than or equal to 255.'
|
|
986
|
+
end
|
|
987
|
+
|
|
988
|
+
# resource path
|
|
989
|
+
local_var_path = '/v1/listings/{id}/offline'.sub('{id}', CGI.escape(id.to_s))
|
|
990
|
+
|
|
991
|
+
# query parameters
|
|
992
|
+
query_params = opts[:query_params] || {}
|
|
993
|
+
query_params[:'hotel_id'] = opts[:'hotel_id'] if !opts[:'hotel_id'].nil?
|
|
994
|
+
|
|
995
|
+
# header parameters
|
|
996
|
+
header_params = opts[:header_params] || {}
|
|
997
|
+
# HTTP header 'Accept' (if needed)
|
|
998
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
999
|
+
# HTTP header 'Content-Type'
|
|
1000
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
1001
|
+
if !content_type.nil?
|
|
1002
|
+
header_params['Content-Type'] = content_type
|
|
1003
|
+
end
|
|
1004
|
+
header_params[:'Idempotency-Key'] = opts[:'idempotency_key'] if !opts[:'idempotency_key'].nil?
|
|
1005
|
+
|
|
1006
|
+
# form parameters
|
|
1007
|
+
form_params = opts[:form_params] || {}
|
|
1008
|
+
|
|
1009
|
+
# http body (model)
|
|
1010
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(opts[:'listing_market_state_request'])
|
|
1011
|
+
|
|
1012
|
+
# return_type
|
|
1013
|
+
return_type = opts[:debug_return_type] || 'ListingMarketStateResponse'
|
|
1014
|
+
|
|
1015
|
+
# auth_names
|
|
1016
|
+
auth_names = opts[:debug_auth_names] || ['bearerAuth']
|
|
1017
|
+
|
|
1018
|
+
new_options = opts.merge(
|
|
1019
|
+
:operation => :"ListingsApi.take_listing_offline",
|
|
1020
|
+
:header_params => header_params,
|
|
1021
|
+
:query_params => query_params,
|
|
1022
|
+
:form_params => form_params,
|
|
1023
|
+
:body => post_body,
|
|
1024
|
+
:auth_names => auth_names,
|
|
1025
|
+
:return_type => return_type
|
|
1026
|
+
)
|
|
1027
|
+
|
|
1028
|
+
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
1029
|
+
if @api_client.config.debugging
|
|
1030
|
+
@api_client.config.logger.debug "API called: ListingsApi#take_listing_offline\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
1031
|
+
end
|
|
1032
|
+
return data, status_code, headers
|
|
1033
|
+
end
|
|
1034
|
+
|
|
1035
|
+
# Put a listing back on the market
|
|
1036
|
+
# Put this listing back on sale, on every channel it is connected to. The counterpart of `POST /v1/listings/{id}/offline`, which documents the per-item response and the difference between this and deactivating a listing in Repull. **It does not push content.** On **Airbnb** it re-enables sync and makes the listing available again; anything that changed while the listing was down is still unpublished, so follow with `POST /v1/listings/{id}/publish/airbnb` if the content moved. On **Booking.com** it re-syncs the true calendar rather than opening everything: dates that are genuinely blocked — a reservation, an owner stay — stay blocked, and only the closure `offline` wrote lifts. The two directions are not mirror images, and that is deliberate. **One asymmetry worth planning for.** Taking a listing down passes no billing gate; putting it back up goes through the channel-publish gate. So on a workspace whose subscription has lapsed, `offline` still works and this endpoint answers `402 payment_required` — a listing can be left off the market until billing is sorted out. That refusal is reported as a billing refusal with the action that fixes it, never as a channel error: retrying, or reconnecting the channel, does nothing for it. 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.
|
|
1037
|
+
# @param id [Integer] Repull listing id.
|
|
1038
|
+
# @param [Hash] opts the optional parameters
|
|
1039
|
+
# @option opts [String] :hotel_id Booking.com property to act on, for a listing mapped to more than one. The query-string spelling of the body's `hotelId`; the body wins when both are sent.
|
|
1040
|
+
# @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged `Idempotency-Status: cached` — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → `409 idempotency_key_in_use`. - Same key with a DIFFERENT payload → `422 idempotency_key_reused`. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status >= 500, `408`, `425` and `429`, and the refusals that happen before anything is done and tell you to fix something outside the request first — `connection_reauth_required`, `listing_inactive`, and the rate/daily limits. Every other answer, including a final refusal such as `422 airbnb_rejected`, is stored and replayed.
|
|
1041
|
+
# @option opts [ListingMarketStateRequest] :listing_market_state_request
|
|
1042
|
+
# @return [ListingMarketStateResponse]
|
|
1043
|
+
def take_listing_online(id, opts = {})
|
|
1044
|
+
data, _status_code, _headers = take_listing_online_with_http_info(id, opts)
|
|
1045
|
+
data
|
|
1046
|
+
end
|
|
1047
|
+
|
|
1048
|
+
# Put a listing back on the market
|
|
1049
|
+
# Put this listing back on sale, on every channel it is connected to. The counterpart of `POST /v1/listings/{id}/offline`, which documents the per-item response and the difference between this and deactivating a listing in Repull. **It does not push content.** On **Airbnb** it re-enables sync and makes the listing available again; anything that changed while the listing was down is still unpublished, so follow with `POST /v1/listings/{id}/publish/airbnb` if the content moved. On **Booking.com** it re-syncs the true calendar rather than opening everything: dates that are genuinely blocked — a reservation, an owner stay — stay blocked, and only the closure `offline` wrote lifts. The two directions are not mirror images, and that is deliberate. **One asymmetry worth planning for.** Taking a listing down passes no billing gate; putting it back up goes through the channel-publish gate. So on a workspace whose subscription has lapsed, `offline` still works and this endpoint answers `402 payment_required` — a listing can be left off the market until billing is sorted out. That refusal is reported as a billing refusal with the action that fixes it, never as a channel error: retrying, or reconnecting the channel, does nothing for it. 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.
|
|
1050
|
+
# @param id [Integer] Repull listing id.
|
|
1051
|
+
# @param [Hash] opts the optional parameters
|
|
1052
|
+
# @option opts [String] :hotel_id Booking.com property to act on, for a listing mapped to more than one. The query-string spelling of the body's `hotelId`; the body wins when both are sent.
|
|
1053
|
+
# @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged `Idempotency-Status: cached` — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → `409 idempotency_key_in_use`. - Same key with a DIFFERENT payload → `422 idempotency_key_reused`. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status >= 500, `408`, `425` and `429`, and the refusals that happen before anything is done and tell you to fix something outside the request first — `connection_reauth_required`, `listing_inactive`, and the rate/daily limits. Every other answer, including a final refusal such as `422 airbnb_rejected`, is stored and replayed.
|
|
1054
|
+
# @option opts [ListingMarketStateRequest] :listing_market_state_request
|
|
1055
|
+
# @return [Array<(ListingMarketStateResponse, Integer, Hash)>] ListingMarketStateResponse data, response status code and response headers
|
|
1056
|
+
def take_listing_online_with_http_info(id, opts = {})
|
|
1057
|
+
if @api_client.config.debugging
|
|
1058
|
+
@api_client.config.logger.debug 'Calling API: ListingsApi.take_listing_online ...'
|
|
1059
|
+
end
|
|
1060
|
+
# verify the required parameter 'id' is set
|
|
1061
|
+
if @api_client.config.client_side_validation && id.nil?
|
|
1062
|
+
fail ArgumentError, "Missing the required parameter 'id' when calling ListingsApi.take_listing_online"
|
|
1063
|
+
end
|
|
1064
|
+
if @api_client.config.client_side_validation && !opts[:'idempotency_key'].nil? && opts[:'idempotency_key'].to_s.length > 255
|
|
1065
|
+
fail ArgumentError, 'invalid value for "opts[:"idempotency_key"]" when calling ListingsApi.take_listing_online, the character length must be smaller than or equal to 255.'
|
|
1066
|
+
end
|
|
1067
|
+
|
|
1068
|
+
# resource path
|
|
1069
|
+
local_var_path = '/v1/listings/{id}/online'.sub('{id}', CGI.escape(id.to_s))
|
|
1070
|
+
|
|
1071
|
+
# query parameters
|
|
1072
|
+
query_params = opts[:query_params] || {}
|
|
1073
|
+
query_params[:'hotel_id'] = opts[:'hotel_id'] if !opts[:'hotel_id'].nil?
|
|
1074
|
+
|
|
1075
|
+
# header parameters
|
|
1076
|
+
header_params = opts[:header_params] || {}
|
|
1077
|
+
# HTTP header 'Accept' (if needed)
|
|
1078
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
1079
|
+
# HTTP header 'Content-Type'
|
|
1080
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
1081
|
+
if !content_type.nil?
|
|
1082
|
+
header_params['Content-Type'] = content_type
|
|
1083
|
+
end
|
|
1084
|
+
header_params[:'Idempotency-Key'] = opts[:'idempotency_key'] if !opts[:'idempotency_key'].nil?
|
|
1085
|
+
|
|
1086
|
+
# form parameters
|
|
1087
|
+
form_params = opts[:form_params] || {}
|
|
1088
|
+
|
|
1089
|
+
# http body (model)
|
|
1090
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(opts[:'listing_market_state_request'])
|
|
1091
|
+
|
|
1092
|
+
# return_type
|
|
1093
|
+
return_type = opts[:debug_return_type] || 'ListingMarketStateResponse'
|
|
1094
|
+
|
|
1095
|
+
# auth_names
|
|
1096
|
+
auth_names = opts[:debug_auth_names] || ['bearerAuth']
|
|
1097
|
+
|
|
1098
|
+
new_options = opts.merge(
|
|
1099
|
+
:operation => :"ListingsApi.take_listing_online",
|
|
1100
|
+
:header_params => header_params,
|
|
1101
|
+
:query_params => query_params,
|
|
1102
|
+
:form_params => form_params,
|
|
1103
|
+
:body => post_body,
|
|
1104
|
+
:auth_names => auth_names,
|
|
1105
|
+
:return_type => return_type
|
|
1106
|
+
)
|
|
1107
|
+
|
|
1108
|
+
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
1109
|
+
if @api_client.config.debugging
|
|
1110
|
+
@api_client.config.logger.debug "API called: ListingsApi#take_listing_online\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
1111
|
+
end
|
|
1112
|
+
return data, status_code, headers
|
|
1113
|
+
end
|
|
1114
|
+
|
|
945
1115
|
# Deactivate or reactivate a listing
|
|
946
1116
|
# Toggle a listing's active state. Send `{ \"active\": false }` to **deactivate** (exclude the listing from Repull) or `{ \"active\": true }` to **reactivate** it. \"Deactivate\" keeps the listing row — it is NOT a hard delete, and it NEVER touches the upstream channel (Airbnb / Hospitable / Booking.com). Repull only mutates its own copy of the inventory. Deactivating is the self-serve way to get back under the plan-listings cap without paying. Reactivation respects the plan-listings cap: if activating this listing would push you over the cap for your tier, the call returns `402 listings_limit_exceeded` and the listing stays inactive. Deactivate another listing or upgrade first. Idempotent: setting a listing to the state it's already in returns 200. To change many listings at once, all or nothing, use `POST /v1/listings/status`.
|
|
947
1117
|
# @param id [Integer] Repull listing id
|
|
@@ -20,7 +20,7 @@ module Repull
|
|
|
20
20
|
@api_client = api_client
|
|
21
21
|
end
|
|
22
22
|
# Accept a booking request
|
|
23
|
-
# Accept a pending Airbnb booking request — a reservation with status `pending`, made on a listing without Instant Book. Find them with `GET /v1/reservations?status=pending`. Airbnb expires a request the host has not answered within 24 hours.
|
|
23
|
+
# Accept a pending Airbnb booking request — a reservation with status `pending`, made on a listing without Instant Book. Find them with `GET /v1/reservations?status=pending`. Airbnb expires a request the host has not answered within 24 hours. Airbnb confirms asynchronously: the reservation’s status moves to confirmed, and a `reservation.updated` webhook fires, when Airbnb’s notification lands (usually within seconds). The response reports what Airbnb was asked to do. **Airbnb only**, and only for listings connected to Airbnb directly: other channels have no request step (`422 channel_not_supported`). A reservation that is not pending is refused before Airbnb is contacted (`409 reservation_not_pending`); one Airbnb says already moved on is `409 request_no_longer_pending`. Neither is worth retrying. Takes no body. Send `Idempotency-Key`: a repeat with the same key replays the first response instead of acting twice (a `409 idempotency_key_in_use` while the first is still running). A 5xx, a `429 airbnb_rate_limited` or a `403 connection_reauth_required` is not stored — nothing was done — so retrying with the same key reaches Airbnb again.
|
|
24
24
|
# @param id [Integer] Repull reservation id (from `GET /v1/reservations?status=pending`) — not the Airbnb confirmation code.
|
|
25
25
|
# @param [Hash] opts the optional parameters
|
|
26
26
|
# @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged `Idempotency-Status: cached` — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → `409 idempotency_key_in_use`. - Same key with a DIFFERENT payload → `422 idempotency_key_reused`. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status >= 500, `408`, `425` and `429`, and the refusals that happen before anything is done and tell you to fix something outside the request first — `connection_reauth_required`, `listing_inactive`, and the rate/daily limits. Every other answer, including a final refusal such as `422 airbnb_rejected`, is stored and replayed.
|
|
@@ -31,7 +31,7 @@ module Repull
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
# Accept a booking request
|
|
34
|
-
# Accept a pending Airbnb booking request — a reservation with status `pending`, made on a listing without Instant Book. Find them with `GET /v1/reservations?status=pending`. Airbnb expires a request the host has not answered within 24 hours.
|
|
34
|
+
# Accept a pending Airbnb booking request — a reservation with status `pending`, made on a listing without Instant Book. Find them with `GET /v1/reservations?status=pending`. Airbnb expires a request the host has not answered within 24 hours. Airbnb confirms asynchronously: the reservation’s status moves to confirmed, and a `reservation.updated` webhook fires, when Airbnb’s notification lands (usually within seconds). The response reports what Airbnb was asked to do. **Airbnb only**, and only for listings connected to Airbnb directly: other channels have no request step (`422 channel_not_supported`). A reservation that is not pending is refused before Airbnb is contacted (`409 reservation_not_pending`); one Airbnb says already moved on is `409 request_no_longer_pending`. Neither is worth retrying. Takes no body. Send `Idempotency-Key`: a repeat with the same key replays the first response instead of acting twice (a `409 idempotency_key_in_use` while the first is still running). A 5xx, a `429 airbnb_rate_limited` or a `403 connection_reauth_required` is not stored — nothing was done — so retrying with the same key reaches Airbnb again.
|
|
35
35
|
# @param id [Integer] Repull reservation id (from `GET /v1/reservations?status=pending`) — not the Airbnb confirmation code.
|
|
36
36
|
# @param [Hash] opts the optional parameters
|
|
37
37
|
# @option opts [String] :idempotency_key Makes a retry of this request safe. Send a unique string (a UUID generated at the point you build the request) and the response is stored for 24 hours: a repeat with the SAME key replays that stored response — tagged `Idempotency-Status: cached` — without running the operation again, so no duplicate reservation, guest or guest message is created. - Same key while the first request is still in flight → `409 idempotency_key_in_use`. - Same key with a DIFFERENT payload → `422 idempotency_key_reused`. Generate a new key per distinct request; reuse one only when retrying that exact request. - Retryable outcomes are deliberately not stored, so a retry with the same key runs for real: any status >= 500, `408`, `425` and `429`, and the refusals that happen before anything is done and tell you to fix something outside the request first — `connection_reauth_required`, `listing_inactive`, and the rate/daily limits. Every other answer, including a final refusal such as `422 airbnb_rejected`, is stored and replayed.
|
|
@@ -165,7 +165,7 @@ module Repull
|
|
|
165
165
|
end
|
|
166
166
|
|
|
167
167
|
# Decline a booking request
|
|
168
|
-
# Decline a pending Airbnb booking request (a reservation with status `pending`; find them with `GET /v1/reservations?status=pending`). `reason` must be one of Airbnb’s own decline reasons. `message` is required: Airbnb sends it to the guest with the decline (at most 500 characters). It is not defaulted — a canned message would put words in your mouth.
|
|
168
|
+
# Decline a pending Airbnb booking request (a reservation with status `pending`; find them with `GET /v1/reservations?status=pending`). `reason` must be one of Airbnb’s own decline reasons. `message` is required: Airbnb sends it to the guest with the decline (at most 500 characters). It is not defaulted — a canned message would put words in your mouth. Airbnb confirms asynchronously; the reservation’s status moves, and `reservation.updated` fires, when its notification lands. Same channel and status rules as `POST /v1/reservations/{id}/accept`. Send `Idempotency-Key`: a repeat with the same key replays the first response instead of acting twice (a `409 idempotency_key_in_use` while the first is still running). A 5xx, a `429 airbnb_rate_limited` or a `403 connection_reauth_required` is not stored — nothing was done — so retrying with the same key reaches Airbnb again.
|
|
169
169
|
# @param id [Integer] Repull reservation id (from `GET /v1/reservations?status=pending`) — not the Airbnb confirmation code.
|
|
170
170
|
# @param decline_reservation_request_request [DeclineReservationRequestRequest]
|
|
171
171
|
# @param [Hash] opts the optional parameters
|
|
@@ -177,7 +177,7 @@ module Repull
|
|
|
177
177
|
end
|
|
178
178
|
|
|
179
179
|
# Decline a booking request
|
|
180
|
-
# Decline a pending Airbnb booking request (a reservation with status `pending`; find them with `GET /v1/reservations?status=pending`). `reason` must be one of Airbnb’s own decline reasons. `message` is required: Airbnb sends it to the guest with the decline (at most 500 characters). It is not defaulted — a canned message would put words in your mouth.
|
|
180
|
+
# Decline a pending Airbnb booking request (a reservation with status `pending`; find them with `GET /v1/reservations?status=pending`). `reason` must be one of Airbnb’s own decline reasons. `message` is required: Airbnb sends it to the guest with the decline (at most 500 characters). It is not defaulted — a canned message would put words in your mouth. Airbnb confirms asynchronously; the reservation’s status moves, and `reservation.updated` fires, when its notification lands. Same channel and status rules as `POST /v1/reservations/{id}/accept`. Send `Idempotency-Key`: a repeat with the same key replays the first response instead of acting twice (a `409 idempotency_key_in_use` while the first is still running). A 5xx, a `429 airbnb_rate_limited` or a `403 connection_reauth_required` is not stored — nothing was done — so retrying with the same key reaches Airbnb again.
|
|
181
181
|
# @param id [Integer] Repull reservation id (from `GET /v1/reservations?status=pending`) — not the Airbnb confirmation code.
|
|
182
182
|
# @param decline_reservation_request_request [DeclineReservationRequestRequest]
|
|
183
183
|
# @param [Hash] opts the optional parameters
|
|
@@ -14,17 +14,23 @@ require 'date'
|
|
|
14
14
|
require 'time'
|
|
15
15
|
|
|
16
16
|
module Repull
|
|
17
|
-
# A publish is not one call to Airbnb: it is up to eight independent ones (details, description, amenities, rooms, policies, photos, pricing, checkout_tasks), each of which can fail on its own. A PARTIAL publish is normal — what succeeded stays applied; there is no rollback.
|
|
17
|
+
# A publish is not one call to Airbnb: it is up to eight independent ones (details, description, amenities, rooms, policies, photos, pricing, checkout_tasks), each of which can fail on its own. A PARTIAL publish is normal — what succeeded stays applied; there is no rollback. **Content landing and the listing being live are two different answers.** `published` is about content; `live` is about whether the listing takes bookings. Read both.
|
|
18
18
|
class AirbnbPublishResult < ApiModelBase
|
|
19
19
|
# True only when EVERY attempted section reached Airbnb.
|
|
20
20
|
attr_accessor :published
|
|
21
21
|
|
|
22
|
+
# Whether the listing is active and bookable on Airbnb — that is, whether activation was actually performed and succeeded. `published: true` with `live: false` is a real and common outcome: every content section landed, but the listing was never activated, because activation is skipped when instant-booking cannot be confirmed to be off. `warnings` says why. **Absent is not `false`.** The field is omitted entirely when activation was never part of the operation — publishing to an already-mapped Airbnb listing updates content and activates nothing, so there is nothing to report. Only treat the listing as not-live when `live` is present and false.
|
|
23
|
+
attr_accessor :live
|
|
24
|
+
|
|
22
25
|
# Sections that landed on Airbnb.
|
|
23
26
|
attr_accessor :sections
|
|
24
27
|
|
|
25
28
|
# Per-section failures. Empty when `published` is true.
|
|
26
29
|
attr_accessor :errors
|
|
27
30
|
|
|
31
|
+
# Steps that failed WITHOUT failing the publish — optional work the push carried on past, each in the push's own words. These used to be swallowed silently, so the only sign of one was a listing that was somehow not quite right afterwards. A publish can be `published: true` and still carry warnings; read them before concluding nothing needs doing.
|
|
32
|
+
attr_accessor :warnings
|
|
33
|
+
|
|
28
34
|
# Set when the publish never started at all (no connection, address missing, subscription gate).
|
|
29
35
|
attr_accessor :reason
|
|
30
36
|
|
|
@@ -35,8 +41,10 @@ module Repull
|
|
|
35
41
|
def self.attribute_map
|
|
36
42
|
{
|
|
37
43
|
:'published' => :'published',
|
|
44
|
+
:'live' => :'live',
|
|
38
45
|
:'sections' => :'sections',
|
|
39
46
|
:'errors' => :'errors',
|
|
47
|
+
:'warnings' => :'warnings',
|
|
40
48
|
:'reason' => :'reason',
|
|
41
49
|
:'locked_fields' => :'lockedFields'
|
|
42
50
|
}
|
|
@@ -56,8 +64,10 @@ module Repull
|
|
|
56
64
|
def self.openapi_types
|
|
57
65
|
{
|
|
58
66
|
:'published' => :'Boolean',
|
|
67
|
+
:'live' => :'Boolean',
|
|
59
68
|
:'sections' => :'Array<String>',
|
|
60
69
|
:'errors' => :'Array<PublishSectionError>',
|
|
70
|
+
:'warnings' => :'Array<String>',
|
|
61
71
|
:'reason' => :'String',
|
|
62
72
|
:'locked_fields' => :'Array<String>'
|
|
63
73
|
}
|
|
@@ -91,6 +101,10 @@ module Repull
|
|
|
91
101
|
self.published = nil
|
|
92
102
|
end
|
|
93
103
|
|
|
104
|
+
if attributes.key?(:'live')
|
|
105
|
+
self.live = attributes[:'live']
|
|
106
|
+
end
|
|
107
|
+
|
|
94
108
|
if attributes.key?(:'sections')
|
|
95
109
|
if (value = attributes[:'sections']).is_a?(Array)
|
|
96
110
|
self.sections = value
|
|
@@ -107,6 +121,14 @@ module Repull
|
|
|
107
121
|
self.errors = nil
|
|
108
122
|
end
|
|
109
123
|
|
|
124
|
+
if attributes.key?(:'warnings')
|
|
125
|
+
if (value = attributes[:'warnings']).is_a?(Array)
|
|
126
|
+
self.warnings = value
|
|
127
|
+
end
|
|
128
|
+
else
|
|
129
|
+
self.warnings = nil
|
|
130
|
+
end
|
|
131
|
+
|
|
110
132
|
if attributes.key?(:'reason')
|
|
111
133
|
self.reason = attributes[:'reason']
|
|
112
134
|
end
|
|
@@ -137,6 +159,10 @@ module Repull
|
|
|
137
159
|
invalid_properties.push('invalid value for "errors", errors cannot be nil.')
|
|
138
160
|
end
|
|
139
161
|
|
|
162
|
+
if @warnings.nil?
|
|
163
|
+
invalid_properties.push('invalid value for "warnings", warnings cannot be nil.')
|
|
164
|
+
end
|
|
165
|
+
|
|
140
166
|
if @locked_fields.nil?
|
|
141
167
|
invalid_properties.push('invalid value for "locked_fields", locked_fields cannot be nil.')
|
|
142
168
|
end
|
|
@@ -151,6 +177,7 @@ module Repull
|
|
|
151
177
|
return false if @published.nil?
|
|
152
178
|
return false if @sections.nil?
|
|
153
179
|
return false if @errors.nil?
|
|
180
|
+
return false if @warnings.nil?
|
|
154
181
|
return false if @locked_fields.nil?
|
|
155
182
|
true
|
|
156
183
|
end
|
|
@@ -185,6 +212,16 @@ module Repull
|
|
|
185
212
|
@errors = errors
|
|
186
213
|
end
|
|
187
214
|
|
|
215
|
+
# Custom attribute writer method with validation
|
|
216
|
+
# @param [Object] warnings Value to be assigned
|
|
217
|
+
def warnings=(warnings)
|
|
218
|
+
if warnings.nil?
|
|
219
|
+
fail ArgumentError, 'warnings cannot be nil'
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
@warnings = warnings
|
|
223
|
+
end
|
|
224
|
+
|
|
188
225
|
# Custom attribute writer method with validation
|
|
189
226
|
# @param [Object] locked_fields Value to be assigned
|
|
190
227
|
def locked_fields=(locked_fields)
|
|
@@ -201,8 +238,10 @@ module Repull
|
|
|
201
238
|
return true if self.equal?(o)
|
|
202
239
|
self.class == o.class &&
|
|
203
240
|
published == o.published &&
|
|
241
|
+
live == o.live &&
|
|
204
242
|
sections == o.sections &&
|
|
205
243
|
errors == o.errors &&
|
|
244
|
+
warnings == o.warnings &&
|
|
206
245
|
reason == o.reason &&
|
|
207
246
|
locked_fields == o.locked_fields
|
|
208
247
|
end
|
|
@@ -216,7 +255,7 @@ module Repull
|
|
|
216
255
|
# Calculates hash code according to all attributes.
|
|
217
256
|
# @return [Integer] Hash code
|
|
218
257
|
def hash
|
|
219
|
-
[published, sections, errors, reason, locked_fields].hash
|
|
258
|
+
[published, live, sections, errors, warnings, reason, locked_fields].hash
|
|
220
259
|
end
|
|
221
260
|
|
|
222
261
|
# Builds the object from hash
|