repull 0.2.33 → 0.2.35
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/connect_api.rb +4 -4
- data/lib/repull/api/health_api.rb +3 -3
- data/lib/repull/api/promotions_api.rb +574 -0
- data/lib/repull/models/connect_session_completed_payload.rb +1 -1
- data/lib/repull/models/connect_status_accounts_inner.rb +12 -1
- data/lib/repull/models/create_connect_session_request.rb +25 -1
- data/lib/repull/models/create_connection_request.rb +2 -22
- data/lib/repull/models/list_connection_units200_response.rb +12 -1
- data/lib/repull/models/list_connection_units200_response_units_inner.rb +1 -0
- data/lib/repull/models/listing_address.rb +62 -5
- data/lib/repull/models/listing_updated_payload.rb +2 -2
- data/lib/repull/models/message.rb +24 -1
- data/lib/repull/models/postal_address.rb +216 -0
- data/lib/repull/models/promotion.rb +344 -0
- data/lib/repull/models/promotion_applies_to.rb +161 -0
- data/lib/repull/models/promotion_bulk_request.rb +236 -0
- data/lib/repull/models/{plumguide_listing_list_response.rb → promotion_bulk_response.rb} +11 -11
- data/lib/repull/models/{calendar_updated_payload.rb → promotion_bulk_response_data_inner.rb} +23 -33
- data/lib/repull/models/promotion_bulk_response_data_inner_error.rb +165 -0
- data/lib/repull/models/promotion_bulk_response_summary.rb +156 -0
- data/lib/repull/models/{plumguide_listing.rb → promotion_catalog.rb} +18 -27
- data/lib/repull/models/promotion_catalog_channels_inner.rb +222 -0
- data/lib/repull/models/promotion_catalog_entry.rb +265 -0
- data/lib/repull/models/promotion_catalog_field.rb +205 -0
- data/lib/repull/models/{calendar_updated_payload_range.rb → promotion_catalog_field_options_inner.rb} +16 -16
- data/lib/repull/models/promotion_catalog_response.rb +147 -0
- data/lib/repull/models/promotion_create_request.rb +258 -0
- data/lib/repull/models/promotion_delete_response.rb +147 -0
- data/lib/repull/models/promotion_delete_response_data.rb +156 -0
- data/lib/repull/models/promotion_discount.rb +191 -0
- data/lib/repull/models/promotion_input.rb +241 -0
- data/lib/repull/models/promotion_list_response.rb +170 -0
- data/lib/repull/models/promotion_refresh_response.rb +170 -0
- data/lib/repull/models/promotion_response.rb +147 -0
- data/lib/repull/models/{calendar_updated_event.rb → promotion_rules.rb} +113 -104
- data/lib/repull/models/promotion_rules_blackout_dates_quota.rb +156 -0
- data/lib/repull/models/promotion_rules_booking_window.rb +230 -0
- data/lib/repull/models/promotion_rules_last_minute.rb +218 -0
- data/lib/repull/models/promotion_rules_stay_window.rb +211 -0
- data/lib/repull/models/promotion_type.rb +47 -0
- data/lib/repull/models/promotion_update_request.rb +175 -0
- data/lib/repull/models/promotion_usage.rb +193 -0
- data/lib/repull/models/promotion_usage_revenue.rb +156 -0
- data/lib/repull/models/property.rb +12 -2
- data/lib/repull/models/reservation_money_line.rb +14 -4
- data/lib/repull/models/webhook_event.rb +0 -2
- data/lib/repull/models/webhook_event_type.rb +1 -2
- data/lib/repull/version.rb +1 -1
- data/lib/repull.rb +32 -6
- data/openapi/v1.json +1193 -357
- data/scripts/regen.sh +1 -1
- metadata +34 -8
- data/lib/repull/api/plumguide_api.rb +0 -552
data/openapi/v1.json
CHANGED
|
@@ -110,14 +110,14 @@
|
|
|
110
110
|
"name": "VRBO",
|
|
111
111
|
"description": "VRBO channel management \u2014 listings and reservations"
|
|
112
112
|
},
|
|
113
|
-
{
|
|
114
|
-
"name": "Plumguide",
|
|
115
|
-
"description": "Plumguide channel management \u2014 availability, pricing, bookings"
|
|
116
|
-
},
|
|
117
113
|
{
|
|
118
114
|
"name": "AI",
|
|
119
115
|
"description": "AI-powered operations \u2014 guest responses, intent classification, listing generation, pricing suggestions"
|
|
120
116
|
},
|
|
117
|
+
{
|
|
118
|
+
"name": "Promotions",
|
|
119
|
+
"description": "Airbnb and Booking.com promotions on a listing, in one model: Airbnb\u2019s discount programmes (top-rated guests, mobile-only, new listing) and Booking.com deals, mobile and country rates and seasonal campaigns. Read the catalog first \u2014 it says, per channel, which types the listing can use and which fields each supports."
|
|
120
|
+
},
|
|
121
121
|
{
|
|
122
122
|
"name": "Pricing",
|
|
123
123
|
"description": "Atlas-powered pricing recommendations and per-listing strategy. Recommendations are pre-computed by the Atlas pricing model from comp data, demand signals, and event calendars; this surface lets you read them, apply or decline them, and tune the strategy that constrains the model."
|
|
@@ -186,12 +186,17 @@
|
|
|
186
186
|
"address": {
|
|
187
187
|
"type": "string",
|
|
188
188
|
"nullable": true,
|
|
189
|
-
"description": "Street
|
|
189
|
+
"description": "Street line only, as stored on the listing \u2014 no unit, state or postal code. Kept for existing integrations; read `addressDetails` for the full postal address.",
|
|
190
|
+
"example": "2700 Northwest 2nd Avenue"
|
|
190
191
|
},
|
|
191
192
|
"city": {
|
|
192
193
|
"type": "string",
|
|
193
194
|
"nullable": true,
|
|
194
|
-
"
|
|
195
|
+
"description": "City as stored on the listing. Kept for existing integrations; `addressDetails.city` is the resolved city.",
|
|
196
|
+
"example": "Miami"
|
|
197
|
+
},
|
|
198
|
+
"addressDetails": {
|
|
199
|
+
"$ref": "#/components/schemas/PostalAddress"
|
|
195
200
|
},
|
|
196
201
|
"latitude": {
|
|
197
202
|
"type": "string",
|
|
@@ -250,6 +255,55 @@
|
|
|
250
255
|
}
|
|
251
256
|
}
|
|
252
257
|
},
|
|
258
|
+
"PostalAddress": {
|
|
259
|
+
"type": "object",
|
|
260
|
+
"description": "The full postal address, unit included. Returned on every active row of `GET /v1/properties`, `GET /v1/properties/{id}`, `GET /v1/listings` and `GET /v1/listings/{id}` (on listings, these fields sit inside `address`). Each part is read from the listing first, then from the connected channels (Airbnb, Vrbo, Booking.com), so `line2` carries the apartment or unit number that tells units in the same building apart. A part nobody has stored is `null`.",
|
|
261
|
+
"required": [
|
|
262
|
+
"line1",
|
|
263
|
+
"line2",
|
|
264
|
+
"city",
|
|
265
|
+
"state",
|
|
266
|
+
"postalCode",
|
|
267
|
+
"countryCode"
|
|
268
|
+
],
|
|
269
|
+
"properties": {
|
|
270
|
+
"line1": {
|
|
271
|
+
"type": "string",
|
|
272
|
+
"nullable": true,
|
|
273
|
+
"description": "Street address: number and street.",
|
|
274
|
+
"example": "2700 Northwest 2nd Avenue"
|
|
275
|
+
},
|
|
276
|
+
"line2": {
|
|
277
|
+
"type": "string",
|
|
278
|
+
"nullable": true,
|
|
279
|
+
"description": "Apartment, unit, suite or building.",
|
|
280
|
+
"example": "Unit 241"
|
|
281
|
+
},
|
|
282
|
+
"city": {
|
|
283
|
+
"type": "string",
|
|
284
|
+
"nullable": true,
|
|
285
|
+
"example": "Miami"
|
|
286
|
+
},
|
|
287
|
+
"state": {
|
|
288
|
+
"type": "string",
|
|
289
|
+
"nullable": true,
|
|
290
|
+
"description": "State, province or region.",
|
|
291
|
+
"example": "FL"
|
|
292
|
+
},
|
|
293
|
+
"postalCode": {
|
|
294
|
+
"type": "string",
|
|
295
|
+
"nullable": true,
|
|
296
|
+
"description": "Postal or ZIP code.",
|
|
297
|
+
"example": "33127"
|
|
298
|
+
},
|
|
299
|
+
"countryCode": {
|
|
300
|
+
"type": "string",
|
|
301
|
+
"nullable": true,
|
|
302
|
+
"description": "ISO 3166-1 alpha-2 country code.",
|
|
303
|
+
"example": "US"
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
},
|
|
253
307
|
"PropertyAvailabilityDay": {
|
|
254
308
|
"type": "object",
|
|
255
309
|
"description": "One calendar day in the availability window.",
|
|
@@ -448,6 +502,10 @@
|
|
|
448
502
|
"type": "number",
|
|
449
503
|
"description": "VAT charged on top of this line, when the channel splits it out separately.",
|
|
450
504
|
"example": 0
|
|
505
|
+
},
|
|
506
|
+
"promotionType": {
|
|
507
|
+
"type": "string",
|
|
508
|
+
"description": "Discount lines only: the listing promotion that produced the discount, named as in `GET /v1/listings/{id}/promotions` (Airbnb reports each applied promotion as its own line). `custom` is an Airbnb Custom promotion."
|
|
451
509
|
}
|
|
452
510
|
}
|
|
453
511
|
},
|
|
@@ -1286,6 +1344,15 @@
|
|
|
1286
1344
|
"direction": {
|
|
1287
1345
|
"type": "string"
|
|
1288
1346
|
},
|
|
1347
|
+
"status": {
|
|
1348
|
+
"type": "string",
|
|
1349
|
+
"description": "Delivery state. Inbound messages are `received`. An outbound message is `sending` while it is queued to the channel, `sent` once the channel accepted it, or `failed`. Only `sent` (or `received`) means the guest can see it."
|
|
1350
|
+
},
|
|
1351
|
+
"statusReason": {
|
|
1352
|
+
"type": "string",
|
|
1353
|
+
"nullable": true,
|
|
1354
|
+
"description": "Why a message is still `sending` or `failed`, in plain words. `null` otherwise."
|
|
1355
|
+
},
|
|
1289
1356
|
"senderType": {
|
|
1290
1357
|
"type": "string",
|
|
1291
1358
|
"nullable": true,
|
|
@@ -1334,7 +1401,9 @@
|
|
|
1334
1401
|
},
|
|
1335
1402
|
"deliveredAt": {
|
|
1336
1403
|
"type": "string",
|
|
1337
|
-
"format": "date-time"
|
|
1404
|
+
"format": "date-time",
|
|
1405
|
+
"nullable": true,
|
|
1406
|
+
"description": "When the message reached the channel. `null` while it is `sending` or when it `failed`."
|
|
1338
1407
|
},
|
|
1339
1408
|
"readAt": {
|
|
1340
1409
|
"type": "string",
|
|
@@ -2238,6 +2307,11 @@
|
|
|
2238
2307
|
],
|
|
2239
2308
|
"description": "Vrbo only."
|
|
2240
2309
|
},
|
|
2310
|
+
"notificationEmail": {
|
|
2311
|
+
"type": "string",
|
|
2312
|
+
"nullable": true,
|
|
2313
|
+
"description": "Vrbo only. The address the host can add on Vrbo as a secondary email (with message and reservation notifications on) so new bookings, inquiries and messages arrive within a minute instead of at the scheduled check. Ask every host to add it: notifications are how Vrbo updates reach Repull, the scheduled check is the backup. Hosted Connect shows it on its mapping screen; show it in your own app when you create sessions with `mapping: \"api\"`."
|
|
2314
|
+
},
|
|
2241
2315
|
"import": {
|
|
2242
2316
|
"nullable": true,
|
|
2243
2317
|
"allOf": [
|
|
@@ -2682,7 +2756,6 @@
|
|
|
2682
2756
|
"listing.deleted",
|
|
2683
2757
|
"listing.suspended",
|
|
2684
2758
|
"listing.reactivated",
|
|
2685
|
-
"calendar.updated",
|
|
2686
2759
|
"account.created",
|
|
2687
2760
|
"connect.session.completed",
|
|
2688
2761
|
"account.disconnected",
|
|
@@ -3646,7 +3719,7 @@
|
|
|
3646
3719
|
},
|
|
3647
3720
|
"ListingUpdatedPayload": {
|
|
3648
3721
|
"type": "object",
|
|
3649
|
-
"description": "Payload for `listing.updated`. Something about the listing changed on the channel \u2014 content, pricing, booking settings, house rules, availability
|
|
3722
|
+
"description": "Payload for `listing.updated`. Something about the listing changed on the channel \u2014 content, pricing, booking settings, house rules, availability, sync settings or promotions.",
|
|
3650
3723
|
"required": [
|
|
3651
3724
|
"object"
|
|
3652
3725
|
],
|
|
@@ -3656,7 +3729,7 @@
|
|
|
3656
3729
|
},
|
|
3657
3730
|
"area": {
|
|
3658
3731
|
"type": "string",
|
|
3659
|
-
"description": "Which part moved. Airbnb sends one notification per area rather than a diff, so this is the signal for what to re-read.",
|
|
3732
|
+
"description": "Which part moved. Airbnb sends one notification per area rather than a diff, so this is the signal for what to re-read. `promotions`: the listing\u2019s Airbnb or Booking.com promotions changed \u2014 re-read `GET /v1/listings/{id}/promotions`.",
|
|
3660
3733
|
"example": "content"
|
|
3661
3734
|
},
|
|
3662
3735
|
"previousAttributes": {
|
|
@@ -3716,43 +3789,6 @@
|
|
|
3716
3789
|
}
|
|
3717
3790
|
}
|
|
3718
3791
|
},
|
|
3719
|
-
"CalendarUpdatedPayload": {
|
|
3720
|
-
"type": "object",
|
|
3721
|
-
"description": "Payload for `calendar.updated`. Availability or pricing for a listing was updated.",
|
|
3722
|
-
"properties": {
|
|
3723
|
-
"listingId": {
|
|
3724
|
-
"type": "integer",
|
|
3725
|
-
"example": 6250
|
|
3726
|
-
},
|
|
3727
|
-
"range": {
|
|
3728
|
-
"type": "object",
|
|
3729
|
-
"properties": {
|
|
3730
|
-
"start": {
|
|
3731
|
-
"type": "string",
|
|
3732
|
-
"format": "date",
|
|
3733
|
-
"example": "2026-06-01"
|
|
3734
|
-
},
|
|
3735
|
-
"end": {
|
|
3736
|
-
"type": "string",
|
|
3737
|
-
"format": "date",
|
|
3738
|
-
"example": "2026-06-15"
|
|
3739
|
-
}
|
|
3740
|
-
}
|
|
3741
|
-
},
|
|
3742
|
-
"affectedDates": {
|
|
3743
|
-
"type": "integer",
|
|
3744
|
-
"example": 14
|
|
3745
|
-
},
|
|
3746
|
-
"pricingChanged": {
|
|
3747
|
-
"type": "boolean",
|
|
3748
|
-
"example": true
|
|
3749
|
-
},
|
|
3750
|
-
"availabilityChanged": {
|
|
3751
|
-
"type": "boolean",
|
|
3752
|
-
"example": false
|
|
3753
|
-
}
|
|
3754
|
-
}
|
|
3755
|
-
},
|
|
3756
3792
|
"AccountCreatedPayload": {
|
|
3757
3793
|
"type": "object",
|
|
3758
3794
|
"description": "Payload for `account.created`. An OAuth or API credential connection was completed by an end user.",
|
|
@@ -3799,7 +3835,7 @@
|
|
|
3799
3835
|
"provider": {
|
|
3800
3836
|
"type": "string",
|
|
3801
3837
|
"nullable": true,
|
|
3802
|
-
"description": "Channel or PMS: airbnb, booking, booking_extranet, vrbo,
|
|
3838
|
+
"description": "Channel or PMS: airbnb, booking, booking_extranet, vrbo, hostaway, \u2026",
|
|
3803
3839
|
"example": "vrbo"
|
|
3804
3840
|
},
|
|
3805
3841
|
"externalAccountId": {
|
|
@@ -4834,42 +4870,6 @@
|
|
|
4834
4870
|
}
|
|
4835
4871
|
}
|
|
4836
4872
|
},
|
|
4837
|
-
"CalendarUpdatedEvent": {
|
|
4838
|
-
"type": "object",
|
|
4839
|
-
"required": [
|
|
4840
|
-
"event",
|
|
4841
|
-
"eventId",
|
|
4842
|
-
"apiVersion",
|
|
4843
|
-
"timestamp",
|
|
4844
|
-
"data"
|
|
4845
|
-
],
|
|
4846
|
-
"properties": {
|
|
4847
|
-
"event": {
|
|
4848
|
-
"type": "string",
|
|
4849
|
-
"description": "The event name. This field is `event`, not `type`."
|
|
4850
|
-
},
|
|
4851
|
-
"eventId": {
|
|
4852
|
-
"type": "string",
|
|
4853
|
-
"format": "uuid",
|
|
4854
|
-
"description": "Stable across every delivery and replay of this logical event \u2014 dedupe on it."
|
|
4855
|
-
},
|
|
4856
|
-
"apiVersion": {
|
|
4857
|
-
"type": "string",
|
|
4858
|
-
"example": "2026-04"
|
|
4859
|
-
},
|
|
4860
|
-
"timestamp": {
|
|
4861
|
-
"type": "string",
|
|
4862
|
-
"format": "date-time",
|
|
4863
|
-
"description": "When this delivery was built."
|
|
4864
|
-
},
|
|
4865
|
-
"account": {
|
|
4866
|
-
"$ref": "#/components/schemas/WebhookEventAccount"
|
|
4867
|
-
},
|
|
4868
|
-
"data": {
|
|
4869
|
-
"$ref": "#/components/schemas/CalendarUpdatedPayload"
|
|
4870
|
-
}
|
|
4871
|
-
}
|
|
4872
|
-
},
|
|
4873
4873
|
"AccountCreatedEvent": {
|
|
4874
4874
|
"type": "object",
|
|
4875
4875
|
"required": [
|
|
@@ -5762,9 +5762,6 @@
|
|
|
5762
5762
|
{
|
|
5763
5763
|
"$ref": "#/components/schemas/ListingReactivatedEvent"
|
|
5764
5764
|
},
|
|
5765
|
-
{
|
|
5766
|
-
"$ref": "#/components/schemas/CalendarUpdatedEvent"
|
|
5767
|
-
},
|
|
5768
5765
|
{
|
|
5769
5766
|
"$ref": "#/components/schemas/AccountCreatedEvent"
|
|
5770
5767
|
},
|
|
@@ -5837,7 +5834,6 @@
|
|
|
5837
5834
|
"listing.deleted": "#/components/schemas/ListingDeletedEvent",
|
|
5838
5835
|
"listing.suspended": "#/components/schemas/ListingSuspendedEvent",
|
|
5839
5836
|
"listing.reactivated": "#/components/schemas/ListingReactivatedEvent",
|
|
5840
|
-
"calendar.updated": "#/components/schemas/CalendarUpdatedEvent",
|
|
5841
5837
|
"account.created": "#/components/schemas/AccountCreatedEvent",
|
|
5842
5838
|
"connect.session.completed": "#/components/schemas/ConnectSessionCompletedEvent",
|
|
5843
5839
|
"account.disconnected": "#/components/schemas/AccountDisconnectedEvent",
|
|
@@ -6152,22 +6148,6 @@
|
|
|
6152
6148
|
}
|
|
6153
6149
|
}
|
|
6154
6150
|
},
|
|
6155
|
-
"PlumguideListing": {
|
|
6156
|
-
"type": "object",
|
|
6157
|
-
"description": "A Plumguide listing.",
|
|
6158
|
-
"properties": {
|
|
6159
|
-
"id": {
|
|
6160
|
-
"type": "string"
|
|
6161
|
-
},
|
|
6162
|
-
"name": {
|
|
6163
|
-
"type": "string"
|
|
6164
|
-
},
|
|
6165
|
-
"status": {
|
|
6166
|
-
"type": "string",
|
|
6167
|
-
"nullable": true
|
|
6168
|
-
}
|
|
6169
|
-
}
|
|
6170
|
-
},
|
|
6171
6151
|
"AirbnbReservation": {
|
|
6172
6152
|
"type": "object",
|
|
6173
6153
|
"description": "An Airbnb reservation as returned by the channel API. Use `confirmationCode` to address it in Airbnb operations.",
|
|
@@ -7031,8 +7011,7 @@
|
|
|
7031
7011
|
"example": [
|
|
7032
7012
|
"airbnb",
|
|
7033
7013
|
"booking",
|
|
7034
|
-
"vrbo"
|
|
7035
|
-
"plumguide"
|
|
7014
|
+
"vrbo"
|
|
7036
7015
|
]
|
|
7037
7016
|
},
|
|
7038
7017
|
"validParams": {
|
|
@@ -8000,20 +7979,6 @@
|
|
|
8000
7979
|
}
|
|
8001
7980
|
}
|
|
8002
7981
|
},
|
|
8003
|
-
"PlumguideListingListResponse": {
|
|
8004
|
-
"type": "object",
|
|
8005
|
-
"properties": {
|
|
8006
|
-
"data": {
|
|
8007
|
-
"type": "array",
|
|
8008
|
-
"items": {
|
|
8009
|
-
"$ref": "#/components/schemas/PlumguideListing"
|
|
8010
|
-
}
|
|
8011
|
-
},
|
|
8012
|
-
"pagination": {
|
|
8013
|
-
"$ref": "#/components/schemas/Pagination"
|
|
8014
|
-
}
|
|
8015
|
-
}
|
|
8016
|
-
},
|
|
8017
7982
|
"ListingCreateRequest": {
|
|
8018
7983
|
"type": "object",
|
|
8019
7984
|
"required": [
|
|
@@ -9549,14 +9514,48 @@
|
|
|
9549
9514
|
},
|
|
9550
9515
|
"address": {
|
|
9551
9516
|
"type": "object",
|
|
9517
|
+
"description": "The listing's postal address, unit included. Each part is read from the listing first, then from the connected channels (Airbnb, Vrbo, Booking.com). On an inactive row only `city` is present.",
|
|
9552
9518
|
"properties": {
|
|
9553
9519
|
"street": {
|
|
9554
9520
|
"type": "string",
|
|
9555
|
-
"nullable": true
|
|
9521
|
+
"nullable": true,
|
|
9522
|
+
"description": "Street line as stored on the listing. Kept for existing integrations; same value as `line1` unless the listing has no street of its own.",
|
|
9523
|
+
"example": "2700 Northwest 2nd Avenue"
|
|
9524
|
+
},
|
|
9525
|
+
"line1": {
|
|
9526
|
+
"type": "string",
|
|
9527
|
+
"nullable": true,
|
|
9528
|
+
"description": "Street address: number and street.",
|
|
9529
|
+
"example": "2700 Northwest 2nd Avenue"
|
|
9530
|
+
},
|
|
9531
|
+
"line2": {
|
|
9532
|
+
"type": "string",
|
|
9533
|
+
"nullable": true,
|
|
9534
|
+
"description": "Apartment, unit, suite or building.",
|
|
9535
|
+
"example": "Unit 241"
|
|
9556
9536
|
},
|
|
9557
9537
|
"city": {
|
|
9558
9538
|
"type": "string",
|
|
9559
|
-
"nullable": true
|
|
9539
|
+
"nullable": true,
|
|
9540
|
+
"example": "Miami"
|
|
9541
|
+
},
|
|
9542
|
+
"state": {
|
|
9543
|
+
"type": "string",
|
|
9544
|
+
"nullable": true,
|
|
9545
|
+
"description": "State, province or region.",
|
|
9546
|
+
"example": "FL"
|
|
9547
|
+
},
|
|
9548
|
+
"postalCode": {
|
|
9549
|
+
"type": "string",
|
|
9550
|
+
"nullable": true,
|
|
9551
|
+
"description": "Postal or ZIP code.",
|
|
9552
|
+
"example": "33127"
|
|
9553
|
+
},
|
|
9554
|
+
"countryCode": {
|
|
9555
|
+
"type": "string",
|
|
9556
|
+
"nullable": true,
|
|
9557
|
+
"description": "ISO 3166-1 alpha-2 country code.",
|
|
9558
|
+
"example": "US"
|
|
9560
9559
|
}
|
|
9561
9560
|
}
|
|
9562
9561
|
},
|
|
@@ -9692,6 +9691,624 @@
|
|
|
9692
9691
|
}
|
|
9693
9692
|
}
|
|
9694
9693
|
},
|
|
9694
|
+
"Promotion": {
|
|
9695
|
+
"type": "object",
|
|
9696
|
+
"description": "One promotion on one listing. Airbnb sets the discount for its promotions (`discount.setBy: channel`); Booking.com promotions belong to the property and list the rooms they cover in `appliesTo`.",
|
|
9697
|
+
"properties": {
|
|
9698
|
+
"id": {
|
|
9699
|
+
"type": "string",
|
|
9700
|
+
"description": "Repull id of this promotion on this listing (use it in `/promotions/{promotionId}`)."
|
|
9701
|
+
},
|
|
9702
|
+
"listingId": {
|
|
9703
|
+
"type": "string"
|
|
9704
|
+
},
|
|
9705
|
+
"channel": {
|
|
9706
|
+
"type": "string"
|
|
9707
|
+
},
|
|
9708
|
+
"type": {
|
|
9709
|
+
"$ref": "#/components/schemas/PromotionType"
|
|
9710
|
+
},
|
|
9711
|
+
"channelType": {
|
|
9712
|
+
"type": "string",
|
|
9713
|
+
"description": "The channel\u2019s own name, e.g. `HIGH_RATED_GUEST_DISCOUNT`, `basic`, `campaign_getaway`."
|
|
9714
|
+
},
|
|
9715
|
+
"externalId": {
|
|
9716
|
+
"type": "string",
|
|
9717
|
+
"description": "The channel\u2019s promotion id. Booking.com may issue a new one when a promotion is changed; the Repull `id` stays the same."
|
|
9718
|
+
},
|
|
9719
|
+
"channelPropertyId": {
|
|
9720
|
+
"type": "string",
|
|
9721
|
+
"description": "Airbnb listing id, or the Booking.com property (hotel id) the promotion belongs to."
|
|
9722
|
+
},
|
|
9723
|
+
"name": {
|
|
9724
|
+
"type": "string",
|
|
9725
|
+
"nullable": true
|
|
9726
|
+
},
|
|
9727
|
+
"status": {
|
|
9728
|
+
"type": "string",
|
|
9729
|
+
"description": "`eligible`: the listing qualifies but is not enrolled (Airbnb new listing promotion). `inactive`: switched off; Booking.com keeps deactivated promotions."
|
|
9730
|
+
},
|
|
9731
|
+
"managedBy": {
|
|
9732
|
+
"type": "string",
|
|
9733
|
+
"description": "`channel`: created in the channel\u2019s own tools and read-only here (Airbnb Custom promotions)."
|
|
9734
|
+
},
|
|
9735
|
+
"managedKey": {
|
|
9736
|
+
"type": "string",
|
|
9737
|
+
"nullable": true,
|
|
9738
|
+
"description": "Set when it comes from the listing\u2019s weekly or monthly discount in its pricing settings \u2014 change those instead."
|
|
9739
|
+
},
|
|
9740
|
+
"editable": {
|
|
9741
|
+
"type": "boolean"
|
|
9742
|
+
},
|
|
9743
|
+
"removable": {
|
|
9744
|
+
"type": "boolean"
|
|
9745
|
+
},
|
|
9746
|
+
"discount": {
|
|
9747
|
+
"type": "object",
|
|
9748
|
+
"properties": {
|
|
9749
|
+
"percent": {
|
|
9750
|
+
"type": "number",
|
|
9751
|
+
"nullable": true
|
|
9752
|
+
},
|
|
9753
|
+
"setBy": {
|
|
9754
|
+
"type": "string",
|
|
9755
|
+
"enum": [
|
|
9756
|
+
"host",
|
|
9757
|
+
"channel"
|
|
9758
|
+
]
|
|
9759
|
+
}
|
|
9760
|
+
}
|
|
9761
|
+
},
|
|
9762
|
+
"rules": {
|
|
9763
|
+
"$ref": "#/components/schemas/PromotionRules"
|
|
9764
|
+
},
|
|
9765
|
+
"appliesTo": {
|
|
9766
|
+
"type": "object",
|
|
9767
|
+
"nullable": true,
|
|
9768
|
+
"description": "Booking.com only. An empty `rooms` list means every room on the property.",
|
|
9769
|
+
"properties": {
|
|
9770
|
+
"rooms": {
|
|
9771
|
+
"type": "array",
|
|
9772
|
+
"items": {
|
|
9773
|
+
"type": "string"
|
|
9774
|
+
}
|
|
9775
|
+
},
|
|
9776
|
+
"ratePlans": {
|
|
9777
|
+
"type": "array",
|
|
9778
|
+
"items": {
|
|
9779
|
+
"type": "string"
|
|
9780
|
+
}
|
|
9781
|
+
}
|
|
9782
|
+
}
|
|
9783
|
+
},
|
|
9784
|
+
"usage": {
|
|
9785
|
+
"type": "object",
|
|
9786
|
+
"nullable": true,
|
|
9787
|
+
"properties": {
|
|
9788
|
+
"bookings": {
|
|
9789
|
+
"type": "integer"
|
|
9790
|
+
},
|
|
9791
|
+
"roomNights": {
|
|
9792
|
+
"type": "integer"
|
|
9793
|
+
},
|
|
9794
|
+
"cancellations": {
|
|
9795
|
+
"type": "integer"
|
|
9796
|
+
},
|
|
9797
|
+
"revenue": {
|
|
9798
|
+
"type": "object",
|
|
9799
|
+
"properties": {
|
|
9800
|
+
"amount": {
|
|
9801
|
+
"type": "number"
|
|
9802
|
+
},
|
|
9803
|
+
"currency": {
|
|
9804
|
+
"type": "string"
|
|
9805
|
+
}
|
|
9806
|
+
}
|
|
9807
|
+
},
|
|
9808
|
+
"lastAppliedAt": {
|
|
9809
|
+
"type": "string",
|
|
9810
|
+
"format": "date-time",
|
|
9811
|
+
"description": "Airbnb Custom promotion: when it was last applied to a booking."
|
|
9812
|
+
},
|
|
9813
|
+
"lastAppliedAmount": {
|
|
9814
|
+
"type": "object",
|
|
9815
|
+
"properties": {
|
|
9816
|
+
"amount": {
|
|
9817
|
+
"type": "number"
|
|
9818
|
+
},
|
|
9819
|
+
"currency": {
|
|
9820
|
+
"type": "string"
|
|
9821
|
+
}
|
|
9822
|
+
}
|
|
9823
|
+
}
|
|
9824
|
+
}
|
|
9825
|
+
},
|
|
9826
|
+
"expiresAt": {
|
|
9827
|
+
"type": "string",
|
|
9828
|
+
"format": "date-time",
|
|
9829
|
+
"nullable": true
|
|
9830
|
+
},
|
|
9831
|
+
"syncedAt": {
|
|
9832
|
+
"type": "string",
|
|
9833
|
+
"format": "date-time"
|
|
9834
|
+
}
|
|
9835
|
+
}
|
|
9836
|
+
},
|
|
9837
|
+
"PromotionType": {
|
|
9838
|
+
"type": "string",
|
|
9839
|
+
"enum": [
|
|
9840
|
+
"new_listing",
|
|
9841
|
+
"mobile",
|
|
9842
|
+
"top_rated_guests",
|
|
9843
|
+
"deal",
|
|
9844
|
+
"last_minute",
|
|
9845
|
+
"early_booker",
|
|
9846
|
+
"country",
|
|
9847
|
+
"campaign",
|
|
9848
|
+
"custom"
|
|
9849
|
+
],
|
|
9850
|
+
"description": "The same idea on both channels shares a type: `mobile` is Airbnb\u2019s mobile-only discount or Booking.com\u2019s mobile rate; `new_listing` is Airbnb\u2019s new listing promotion or Booking.com\u2019s new property deal. `top_rated_guests` is Airbnb only; the deal, last-minute, early-booker, country and campaign types are Booking.com only; `custom` (Airbnb Custom promotion) is read-only."
|
|
9851
|
+
},
|
|
9852
|
+
"PromotionRules": {
|
|
9853
|
+
"type": "object",
|
|
9854
|
+
"description": "Which rules a type supports depends on the channel \u2014 see the catalog.",
|
|
9855
|
+
"properties": {
|
|
9856
|
+
"campaign": {
|
|
9857
|
+
"type": "string",
|
|
9858
|
+
"description": "Booking.com campaigns: `black_friday`, `getaway`, `late_escape`, `early_year`."
|
|
9859
|
+
},
|
|
9860
|
+
"audience": {
|
|
9861
|
+
"type": "string",
|
|
9862
|
+
"description": "`public`, `subscribers` (members only, at least 10%), `app`, `all` (app and mobile web), or a country id from the catalog (e.g. `united_kingdom_pos`)."
|
|
9863
|
+
},
|
|
9864
|
+
"stayWindow": {
|
|
9865
|
+
"type": "object",
|
|
9866
|
+
"properties": {
|
|
9867
|
+
"start": {
|
|
9868
|
+
"type": "string",
|
|
9869
|
+
"format": "date"
|
|
9870
|
+
},
|
|
9871
|
+
"end": {
|
|
9872
|
+
"type": "string",
|
|
9873
|
+
"format": "date"
|
|
9874
|
+
},
|
|
9875
|
+
"weekdays": {
|
|
9876
|
+
"type": "array",
|
|
9877
|
+
"items": {
|
|
9878
|
+
"type": "string",
|
|
9879
|
+
"enum": [
|
|
9880
|
+
"mon",
|
|
9881
|
+
"tue",
|
|
9882
|
+
"wed",
|
|
9883
|
+
"thu",
|
|
9884
|
+
"fri",
|
|
9885
|
+
"sat",
|
|
9886
|
+
"sun"
|
|
9887
|
+
]
|
|
9888
|
+
}
|
|
9889
|
+
},
|
|
9890
|
+
"excludedDates": {
|
|
9891
|
+
"type": "array",
|
|
9892
|
+
"items": {
|
|
9893
|
+
"type": "string",
|
|
9894
|
+
"format": "date"
|
|
9895
|
+
}
|
|
9896
|
+
},
|
|
9897
|
+
"additionalDates": {
|
|
9898
|
+
"type": "array",
|
|
9899
|
+
"items": {
|
|
9900
|
+
"type": "string",
|
|
9901
|
+
"format": "date"
|
|
9902
|
+
}
|
|
9903
|
+
}
|
|
9904
|
+
}
|
|
9905
|
+
},
|
|
9906
|
+
"bookingWindow": {
|
|
9907
|
+
"type": "object",
|
|
9908
|
+
"properties": {
|
|
9909
|
+
"start": {
|
|
9910
|
+
"type": "string",
|
|
9911
|
+
"format": "date"
|
|
9912
|
+
},
|
|
9913
|
+
"end": {
|
|
9914
|
+
"type": "string",
|
|
9915
|
+
"format": "date"
|
|
9916
|
+
},
|
|
9917
|
+
"startHour": {
|
|
9918
|
+
"type": "integer",
|
|
9919
|
+
"minimum": 0,
|
|
9920
|
+
"maximum": 23
|
|
9921
|
+
},
|
|
9922
|
+
"endHour": {
|
|
9923
|
+
"type": "integer",
|
|
9924
|
+
"minimum": 0,
|
|
9925
|
+
"maximum": 23
|
|
9926
|
+
}
|
|
9927
|
+
}
|
|
9928
|
+
},
|
|
9929
|
+
"lastMinute": {
|
|
9930
|
+
"type": "object",
|
|
9931
|
+
"properties": {
|
|
9932
|
+
"unit": {
|
|
9933
|
+
"type": "string",
|
|
9934
|
+
"enum": [
|
|
9935
|
+
"day",
|
|
9936
|
+
"hour"
|
|
9937
|
+
]
|
|
9938
|
+
},
|
|
9939
|
+
"value": {
|
|
9940
|
+
"type": "integer",
|
|
9941
|
+
"minimum": 1,
|
|
9942
|
+
"maximum": 1000
|
|
9943
|
+
}
|
|
9944
|
+
}
|
|
9945
|
+
},
|
|
9946
|
+
"earlyBookerDays": {
|
|
9947
|
+
"type": "integer",
|
|
9948
|
+
"minimum": 1,
|
|
9949
|
+
"maximum": 500
|
|
9950
|
+
},
|
|
9951
|
+
"minNights": {
|
|
9952
|
+
"type": "integer",
|
|
9953
|
+
"minimum": 0,
|
|
9954
|
+
"maximum": 30
|
|
9955
|
+
},
|
|
9956
|
+
"nonRefundable": {
|
|
9957
|
+
"type": "boolean"
|
|
9958
|
+
},
|
|
9959
|
+
"blackoutDates": {
|
|
9960
|
+
"type": "array",
|
|
9961
|
+
"items": {
|
|
9962
|
+
"type": "string",
|
|
9963
|
+
"format": "date"
|
|
9964
|
+
},
|
|
9965
|
+
"description": "Airbnb \u2014 not yet available."
|
|
9966
|
+
},
|
|
9967
|
+
"blackoutDatesQuota": {
|
|
9968
|
+
"type": "object",
|
|
9969
|
+
"properties": {
|
|
9970
|
+
"used": {
|
|
9971
|
+
"type": "integer"
|
|
9972
|
+
},
|
|
9973
|
+
"available": {
|
|
9974
|
+
"type": "integer"
|
|
9975
|
+
}
|
|
9976
|
+
}
|
|
9977
|
+
}
|
|
9978
|
+
}
|
|
9979
|
+
},
|
|
9980
|
+
"PromotionInput": {
|
|
9981
|
+
"type": "object",
|
|
9982
|
+
"required": [
|
|
9983
|
+
"channel",
|
|
9984
|
+
"type"
|
|
9985
|
+
],
|
|
9986
|
+
"properties": {
|
|
9987
|
+
"channel": {
|
|
9988
|
+
"type": "string"
|
|
9989
|
+
},
|
|
9990
|
+
"type": {
|
|
9991
|
+
"$ref": "#/components/schemas/PromotionType"
|
|
9992
|
+
},
|
|
9993
|
+
"name": {
|
|
9994
|
+
"type": "string",
|
|
9995
|
+
"description": "Booking.com only; only you see it."
|
|
9996
|
+
},
|
|
9997
|
+
"discountPercent": {
|
|
9998
|
+
"type": "integer",
|
|
9999
|
+
"description": "Booking.com only \u2014 Airbnb sets its own rates. Limits per type are in the catalog."
|
|
10000
|
+
},
|
|
10001
|
+
"rules": {
|
|
10002
|
+
"$ref": "#/components/schemas/PromotionRules"
|
|
10003
|
+
}
|
|
10004
|
+
}
|
|
10005
|
+
},
|
|
10006
|
+
"PromotionCreateRequest": {
|
|
10007
|
+
"allOf": [
|
|
10008
|
+
{
|
|
10009
|
+
"$ref": "#/components/schemas/PromotionInput"
|
|
10010
|
+
},
|
|
10011
|
+
{
|
|
10012
|
+
"type": "object",
|
|
10013
|
+
"properties": {
|
|
10014
|
+
"hotelId": {
|
|
10015
|
+
"type": "string",
|
|
10016
|
+
"description": "Booking.com: required when the listing has a room on more than one property (see `properties` in the catalog)."
|
|
10017
|
+
}
|
|
10018
|
+
}
|
|
10019
|
+
}
|
|
10020
|
+
]
|
|
10021
|
+
},
|
|
10022
|
+
"PromotionUpdateRequest": {
|
|
10023
|
+
"type": "object",
|
|
10024
|
+
"properties": {
|
|
10025
|
+
"name": {
|
|
10026
|
+
"type": "string"
|
|
10027
|
+
},
|
|
10028
|
+
"discountPercent": {
|
|
10029
|
+
"type": "integer"
|
|
10030
|
+
},
|
|
10031
|
+
"rules": {
|
|
10032
|
+
"$ref": "#/components/schemas/PromotionRules"
|
|
10033
|
+
},
|
|
10034
|
+
"confirmShared": {
|
|
10035
|
+
"type": "boolean",
|
|
10036
|
+
"description": "Required when the promotion also covers other listings\u2019 rooms \u2014 the change applies to them too."
|
|
10037
|
+
}
|
|
10038
|
+
}
|
|
10039
|
+
},
|
|
10040
|
+
"PromotionCatalogField": {
|
|
10041
|
+
"type": "object",
|
|
10042
|
+
"properties": {
|
|
10043
|
+
"supported": {
|
|
10044
|
+
"type": "boolean"
|
|
10045
|
+
},
|
|
10046
|
+
"comingSoon": {
|
|
10047
|
+
"type": "boolean",
|
|
10048
|
+
"description": "Shown but not yet usable on this channel."
|
|
10049
|
+
},
|
|
10050
|
+
"required": {
|
|
10051
|
+
"type": "boolean"
|
|
10052
|
+
},
|
|
10053
|
+
"min": {
|
|
10054
|
+
"type": "number"
|
|
10055
|
+
},
|
|
10056
|
+
"max": {
|
|
10057
|
+
"type": "number"
|
|
10058
|
+
},
|
|
10059
|
+
"fixed": {
|
|
10060
|
+
"type": "number",
|
|
10061
|
+
"description": "Value the channel sets (e.g. Airbnb\u2019s 15% top-rated-guests discount)."
|
|
10062
|
+
},
|
|
10063
|
+
"options": {
|
|
10064
|
+
"type": "array",
|
|
10065
|
+
"items": {
|
|
10066
|
+
"type": "object",
|
|
10067
|
+
"properties": {
|
|
10068
|
+
"id": {
|
|
10069
|
+
"type": "string"
|
|
10070
|
+
},
|
|
10071
|
+
"label": {
|
|
10072
|
+
"type": "string"
|
|
10073
|
+
}
|
|
10074
|
+
}
|
|
10075
|
+
}
|
|
10076
|
+
}
|
|
10077
|
+
}
|
|
10078
|
+
},
|
|
10079
|
+
"PromotionCatalogEntry": {
|
|
10080
|
+
"type": "object",
|
|
10081
|
+
"properties": {
|
|
10082
|
+
"channel": {
|
|
10083
|
+
"type": "string"
|
|
10084
|
+
},
|
|
10085
|
+
"type": {
|
|
10086
|
+
"$ref": "#/components/schemas/PromotionType"
|
|
10087
|
+
},
|
|
10088
|
+
"channelType": {
|
|
10089
|
+
"type": "string"
|
|
10090
|
+
},
|
|
10091
|
+
"campaign": {
|
|
10092
|
+
"type": "string"
|
|
10093
|
+
},
|
|
10094
|
+
"label": {
|
|
10095
|
+
"type": "string"
|
|
10096
|
+
},
|
|
10097
|
+
"description": {
|
|
10098
|
+
"type": "string",
|
|
10099
|
+
"description": "One or two sentences to show hosts."
|
|
10100
|
+
},
|
|
10101
|
+
"isNew": {
|
|
10102
|
+
"type": "boolean",
|
|
10103
|
+
"description": "Newly available \u2014 show a \u201cNew\u201d badge."
|
|
10104
|
+
},
|
|
10105
|
+
"available": {
|
|
10106
|
+
"type": "boolean"
|
|
10107
|
+
},
|
|
10108
|
+
"unavailableReason": {
|
|
10109
|
+
"type": "string"
|
|
10110
|
+
},
|
|
10111
|
+
"single": {
|
|
10112
|
+
"type": "boolean",
|
|
10113
|
+
"description": "Only one at a time (Airbnb types; Booking.com mobile and country rates per property)."
|
|
10114
|
+
},
|
|
10115
|
+
"fields": {
|
|
10116
|
+
"type": "object",
|
|
10117
|
+
"description": "Every field, supported or not, so a UI can grey out what a type does not take.",
|
|
10118
|
+
"additionalProperties": {
|
|
10119
|
+
"$ref": "#/components/schemas/PromotionCatalogField"
|
|
10120
|
+
}
|
|
10121
|
+
}
|
|
10122
|
+
}
|
|
10123
|
+
},
|
|
10124
|
+
"PromotionCatalog": {
|
|
10125
|
+
"type": "object",
|
|
10126
|
+
"properties": {
|
|
10127
|
+
"listingId": {
|
|
10128
|
+
"type": "string"
|
|
10129
|
+
},
|
|
10130
|
+
"channels": {
|
|
10131
|
+
"type": "array",
|
|
10132
|
+
"items": {
|
|
10133
|
+
"type": "object",
|
|
10134
|
+
"properties": {
|
|
10135
|
+
"channel": {
|
|
10136
|
+
"type": "string",
|
|
10137
|
+
"enum": [
|
|
10138
|
+
"airbnb",
|
|
10139
|
+
"booking"
|
|
10140
|
+
]
|
|
10141
|
+
},
|
|
10142
|
+
"connected": {
|
|
10143
|
+
"type": "boolean"
|
|
10144
|
+
},
|
|
10145
|
+
"reason": {
|
|
10146
|
+
"type": "string"
|
|
10147
|
+
},
|
|
10148
|
+
"properties": {
|
|
10149
|
+
"type": "array",
|
|
10150
|
+
"items": {
|
|
10151
|
+
"type": "string"
|
|
10152
|
+
},
|
|
10153
|
+
"description": "Booking.com properties the listing has a room on."
|
|
10154
|
+
},
|
|
10155
|
+
"entries": {
|
|
10156
|
+
"type": "array",
|
|
10157
|
+
"items": {
|
|
10158
|
+
"$ref": "#/components/schemas/PromotionCatalogEntry"
|
|
10159
|
+
}
|
|
10160
|
+
}
|
|
10161
|
+
}
|
|
10162
|
+
}
|
|
10163
|
+
}
|
|
10164
|
+
}
|
|
10165
|
+
},
|
|
10166
|
+
"PromotionListResponse": {
|
|
10167
|
+
"type": "object",
|
|
10168
|
+
"properties": {
|
|
10169
|
+
"data": {
|
|
10170
|
+
"type": "array",
|
|
10171
|
+
"items": {
|
|
10172
|
+
"$ref": "#/components/schemas/Promotion"
|
|
10173
|
+
}
|
|
10174
|
+
},
|
|
10175
|
+
"syncedAt": {
|
|
10176
|
+
"type": "string",
|
|
10177
|
+
"format": "date-time",
|
|
10178
|
+
"nullable": true,
|
|
10179
|
+
"description": "When the channels were last read for this listing."
|
|
10180
|
+
},
|
|
10181
|
+
"syncError": {
|
|
10182
|
+
"type": "string",
|
|
10183
|
+
"nullable": true
|
|
10184
|
+
}
|
|
10185
|
+
}
|
|
10186
|
+
},
|
|
10187
|
+
"PromotionResponse": {
|
|
10188
|
+
"type": "object",
|
|
10189
|
+
"properties": {
|
|
10190
|
+
"data": {
|
|
10191
|
+
"$ref": "#/components/schemas/Promotion"
|
|
10192
|
+
}
|
|
10193
|
+
}
|
|
10194
|
+
},
|
|
10195
|
+
"PromotionDeleteResponse": {
|
|
10196
|
+
"type": "object",
|
|
10197
|
+
"properties": {
|
|
10198
|
+
"data": {
|
|
10199
|
+
"type": "object",
|
|
10200
|
+
"properties": {
|
|
10201
|
+
"removed": {
|
|
10202
|
+
"type": "boolean"
|
|
10203
|
+
},
|
|
10204
|
+
"promotionId": {
|
|
10205
|
+
"type": "string"
|
|
10206
|
+
}
|
|
10207
|
+
}
|
|
10208
|
+
}
|
|
10209
|
+
}
|
|
10210
|
+
},
|
|
10211
|
+
"PromotionCatalogResponse": {
|
|
10212
|
+
"type": "object",
|
|
10213
|
+
"properties": {
|
|
10214
|
+
"data": {
|
|
10215
|
+
"$ref": "#/components/schemas/PromotionCatalog"
|
|
10216
|
+
}
|
|
10217
|
+
}
|
|
10218
|
+
},
|
|
10219
|
+
"PromotionRefreshResponse": {
|
|
10220
|
+
"type": "object",
|
|
10221
|
+
"properties": {
|
|
10222
|
+
"data": {
|
|
10223
|
+
"type": "array",
|
|
10224
|
+
"items": {
|
|
10225
|
+
"$ref": "#/components/schemas/Promotion"
|
|
10226
|
+
}
|
|
10227
|
+
},
|
|
10228
|
+
"syncedAt": {
|
|
10229
|
+
"type": "string",
|
|
10230
|
+
"format": "date-time",
|
|
10231
|
+
"nullable": true
|
|
10232
|
+
},
|
|
10233
|
+
"errors": {
|
|
10234
|
+
"type": "array",
|
|
10235
|
+
"items": {
|
|
10236
|
+
"type": "string"
|
|
10237
|
+
}
|
|
10238
|
+
}
|
|
10239
|
+
}
|
|
10240
|
+
},
|
|
10241
|
+
"PromotionBulkRequest": {
|
|
10242
|
+
"type": "object",
|
|
10243
|
+
"required": [
|
|
10244
|
+
"listingIds",
|
|
10245
|
+
"action",
|
|
10246
|
+
"promotion"
|
|
10247
|
+
],
|
|
10248
|
+
"properties": {
|
|
10249
|
+
"listingIds": {
|
|
10250
|
+
"type": "array",
|
|
10251
|
+
"items": {
|
|
10252
|
+
"type": "integer"
|
|
10253
|
+
},
|
|
10254
|
+
"minItems": 1,
|
|
10255
|
+
"maxItems": 100
|
|
10256
|
+
},
|
|
10257
|
+
"action": {
|
|
10258
|
+
"type": "string"
|
|
10259
|
+
},
|
|
10260
|
+
"promotion": {
|
|
10261
|
+
"$ref": "#/components/schemas/PromotionInput"
|
|
10262
|
+
}
|
|
10263
|
+
}
|
|
10264
|
+
},
|
|
10265
|
+
"PromotionBulkResponse": {
|
|
10266
|
+
"type": "object",
|
|
10267
|
+
"properties": {
|
|
10268
|
+
"data": {
|
|
10269
|
+
"type": "array",
|
|
10270
|
+
"items": {
|
|
10271
|
+
"type": "object",
|
|
10272
|
+
"properties": {
|
|
10273
|
+
"listingId": {
|
|
10274
|
+
"type": "string"
|
|
10275
|
+
},
|
|
10276
|
+
"ok": {
|
|
10277
|
+
"type": "boolean"
|
|
10278
|
+
},
|
|
10279
|
+
"promotion": {
|
|
10280
|
+
"$ref": "#/components/schemas/Promotion"
|
|
10281
|
+
},
|
|
10282
|
+
"error": {
|
|
10283
|
+
"type": "object",
|
|
10284
|
+
"properties": {
|
|
10285
|
+
"message": {
|
|
10286
|
+
"type": "string"
|
|
10287
|
+
},
|
|
10288
|
+
"code": {
|
|
10289
|
+
"type": "string"
|
|
10290
|
+
},
|
|
10291
|
+
"field": {
|
|
10292
|
+
"type": "string"
|
|
10293
|
+
}
|
|
10294
|
+
}
|
|
10295
|
+
}
|
|
10296
|
+
}
|
|
10297
|
+
}
|
|
10298
|
+
},
|
|
10299
|
+
"summary": {
|
|
10300
|
+
"type": "object",
|
|
10301
|
+
"properties": {
|
|
10302
|
+
"succeeded": {
|
|
10303
|
+
"type": "integer"
|
|
10304
|
+
},
|
|
10305
|
+
"failed": {
|
|
10306
|
+
"type": "integer"
|
|
10307
|
+
}
|
|
10308
|
+
}
|
|
10309
|
+
}
|
|
10310
|
+
}
|
|
10311
|
+
},
|
|
9695
10312
|
"ListingPricingResponse": {
|
|
9696
10313
|
"type": "object",
|
|
9697
10314
|
"properties": {
|
|
@@ -17653,6 +18270,15 @@
|
|
|
17653
18270
|
"example": 24,
|
|
17654
18271
|
"description": "Airbnb \u2014 how many months of past reservations the first import pulls (1\u201360). Omit it for the default window. Upcoming stays are always imported. A wider window takes longer to import, because every extra month is more stays to fetch."
|
|
17655
18272
|
},
|
|
18273
|
+
"mapping": {
|
|
18274
|
+
"type": "string",
|
|
18275
|
+
"enum": [
|
|
18276
|
+
"hosted",
|
|
18277
|
+
"api"
|
|
18278
|
+
],
|
|
18279
|
+
"default": "hosted",
|
|
18280
|
+
"description": "Where the channel's units get linked to listings. `hosted` (default): after a Vrbo or Booking.com Extranet sign-in, Connect shows a mapping step and returns to `redirectUrl` when it's confirmed. `api`: Connect skips that step and finishes right after sign-in. The connection reaches you in the `connect.session.completed` webhook (and as `connectionId` in the popup message), its handle is `vrbo:{connectionId}` or `booking_extranet:{connectionId}`; you list the units with `GET /v1/connections/{id}/units` and link them with `POST /v1/connections/{id}/mappings`. Nothing is imported until you post the mappings. Other providers ignore it."
|
|
18281
|
+
},
|
|
17656
18282
|
"accessType": {
|
|
17657
18283
|
"type": "string",
|
|
17658
18284
|
"enum": [
|
|
@@ -17891,7 +18517,7 @@
|
|
|
17891
18517
|
"post": {
|
|
17892
18518
|
"operationId": "create_connection",
|
|
17893
18519
|
"summary": "Connect to PMS/OTA provider",
|
|
17894
|
-
"description": "Establish a connection to a PMS or OTA platform. Credentials vary by provider \u2014 see docs for each provider.\n\nAirbnb-specific: pass `redirectUrl` (where to send the user after consent) and optionally `accessType`. Three tiers: `read_only` grants read-only scopes; `messaging` grants read scopes plus message read/send but NOT property management, so it can coexist with another app (e.g. an existing PMS) that already holds property management on the same Airbnb account; `full_access` \u2014 the default \u2014 grants full host scopes including the exclusive property management (only one app per Airbnb account can hold it). The response returns a hosted `url` to redirect the user to.\n\nBooking.com: pass `redirectUrl` (no `accessType`). The response returns a hosted `url` \u2014 send the user there to
|
|
18520
|
+
"description": "Establish a connection to a PMS or OTA platform. Credentials vary by provider \u2014 see docs for each provider.\n\nAirbnb-specific: pass `redirectUrl` (where to send the user after consent) and optionally `accessType`. Three tiers: `read_only` grants read-only scopes; `messaging` (shown to hosts as \"Messaging & reviews\") grants read scopes plus message read/send and review writes (reply to guest reviews, submit host reviews \u2014 Airbnb's `reviews_write`) but NOT property management, so it can coexist with another app (e.g. an existing PMS) that already holds property management on the same Airbnb account; `full_access` \u2014 the default \u2014 grants full host scopes including the exclusive property management (only one app per Airbnb account can hold it). The response returns a hosted `url` to redirect the user to.\n\nBooking.com: pass `redirectUrl` (no `accessType`). The response returns a hosted `url` \u2014 send the user there to select our connectivity provider in their Booking.com Extranet and paste their Hotel ID. Same response shape as Airbnb (`url`, `sessionId`, `expiresAt`).\n\nPMS providers are not connected by this call: send their credentials to `POST /v1/connect/{provider}/credentials`, or start a hosted session with `POST /v1/connect`.",
|
|
17895
18521
|
"tags": [
|
|
17896
18522
|
"Connect"
|
|
17897
18523
|
],
|
|
@@ -17920,7 +18546,7 @@
|
|
|
17920
18546
|
"messaging"
|
|
17921
18547
|
],
|
|
17922
18548
|
"default": "full_access",
|
|
17923
|
-
"description": "Airbnb only \u2014 selects the OAuth scope set. 'read_only' grants read-only scopes; 'messaging' grants read scopes plus message read/send but NOT property management, so it can coexist with another app (e.g. an existing PMS) that already holds property management on the same Airbnb account; 'full_access' (default) grants full host scopes including the exclusive property management (only one app per Airbnb account can hold it). The hosted consent screen normally lets the host pick a tier; passing `accessType` explicitly fixes the tier and hides that choice, so the host can only continue with the tier you requested. Omit it to let the host choose."
|
|
18549
|
+
"description": "Airbnb only \u2014 selects the OAuth scope set. 'read_only' grants read-only scopes; 'messaging' (shown to hosts as \"Messaging & reviews\") grants read scopes plus message read/send and review writes (reply to guest reviews, submit host reviews \u2014 Airbnb's reviews_write) but NOT property management, so it can coexist with another app (e.g. an existing PMS) that already holds property management on the same Airbnb account; 'full_access' (default) grants full host scopes including the exclusive property management (only one app per Airbnb account can hold it). The hosted consent screen normally lets the host pick a tier; passing `accessType` explicitly fixes the tier and hides that choice, so the host can only continue with the tier you requested. Omit it to let the host choose."
|
|
17924
18550
|
},
|
|
17925
18551
|
"reservationHistoryMonths": {
|
|
17926
18552
|
"type": "integer",
|
|
@@ -17933,14 +18559,6 @@
|
|
|
17933
18559
|
"type": "string",
|
|
17934
18560
|
"description": "Airbnb + Booking.com \u2014 your own correlation token, e.g. your user id (at most 500 characters). Echoed on the redirect back (`&state=`) and in the `connect.session.completed` webhook."
|
|
17935
18561
|
},
|
|
17936
|
-
"clientId": {
|
|
17937
|
-
"type": "string",
|
|
17938
|
-
"description": "Plumguide \u2014 client ID."
|
|
17939
|
-
},
|
|
17940
|
-
"clientSecret": {
|
|
17941
|
-
"type": "string",
|
|
17942
|
-
"description": "Plumguide \u2014 client secret."
|
|
17943
|
-
},
|
|
17944
18562
|
"locale": {
|
|
17945
18563
|
"type": "string",
|
|
17946
18564
|
"nullable": true,
|
|
@@ -18808,7 +19426,7 @@
|
|
|
18808
19426
|
"get": {
|
|
18809
19427
|
"operationId": "getChannelHealth",
|
|
18810
19428
|
"summary": "Per-channel connectivity health",
|
|
18811
|
-
"description": "Reports reachability and auth state for one channel (`airbnb`, `booking`, `vrbo
|
|
19429
|
+
"description": "Reports reachability and auth state for one channel (`airbnb`, `booking`, `vrbo`). Use it to tell \"the channel is down\" apart from \"this workspace's connection expired\". `200` when `status` is `ok`, `503` when `degraded` or `down` (the body's `status` and `message` say which and why).\n\n**`vrbo`** reports the connector's own signals in a `vrbo` block: connected accounts, accounts VRBO signed out (their bookings, messages and calendar stop until reconnected \u2014 `down`), accounts whose inbox sync is late (`degraded`), and the calendar push queue backlog and its oldest wait (`degraded` past 3 hours). Its rate is calendar pushes VRBO refused over finished ones in the last 3 hours; failures inside Repull's own connector are reported apart as `vrbo.connector_errors` and do not count (`vrbo.window_hours`; `refresh_attempts_24h` / `refresh_rejections_24h` count that window for VRBO), judged only once at least 50 pushes finished and at least 5 failed \u2014 VRBO pushes run in bursts, so a day-long window would keep reporting a problem already fixed.",
|
|
18812
19430
|
"tags": [
|
|
18813
19431
|
"Health"
|
|
18814
19432
|
],
|
|
@@ -18823,8 +19441,7 @@
|
|
|
18823
19441
|
"enum": [
|
|
18824
19442
|
"airbnb",
|
|
18825
19443
|
"booking",
|
|
18826
|
-
"vrbo"
|
|
18827
|
-
"plumguide"
|
|
19444
|
+
"vrbo"
|
|
18828
19445
|
]
|
|
18829
19446
|
}
|
|
18830
19447
|
}
|
|
@@ -19179,7 +19796,7 @@
|
|
|
19179
19796
|
"post": {
|
|
19180
19797
|
"operationId": "verifyBookingHotel",
|
|
19181
19798
|
"summary": "Verify a Booking.com hotel ID for a Connect session",
|
|
19182
|
-
"description": "Manual-paste fallback that closes the Booking.com claim flow. Call this after the customer completes Stage 1 designation in their Booking Extranet (
|
|
19799
|
+
"description": "Manual-paste fallback that closes the Booking.com claim flow. Call this after the customer completes Stage 1 designation in their Booking Extranet (selecting our connectivity provider, named on the hosted Connect page) and pastes their Hotel ID into the hosted picker.\n\nValidates the hotel against Booking's property API, persists the `pms_connections` row, kicks off the room import, and transitions the Connect session to `awaiting_room_mapping`.\n\nNo API key required \u2014 the `sessionId` is the capability token. Sessions in any terminal state are rejected.",
|
|
19183
19800
|
"tags": [
|
|
19184
19801
|
"Connect"
|
|
19185
19802
|
],
|
|
@@ -26760,226 +27377,6 @@
|
|
|
26760
27377
|
}
|
|
26761
27378
|
}
|
|
26762
27379
|
},
|
|
26763
|
-
"/v1/channels/plumguide/listings": {
|
|
26764
|
-
"get": {
|
|
26765
|
-
"operationId": "list_plumguide_listings",
|
|
26766
|
-
"summary": "List Plumguide listings",
|
|
26767
|
-
"description": "List Plumguide listings this workspace has access to. Plumguide is approval-based \u2014 listings appear once Plumguide has accepted them.",
|
|
26768
|
-
"tags": [
|
|
26769
|
-
"Plumguide"
|
|
26770
|
-
],
|
|
26771
|
-
"responses": {
|
|
26772
|
-
"200": {
|
|
26773
|
-
"description": "Listings",
|
|
26774
|
-
"content": {
|
|
26775
|
-
"application/json": {
|
|
26776
|
-
"schema": {
|
|
26777
|
-
"$ref": "#/components/schemas/PlumguideListingListResponse"
|
|
26778
|
-
}
|
|
26779
|
-
}
|
|
26780
|
-
}
|
|
26781
|
-
}
|
|
26782
|
-
}
|
|
26783
|
-
}
|
|
26784
|
-
},
|
|
26785
|
-
"/v1/channels/plumguide/availability": {
|
|
26786
|
-
"get": {
|
|
26787
|
-
"operationId": "get_plumguide_availability",
|
|
26788
|
-
"summary": "Get Plumguide availability",
|
|
26789
|
-
"description": "Read the per-day availability calendar for a Plumguide listing. Returns the same row shape as Airbnb availability for SDK convenience.\n\nReturns `403 listing_inactive` when the listing this resolves to is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.",
|
|
26790
|
-
"tags": [
|
|
26791
|
-
"Plumguide"
|
|
26792
|
-
],
|
|
26793
|
-
"responses": {
|
|
26794
|
-
"200": {
|
|
26795
|
-
"description": "Availability"
|
|
26796
|
-
},
|
|
26797
|
-
"403": {
|
|
26798
|
-
"$ref": "#/components/responses/ListingInactive"
|
|
26799
|
-
}
|
|
26800
|
-
}
|
|
26801
|
-
},
|
|
26802
|
-
"put": {
|
|
26803
|
-
"operationId": "update_plumguide_availability",
|
|
26804
|
-
"summary": "Push availability to Plumguide",
|
|
26805
|
-
"description": "Push per-day availability changes to Plumguide. Plumguide accepts only the next 24 months \u2014 dates beyond that are silently ignored.\n\nReturns `403 listing_inactive` when the listing this resolves to is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.",
|
|
26806
|
-
"tags": [
|
|
26807
|
-
"Plumguide"
|
|
26808
|
-
],
|
|
26809
|
-
"responses": {
|
|
26810
|
-
"200": {
|
|
26811
|
-
"description": "Pushed"
|
|
26812
|
-
},
|
|
26813
|
-
"403": {
|
|
26814
|
-
"$ref": "#/components/responses/ListingInactive"
|
|
26815
|
-
}
|
|
26816
|
-
}
|
|
26817
|
-
}
|
|
26818
|
-
},
|
|
26819
|
-
"/v1/channels/plumguide/pricing": {
|
|
26820
|
-
"get": {
|
|
26821
|
-
"operationId": "get_plumguide_pricing",
|
|
26822
|
-
"summary": "Get Plumguide pricing",
|
|
26823
|
-
"description": "Read the current pricing for a Plumguide listing (base price, currency, weekend uplift).\n\nReturns `403 listing_inactive` when the listing this resolves to is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.",
|
|
26824
|
-
"tags": [
|
|
26825
|
-
"Plumguide"
|
|
26826
|
-
],
|
|
26827
|
-
"responses": {
|
|
26828
|
-
"200": {
|
|
26829
|
-
"description": "Pricing"
|
|
26830
|
-
},
|
|
26831
|
-
"403": {
|
|
26832
|
-
"$ref": "#/components/responses/ListingInactive"
|
|
26833
|
-
}
|
|
26834
|
-
}
|
|
26835
|
-
},
|
|
26836
|
-
"put": {
|
|
26837
|
-
"operationId": "update_plumguide_pricing",
|
|
26838
|
-
"summary": "Push pricing to Plumguide",
|
|
26839
|
-
"description": "Push pricing changes to Plumguide. Plumguide rounds all prices to whole units of the listing currency \u2014 sub-unit precision is silently truncated.\n\nReturns `403 listing_inactive` when the listing this resolves to is inactive. An inactive listing keeps syncing, but cannot be read or changed through the API until it is activated.",
|
|
26840
|
-
"tags": [
|
|
26841
|
-
"Plumguide"
|
|
26842
|
-
],
|
|
26843
|
-
"responses": {
|
|
26844
|
-
"200": {
|
|
26845
|
-
"description": "Pushed"
|
|
26846
|
-
},
|
|
26847
|
-
"403": {
|
|
26848
|
-
"$ref": "#/components/responses/ListingInactive"
|
|
26849
|
-
}
|
|
26850
|
-
}
|
|
26851
|
-
}
|
|
26852
|
-
},
|
|
26853
|
-
"/v1/channels/plumguide/bookings": {
|
|
26854
|
-
"get": {
|
|
26855
|
-
"operationId": "list_plumguide_bookings",
|
|
26856
|
-
"summary": "List Plumguide bookings",
|
|
26857
|
-
"description": "List Plumguide bookings. Default returns all bookings; pass `listing_id` to filter to one listing, or `booking_code` to fetch a single booking.\n\nReturns `403 listing_inactive` when `listing_id` or `booking_code` resolves to an inactive listing. The unfiltered list is read straight from Plum Guide and is not filtered by listing status.",
|
|
26858
|
-
"tags": [
|
|
26859
|
-
"Plumguide"
|
|
26860
|
-
],
|
|
26861
|
-
"parameters": [
|
|
26862
|
-
{
|
|
26863
|
-
"name": "listing_id",
|
|
26864
|
-
"in": "query",
|
|
26865
|
-
"required": false,
|
|
26866
|
-
"schema": {
|
|
26867
|
-
"type": "integer"
|
|
26868
|
-
},
|
|
26869
|
-
"description": "Filter to a single Plumguide listing."
|
|
26870
|
-
},
|
|
26871
|
-
{
|
|
26872
|
-
"name": "booking_code",
|
|
26873
|
-
"in": "query",
|
|
26874
|
-
"required": false,
|
|
26875
|
-
"schema": {
|
|
26876
|
-
"type": "string"
|
|
26877
|
-
},
|
|
26878
|
-
"description": "Fetch a single booking by its Plumguide booking code."
|
|
26879
|
-
}
|
|
26880
|
-
],
|
|
26881
|
-
"responses": {
|
|
26882
|
-
"200": {
|
|
26883
|
-
"description": "Bookings"
|
|
26884
|
-
},
|
|
26885
|
-
"401": {
|
|
26886
|
-
"$ref": "#/components/responses/Unauthorized"
|
|
26887
|
-
},
|
|
26888
|
-
"403": {
|
|
26889
|
-
"$ref": "#/components/responses/ListingInactive"
|
|
26890
|
-
},
|
|
26891
|
-
"404": {
|
|
26892
|
-
"$ref": "#/components/responses/NotFound"
|
|
26893
|
-
},
|
|
26894
|
-
"500": {
|
|
26895
|
-
"$ref": "#/components/responses/InternalError"
|
|
26896
|
-
}
|
|
26897
|
-
}
|
|
26898
|
-
}
|
|
26899
|
-
},
|
|
26900
|
-
"/v1/channels/plumguide/webhooks": {
|
|
26901
|
-
"get": {
|
|
26902
|
-
"operationId": "get_plumguide_webhooks",
|
|
26903
|
-
"summary": "Get Plumguide webhook config",
|
|
26904
|
-
"description": "Read the current Plumguide webhook configuration for this workspace.",
|
|
26905
|
-
"tags": [
|
|
26906
|
-
"Plumguide"
|
|
26907
|
-
],
|
|
26908
|
-
"responses": {
|
|
26909
|
-
"200": {
|
|
26910
|
-
"description": "Webhook config"
|
|
26911
|
-
},
|
|
26912
|
-
"401": {
|
|
26913
|
-
"$ref": "#/components/responses/Unauthorized"
|
|
26914
|
-
},
|
|
26915
|
-
"404": {
|
|
26916
|
-
"$ref": "#/components/responses/NotFound"
|
|
26917
|
-
},
|
|
26918
|
-
"500": {
|
|
26919
|
-
"$ref": "#/components/responses/InternalError"
|
|
26920
|
-
}
|
|
26921
|
-
}
|
|
26922
|
-
},
|
|
26923
|
-
"put": {
|
|
26924
|
-
"operationId": "update_plumguide_webhooks",
|
|
26925
|
-
"summary": "Replace Plumguide webhook config",
|
|
26926
|
-
"description": "Replace the Plumguide webhook configuration. The body carries the full webhook config payload \u2014 this is a full replacement, not a patch.",
|
|
26927
|
-
"tags": [
|
|
26928
|
-
"Plumguide"
|
|
26929
|
-
],
|
|
26930
|
-
"requestBody": {
|
|
26931
|
-
"required": true,
|
|
26932
|
-
"content": {
|
|
26933
|
-
"application/json": {
|
|
26934
|
-
"schema": {
|
|
26935
|
-
"type": "object",
|
|
26936
|
-
"additionalProperties": true,
|
|
26937
|
-
"description": "Full Plumguide webhook config payload."
|
|
26938
|
-
}
|
|
26939
|
-
}
|
|
26940
|
-
}
|
|
26941
|
-
},
|
|
26942
|
-
"responses": {
|
|
26943
|
-
"200": {
|
|
26944
|
-
"description": "Updated"
|
|
26945
|
-
},
|
|
26946
|
-
"400": {
|
|
26947
|
-
"$ref": "#/components/responses/BadRequest"
|
|
26948
|
-
},
|
|
26949
|
-
"401": {
|
|
26950
|
-
"$ref": "#/components/responses/Unauthorized"
|
|
26951
|
-
},
|
|
26952
|
-
"404": {
|
|
26953
|
-
"$ref": "#/components/responses/NotFound"
|
|
26954
|
-
},
|
|
26955
|
-
"500": {
|
|
26956
|
-
"$ref": "#/components/responses/InternalError"
|
|
26957
|
-
}
|
|
26958
|
-
}
|
|
26959
|
-
},
|
|
26960
|
-
"delete": {
|
|
26961
|
-
"operationId": "delete_plumguide_webhooks",
|
|
26962
|
-
"summary": "Remove Plumguide webhook config",
|
|
26963
|
-
"description": "Delete the Plumguide webhook configuration for this workspace. Plumguide stops delivering webhooks until a new config is set.",
|
|
26964
|
-
"tags": [
|
|
26965
|
-
"Plumguide"
|
|
26966
|
-
],
|
|
26967
|
-
"responses": {
|
|
26968
|
-
"200": {
|
|
26969
|
-
"description": "Deleted"
|
|
26970
|
-
},
|
|
26971
|
-
"401": {
|
|
26972
|
-
"$ref": "#/components/responses/Unauthorized"
|
|
26973
|
-
},
|
|
26974
|
-
"404": {
|
|
26975
|
-
"$ref": "#/components/responses/NotFound"
|
|
26976
|
-
},
|
|
26977
|
-
"500": {
|
|
26978
|
-
"$ref": "#/components/responses/InternalError"
|
|
26979
|
-
}
|
|
26980
|
-
}
|
|
26981
|
-
}
|
|
26982
|
-
},
|
|
26983
27380
|
"/v1/listings/{id}/pricing": {
|
|
26984
27381
|
"get": {
|
|
26985
27382
|
"operationId": "get_listing_pricing",
|
|
@@ -36472,6 +36869,11 @@
|
|
|
36472
36869
|
"completed"
|
|
36473
36870
|
]
|
|
36474
36871
|
},
|
|
36872
|
+
"notification_email": {
|
|
36873
|
+
"type": "string",
|
|
36874
|
+
"nullable": true,
|
|
36875
|
+
"description": "Vrbo only. Ask the host to add this address on Vrbo as a secondary email, with message and reservation notifications on. It is how new bookings, inquiries and guest messages reach Repull within a minute; without it they arrive at the next scheduled check. Hosted Connect asks for it on its mapping screen, so show it in your own flow when you map with `mapping: \"api\"`."
|
|
36876
|
+
},
|
|
36475
36877
|
"units": {
|
|
36476
36878
|
"type": "array",
|
|
36477
36879
|
"items": {
|
|
@@ -36495,7 +36897,8 @@
|
|
|
36495
36897
|
"nullable": true
|
|
36496
36898
|
},
|
|
36497
36899
|
"meta": {
|
|
36498
|
-
"type": "object"
|
|
36900
|
+
"type": "object",
|
|
36901
|
+
"description": "Channel details that identify the unit. Booking.com Extranet: `hotel` (property name), `hotelId` (Booking.com property ID), `roomId` (Booking.com room ID), `city`. Vrbo: `headline`, `address`, `vrboStatus`; the Vrbo listing ID is `unit_id`."
|
|
36499
36902
|
}
|
|
36500
36903
|
}
|
|
36501
36904
|
}
|
|
@@ -38439,6 +38842,439 @@
|
|
|
38439
38842
|
}
|
|
38440
38843
|
}
|
|
38441
38844
|
}
|
|
38845
|
+
},
|
|
38846
|
+
"/v1/listings/promotions/bulk": {
|
|
38847
|
+
"post": {
|
|
38848
|
+
"operationId": "bulk_listing_promotions",
|
|
38849
|
+
"summary": "Add or remove a promotion on many listings",
|
|
38850
|
+
"description": "Applies one promotion to up to 100 listings \u2014 `add` it, or `remove` the listing's running promotion of that channel and type. Each listing gets its own result with the channel's reason when refused, so one refusal doesn't stop the rest. Returns `403 listing_inactive` before doing anything when any listing is inactive.",
|
|
38851
|
+
"tags": [
|
|
38852
|
+
"Promotions"
|
|
38853
|
+
],
|
|
38854
|
+
"requestBody": {
|
|
38855
|
+
"required": true,
|
|
38856
|
+
"content": {
|
|
38857
|
+
"application/json": {
|
|
38858
|
+
"schema": {
|
|
38859
|
+
"$ref": "#/components/schemas/PromotionBulkRequest"
|
|
38860
|
+
}
|
|
38861
|
+
}
|
|
38862
|
+
}
|
|
38863
|
+
},
|
|
38864
|
+
"responses": {
|
|
38865
|
+
"200": {
|
|
38866
|
+
"description": "A result per listing",
|
|
38867
|
+
"content": {
|
|
38868
|
+
"application/json": {
|
|
38869
|
+
"schema": {
|
|
38870
|
+
"$ref": "#/components/schemas/PromotionBulkResponse"
|
|
38871
|
+
}
|
|
38872
|
+
}
|
|
38873
|
+
}
|
|
38874
|
+
},
|
|
38875
|
+
"400": {
|
|
38876
|
+
"$ref": "#/components/responses/BadRequest"
|
|
38877
|
+
},
|
|
38878
|
+
"401": {
|
|
38879
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
38880
|
+
},
|
|
38881
|
+
"403": {
|
|
38882
|
+
"$ref": "#/components/responses/ListingInactive"
|
|
38883
|
+
}
|
|
38884
|
+
}
|
|
38885
|
+
}
|
|
38886
|
+
},
|
|
38887
|
+
"/v1/listings/{id}/promotions": {
|
|
38888
|
+
"get": {
|
|
38889
|
+
"operationId": "list_listing_promotions",
|
|
38890
|
+
"summary": "List a listing's promotions",
|
|
38891
|
+
"description": "Airbnb and Booking.com promotions on the listing, in one model. Includes Airbnb promotions running or available (the new listing promotion shows as `eligible` when the listing qualifies), Airbnb Custom promotions seen on bookings (read-only \u2014 they override your prices on Airbnb), and Booking.com promotions covering the listing's room, including deactivated ones.\n\nPass `refresh=true` to re-read the channels first; otherwise the stored copy is returned (kept current by Airbnb's notifications and a sync every 30 minutes).\n\nReturns `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.",
|
|
38892
|
+
"tags": [
|
|
38893
|
+
"Promotions"
|
|
38894
|
+
],
|
|
38895
|
+
"parameters": [
|
|
38896
|
+
{
|
|
38897
|
+
"name": "id",
|
|
38898
|
+
"in": "path",
|
|
38899
|
+
"required": true,
|
|
38900
|
+
"schema": {
|
|
38901
|
+
"type": "integer"
|
|
38902
|
+
},
|
|
38903
|
+
"description": "Listing ID"
|
|
38904
|
+
},
|
|
38905
|
+
{
|
|
38906
|
+
"name": "refresh",
|
|
38907
|
+
"in": "query",
|
|
38908
|
+
"required": false,
|
|
38909
|
+
"schema": {
|
|
38910
|
+
"type": "boolean"
|
|
38911
|
+
},
|
|
38912
|
+
"description": "Re-read Airbnb and Booking.com before answering."
|
|
38913
|
+
}
|
|
38914
|
+
],
|
|
38915
|
+
"responses": {
|
|
38916
|
+
"200": {
|
|
38917
|
+
"description": "The listing's promotions",
|
|
38918
|
+
"content": {
|
|
38919
|
+
"application/json": {
|
|
38920
|
+
"schema": {
|
|
38921
|
+
"$ref": "#/components/schemas/PromotionListResponse"
|
|
38922
|
+
}
|
|
38923
|
+
}
|
|
38924
|
+
}
|
|
38925
|
+
},
|
|
38926
|
+
"400": {
|
|
38927
|
+
"$ref": "#/components/responses/BadRequest"
|
|
38928
|
+
},
|
|
38929
|
+
"401": {
|
|
38930
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
38931
|
+
},
|
|
38932
|
+
"403": {
|
|
38933
|
+
"$ref": "#/components/responses/ListingInactive"
|
|
38934
|
+
},
|
|
38935
|
+
"404": {
|
|
38936
|
+
"$ref": "#/components/responses/NotFound"
|
|
38937
|
+
}
|
|
38938
|
+
}
|
|
38939
|
+
},
|
|
38940
|
+
"post": {
|
|
38941
|
+
"operationId": "create_listing_promotion",
|
|
38942
|
+
"summary": "Add a promotion to a listing",
|
|
38943
|
+
"description": "Adds an Airbnb or Booking.com promotion. Read `GET /v1/listings/{id}/promotions/catalog` first for the types and fields the listing's channels accept.\n\n**Airbnb:** send `channel` and `type` only (`top_rated_guests`, `mobile`, `new_listing`) \u2014 Airbnb sets the discount. **Booking.com:** a listing's promotion covers that listing's room; send `discountPercent` and the rules the type takes, and `hotelId` when the listing is on several properties.\n\nA request a channel can't take is refused with `422` and a `promotion_*` code; the message names the channel and the field and says what to do, and `channel` / `field` are set. Booking.com writes return once Booking.com shows the change (it lags its own writes by a few seconds).\n\nReturns `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.",
|
|
38944
|
+
"tags": [
|
|
38945
|
+
"Promotions"
|
|
38946
|
+
],
|
|
38947
|
+
"parameters": [
|
|
38948
|
+
{
|
|
38949
|
+
"name": "id",
|
|
38950
|
+
"in": "path",
|
|
38951
|
+
"required": true,
|
|
38952
|
+
"schema": {
|
|
38953
|
+
"type": "integer"
|
|
38954
|
+
},
|
|
38955
|
+
"description": "Listing ID"
|
|
38956
|
+
}
|
|
38957
|
+
],
|
|
38958
|
+
"requestBody": {
|
|
38959
|
+
"required": true,
|
|
38960
|
+
"content": {
|
|
38961
|
+
"application/json": {
|
|
38962
|
+
"schema": {
|
|
38963
|
+
"$ref": "#/components/schemas/PromotionCreateRequest"
|
|
38964
|
+
}
|
|
38965
|
+
}
|
|
38966
|
+
}
|
|
38967
|
+
},
|
|
38968
|
+
"responses": {
|
|
38969
|
+
"201": {
|
|
38970
|
+
"description": "The new promotion",
|
|
38971
|
+
"content": {
|
|
38972
|
+
"application/json": {
|
|
38973
|
+
"schema": {
|
|
38974
|
+
"$ref": "#/components/schemas/PromotionResponse"
|
|
38975
|
+
}
|
|
38976
|
+
}
|
|
38977
|
+
}
|
|
38978
|
+
},
|
|
38979
|
+
"400": {
|
|
38980
|
+
"$ref": "#/components/responses/BadRequest"
|
|
38981
|
+
},
|
|
38982
|
+
"401": {
|
|
38983
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
38984
|
+
},
|
|
38985
|
+
"403": {
|
|
38986
|
+
"$ref": "#/components/responses/ListingInactive"
|
|
38987
|
+
},
|
|
38988
|
+
"404": {
|
|
38989
|
+
"$ref": "#/components/responses/NotFound"
|
|
38990
|
+
},
|
|
38991
|
+
"409": {
|
|
38992
|
+
"$ref": "#/components/responses/Conflict"
|
|
38993
|
+
},
|
|
38994
|
+
"422": {
|
|
38995
|
+
"$ref": "#/components/responses/UnprocessableEntity"
|
|
38996
|
+
},
|
|
38997
|
+
"502": {
|
|
38998
|
+
"description": "The channel didn't answer"
|
|
38999
|
+
}
|
|
39000
|
+
}
|
|
39001
|
+
}
|
|
39002
|
+
},
|
|
39003
|
+
"/v1/listings/{id}/promotions/catalog": {
|
|
39004
|
+
"get": {
|
|
39005
|
+
"operationId": "get_listing_promotion_catalog",
|
|
39006
|
+
"summary": "Promotion types a listing can use",
|
|
39007
|
+
"description": "Per channel: whether the listing is connected, and each promotion type with a short description for hosts, whether it is new, whether it is available to this listing (and why not), and every field \u2014 supported or not \u2014 with its limits and any value the channel fixes. Booking.com's types and limits come from the property itself; seasonal campaigns appear while Booking.com runs them.\n\nAirbnb asks partners to show newly available discounts with a \u201cNew\u201d badge and to grey out fields a discount does not support rather than hide them; `isNew` and `fields` carry what that needs.\n\nReturns `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.",
|
|
39008
|
+
"tags": [
|
|
39009
|
+
"Promotions"
|
|
39010
|
+
],
|
|
39011
|
+
"parameters": [
|
|
39012
|
+
{
|
|
39013
|
+
"name": "id",
|
|
39014
|
+
"in": "path",
|
|
39015
|
+
"required": true,
|
|
39016
|
+
"schema": {
|
|
39017
|
+
"type": "integer"
|
|
39018
|
+
},
|
|
39019
|
+
"description": "Listing ID"
|
|
39020
|
+
}
|
|
39021
|
+
],
|
|
39022
|
+
"responses": {
|
|
39023
|
+
"200": {
|
|
39024
|
+
"description": "The catalog",
|
|
39025
|
+
"content": {
|
|
39026
|
+
"application/json": {
|
|
39027
|
+
"schema": {
|
|
39028
|
+
"$ref": "#/components/schemas/PromotionCatalogResponse"
|
|
39029
|
+
}
|
|
39030
|
+
}
|
|
39031
|
+
}
|
|
39032
|
+
},
|
|
39033
|
+
"400": {
|
|
39034
|
+
"$ref": "#/components/responses/BadRequest"
|
|
39035
|
+
},
|
|
39036
|
+
"401": {
|
|
39037
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
39038
|
+
},
|
|
39039
|
+
"403": {
|
|
39040
|
+
"$ref": "#/components/responses/ListingInactive"
|
|
39041
|
+
},
|
|
39042
|
+
"404": {
|
|
39043
|
+
"$ref": "#/components/responses/NotFound"
|
|
39044
|
+
}
|
|
39045
|
+
}
|
|
39046
|
+
}
|
|
39047
|
+
},
|
|
39048
|
+
"/v1/listings/{id}/promotions/refresh": {
|
|
39049
|
+
"post": {
|
|
39050
|
+
"operationId": "refresh_listing_promotions",
|
|
39051
|
+
"summary": "Re-read a listing's promotions now",
|
|
39052
|
+
"description": "Reads the listing's promotions from Airbnb and Booking.com and returns them. Booking.com promotions belong to the property, so the property's other listings are refreshed too. `errors` lists any channel that could not be read.\n\nReturns `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.",
|
|
39053
|
+
"tags": [
|
|
39054
|
+
"Promotions"
|
|
39055
|
+
],
|
|
39056
|
+
"parameters": [
|
|
39057
|
+
{
|
|
39058
|
+
"name": "id",
|
|
39059
|
+
"in": "path",
|
|
39060
|
+
"required": true,
|
|
39061
|
+
"schema": {
|
|
39062
|
+
"type": "integer"
|
|
39063
|
+
},
|
|
39064
|
+
"description": "Listing ID"
|
|
39065
|
+
}
|
|
39066
|
+
],
|
|
39067
|
+
"responses": {
|
|
39068
|
+
"200": {
|
|
39069
|
+
"description": "The listing's promotions after the read",
|
|
39070
|
+
"content": {
|
|
39071
|
+
"application/json": {
|
|
39072
|
+
"schema": {
|
|
39073
|
+
"$ref": "#/components/schemas/PromotionRefreshResponse"
|
|
39074
|
+
}
|
|
39075
|
+
}
|
|
39076
|
+
}
|
|
39077
|
+
},
|
|
39078
|
+
"400": {
|
|
39079
|
+
"$ref": "#/components/responses/BadRequest"
|
|
39080
|
+
},
|
|
39081
|
+
"401": {
|
|
39082
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
39083
|
+
},
|
|
39084
|
+
"403": {
|
|
39085
|
+
"$ref": "#/components/responses/ListingInactive"
|
|
39086
|
+
},
|
|
39087
|
+
"404": {
|
|
39088
|
+
"$ref": "#/components/responses/NotFound"
|
|
39089
|
+
}
|
|
39090
|
+
}
|
|
39091
|
+
}
|
|
39092
|
+
},
|
|
39093
|
+
"/v1/listings/{id}/promotions/{promotionId}": {
|
|
39094
|
+
"get": {
|
|
39095
|
+
"operationId": "get_listing_promotion",
|
|
39096
|
+
"summary": "Get one promotion",
|
|
39097
|
+
"description": "One promotion on the listing.\n\nReturns `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.",
|
|
39098
|
+
"tags": [
|
|
39099
|
+
"Promotions"
|
|
39100
|
+
],
|
|
39101
|
+
"parameters": [
|
|
39102
|
+
{
|
|
39103
|
+
"name": "id",
|
|
39104
|
+
"in": "path",
|
|
39105
|
+
"required": true,
|
|
39106
|
+
"schema": {
|
|
39107
|
+
"type": "integer"
|
|
39108
|
+
},
|
|
39109
|
+
"description": "Listing ID"
|
|
39110
|
+
},
|
|
39111
|
+
{
|
|
39112
|
+
"name": "promotionId",
|
|
39113
|
+
"in": "path",
|
|
39114
|
+
"required": true,
|
|
39115
|
+
"schema": {
|
|
39116
|
+
"type": "integer"
|
|
39117
|
+
},
|
|
39118
|
+
"description": "Promotion ID (from the list)"
|
|
39119
|
+
}
|
|
39120
|
+
],
|
|
39121
|
+
"responses": {
|
|
39122
|
+
"200": {
|
|
39123
|
+
"description": "The promotion",
|
|
39124
|
+
"content": {
|
|
39125
|
+
"application/json": {
|
|
39126
|
+
"schema": {
|
|
39127
|
+
"$ref": "#/components/schemas/PromotionResponse"
|
|
39128
|
+
}
|
|
39129
|
+
}
|
|
39130
|
+
}
|
|
39131
|
+
},
|
|
39132
|
+
"400": {
|
|
39133
|
+
"$ref": "#/components/responses/BadRequest"
|
|
39134
|
+
},
|
|
39135
|
+
"401": {
|
|
39136
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
39137
|
+
},
|
|
39138
|
+
"403": {
|
|
39139
|
+
"$ref": "#/components/responses/ListingInactive"
|
|
39140
|
+
},
|
|
39141
|
+
"404": {
|
|
39142
|
+
"$ref": "#/components/responses/NotFound"
|
|
39143
|
+
}
|
|
39144
|
+
}
|
|
39145
|
+
},
|
|
39146
|
+
"patch": {
|
|
39147
|
+
"operationId": "update_listing_promotion",
|
|
39148
|
+
"summary": "Change a promotion",
|
|
39149
|
+
"description": "Booking.com promotions only \u2014 Airbnb's have nothing to change. `rules`, when sent, replaces the promotion's rules whole. A promotion that also covers other listings' rooms changes for them too, so it needs `confirmShared: true` (otherwise `409 promotion_shared_promotion`). Promotions that come from the listing's weekly or monthly discount are changed in its pricing settings.\n\nA request a channel can't take is refused with `422` and a `promotion_*` code; the message names the channel and the field and says what to do, and `channel` / `field` are set. Booking.com writes return once Booking.com shows the change (it lags its own writes by a few seconds).\n\nReturns `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.",
|
|
39150
|
+
"tags": [
|
|
39151
|
+
"Promotions"
|
|
39152
|
+
],
|
|
39153
|
+
"parameters": [
|
|
39154
|
+
{
|
|
39155
|
+
"name": "id",
|
|
39156
|
+
"in": "path",
|
|
39157
|
+
"required": true,
|
|
39158
|
+
"schema": {
|
|
39159
|
+
"type": "integer"
|
|
39160
|
+
},
|
|
39161
|
+
"description": "Listing ID"
|
|
39162
|
+
},
|
|
39163
|
+
{
|
|
39164
|
+
"name": "promotionId",
|
|
39165
|
+
"in": "path",
|
|
39166
|
+
"required": true,
|
|
39167
|
+
"schema": {
|
|
39168
|
+
"type": "integer"
|
|
39169
|
+
},
|
|
39170
|
+
"description": "Promotion ID (from the list)"
|
|
39171
|
+
}
|
|
39172
|
+
],
|
|
39173
|
+
"requestBody": {
|
|
39174
|
+
"required": true,
|
|
39175
|
+
"content": {
|
|
39176
|
+
"application/json": {
|
|
39177
|
+
"schema": {
|
|
39178
|
+
"$ref": "#/components/schemas/PromotionUpdateRequest"
|
|
39179
|
+
}
|
|
39180
|
+
}
|
|
39181
|
+
}
|
|
39182
|
+
},
|
|
39183
|
+
"responses": {
|
|
39184
|
+
"200": {
|
|
39185
|
+
"description": "The changed promotion",
|
|
39186
|
+
"content": {
|
|
39187
|
+
"application/json": {
|
|
39188
|
+
"schema": {
|
|
39189
|
+
"$ref": "#/components/schemas/PromotionResponse"
|
|
39190
|
+
}
|
|
39191
|
+
}
|
|
39192
|
+
}
|
|
39193
|
+
},
|
|
39194
|
+
"400": {
|
|
39195
|
+
"$ref": "#/components/responses/BadRequest"
|
|
39196
|
+
},
|
|
39197
|
+
"401": {
|
|
39198
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
39199
|
+
},
|
|
39200
|
+
"403": {
|
|
39201
|
+
"$ref": "#/components/responses/ListingInactive"
|
|
39202
|
+
},
|
|
39203
|
+
"404": {
|
|
39204
|
+
"$ref": "#/components/responses/NotFound"
|
|
39205
|
+
},
|
|
39206
|
+
"409": {
|
|
39207
|
+
"$ref": "#/components/responses/Conflict"
|
|
39208
|
+
},
|
|
39209
|
+
"422": {
|
|
39210
|
+
"$ref": "#/components/responses/UnprocessableEntity"
|
|
39211
|
+
},
|
|
39212
|
+
"502": {
|
|
39213
|
+
"description": "The channel didn't answer"
|
|
39214
|
+
}
|
|
39215
|
+
}
|
|
39216
|
+
},
|
|
39217
|
+
"delete": {
|
|
39218
|
+
"operationId": "delete_listing_promotion",
|
|
39219
|
+
"summary": "Remove a promotion from a listing",
|
|
39220
|
+
"description": "Airbnb: ends the listing's enrolment. Booking.com: takes the listing's room off the promotion \u2014 it keeps running for any other rooms it covers, and is deactivated when none are left. Airbnb Custom promotions can only be ended in Airbnb.\n\nA request a channel can't take is refused with `422` and a `promotion_*` code; the message names the channel and the field and says what to do, and `channel` / `field` are set. Booking.com writes return once Booking.com shows the change (it lags its own writes by a few seconds).\n\nReturns `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.",
|
|
39221
|
+
"tags": [
|
|
39222
|
+
"Promotions"
|
|
39223
|
+
],
|
|
39224
|
+
"parameters": [
|
|
39225
|
+
{
|
|
39226
|
+
"name": "id",
|
|
39227
|
+
"in": "path",
|
|
39228
|
+
"required": true,
|
|
39229
|
+
"schema": {
|
|
39230
|
+
"type": "integer"
|
|
39231
|
+
},
|
|
39232
|
+
"description": "Listing ID"
|
|
39233
|
+
},
|
|
39234
|
+
{
|
|
39235
|
+
"name": "promotionId",
|
|
39236
|
+
"in": "path",
|
|
39237
|
+
"required": true,
|
|
39238
|
+
"schema": {
|
|
39239
|
+
"type": "integer"
|
|
39240
|
+
},
|
|
39241
|
+
"description": "Promotion ID (from the list)"
|
|
39242
|
+
}
|
|
39243
|
+
],
|
|
39244
|
+
"responses": {
|
|
39245
|
+
"200": {
|
|
39246
|
+
"description": "Removed",
|
|
39247
|
+
"content": {
|
|
39248
|
+
"application/json": {
|
|
39249
|
+
"schema": {
|
|
39250
|
+
"$ref": "#/components/schemas/PromotionDeleteResponse"
|
|
39251
|
+
}
|
|
39252
|
+
}
|
|
39253
|
+
}
|
|
39254
|
+
},
|
|
39255
|
+
"400": {
|
|
39256
|
+
"$ref": "#/components/responses/BadRequest"
|
|
39257
|
+
},
|
|
39258
|
+
"401": {
|
|
39259
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
39260
|
+
},
|
|
39261
|
+
"403": {
|
|
39262
|
+
"$ref": "#/components/responses/ListingInactive"
|
|
39263
|
+
},
|
|
39264
|
+
"404": {
|
|
39265
|
+
"$ref": "#/components/responses/NotFound"
|
|
39266
|
+
},
|
|
39267
|
+
"409": {
|
|
39268
|
+
"$ref": "#/components/responses/Conflict"
|
|
39269
|
+
},
|
|
39270
|
+
"422": {
|
|
39271
|
+
"$ref": "#/components/responses/UnprocessableEntity"
|
|
39272
|
+
},
|
|
39273
|
+
"502": {
|
|
39274
|
+
"description": "The channel didn't answer"
|
|
39275
|
+
}
|
|
39276
|
+
}
|
|
39277
|
+
}
|
|
38442
39278
|
}
|
|
38443
39279
|
}
|
|
38444
39280
|
}
|