repull 0.2.24 → 0.2.26
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 +619 -2
- data/lib/repull/api/connections_api.rb +312 -0
- data/lib/repull/api/conversations_api.rb +154 -18
- data/lib/repull/api/health_api.rb +5 -5
- data/lib/repull/api/listings_api.rb +67 -4
- data/lib/repull/api/properties_api.rb +3 -0
- data/lib/repull/api/reservations_api.rb +3 -0
- data/lib/repull/api/reviews_api.rb +5 -2
- data/lib/repull/api/vrbo_api.rb +4 -4
- data/lib/repull/models/apply_connection_mappings200_response.rb +167 -0
- data/lib/repull/models/apply_connection_mappings200_response_results_inner.rb +184 -0
- data/lib/repull/models/apply_connection_mappings_request.rb +175 -0
- data/lib/repull/models/apply_connection_mappings_request_mappings_inner.rb +193 -0
- data/lib/repull/models/auto_map_connection_units200_response.rb +176 -0
- data/lib/repull/models/auto_map_connection_units_request.rb +156 -0
- data/lib/repull/models/channel_market_state_item.rb +15 -4
- data/lib/repull/models/connect_session_completed_event.rb +281 -0
- data/lib/repull/models/connect_session_completed_payload.rb +210 -0
- data/lib/repull/models/connect_status.rb +25 -5
- data/lib/repull/models/connect_status_accounts_inner.rb +71 -4
- data/lib/repull/models/conversation.rb +12 -1
- data/lib/repull/models/conversation_capabilities.rb +260 -0
- data/lib/repull/models/conversation_detail.rb +25 -5
- data/lib/repull/models/create_connect_session_request.rb +24 -2
- data/lib/repull/models/create_connection_request.rb +8 -8
- data/lib/repull/models/create_conversation_special_offer201_response.rb +127 -4
- data/lib/repull/models/create_conversation_special_offer201_response_fees_inner.rb +166 -0
- data/lib/repull/models/create_conversation_special_offer201_response_lines_inner.rb +157 -0
- data/lib/repull/models/create_conversation_special_offer_request.rb +91 -52
- data/lib/repull/models/create_conversation_special_offer_request_fees_inner.rb +199 -0
- data/lib/repull/models/get_booking_extranet_login_config200_response.rb +147 -0
- data/lib/repull/models/get_booking_extranet_login_status200_response.rb +192 -0
- data/lib/repull/models/get_channel_health200_response.rb +190 -0
- data/lib/repull/models/get_channel_health200_response_vrbo.rb +197 -0
- data/lib/repull/models/get_connect_write_policy200_response.rb +166 -0
- data/lib/repull/models/get_listing_calendar_sync200_response.rb +192 -0
- data/lib/repull/models/get_listing_calendar_sync200_response_channels_inner.rb +331 -0
- data/lib/repull/models/get_listing_calendar_sync200_response_channels_inner_problems_inner.rb +157 -0
- data/lib/repull/models/get_listing_calendar_sync200_response_channels_inner_queue.rb +212 -0
- data/lib/repull/models/get_listing_calendar_sync200_response_channels_inner_queue_last_push.rb +268 -0
- data/lib/repull/models/invite_booking_extranet_user200_response.rb +174 -0
- data/lib/repull/models/invite_booking_extranet_user_request.rb +173 -0
- data/lib/repull/models/list_connection_units200_response.rb +242 -0
- data/lib/repull/models/list_connection_units200_response_listing_options_inner.rb +165 -0
- data/lib/repull/models/list_connection_units200_response_units_inner.rb +194 -0
- data/lib/repull/models/listing_publish_status_connection.rb +34 -1
- data/lib/repull/models/pms_write_policy.rb +191 -0
- data/lib/repull/models/pms_write_policy_calendar.rb +219 -0
- data/lib/repull/models/pms_write_policy_reservations.rb +219 -0
- data/lib/repull/models/preapprove_conversation201_response.rb +47 -6
- data/lib/repull/models/preapprove_conversation_request.rb +34 -5
- data/lib/repull/models/preview_conversation_special_offer_request.rb +231 -0
- data/lib/repull/models/preview_conversation_special_offer_request_fees_inner.rb +199 -0
- data/lib/repull/models/preview_conversation_special_offer_request_guests.rb +250 -0
- data/lib/repull/models/property.rb +14 -2
- data/lib/repull/models/record_account.rb +170 -0
- data/lib/repull/models/reply_to_review_request.rb +33 -4
- data/lib/repull/models/reservation.rb +12 -1
- data/lib/repull/models/review.rb +12 -1
- data/lib/repull/models/search_connect_session_listing_options200_response.rb +158 -0
- data/lib/repull/models/search_connect_session_listing_options200_response_data_inner.rb +166 -0
- data/lib/repull/models/search_connection_listing_options200_response.rb +159 -0
- data/lib/repull/models/send_message_request.rb +1 -1
- data/lib/repull/models/start_booking_extranet_login200_response.rb +174 -0
- data/lib/repull/models/start_booking_extranet_login_request.rb +225 -0
- data/lib/repull/models/submit_cloudbeds_credentials200_response.rb +10 -1
- data/lib/repull/models/submit_cloudbeds_credentials_request.rb +11 -1
- data/lib/repull/models/submit_mews_credentials200_response.rb +10 -1
- data/lib/repull/models/submit_mews_credentials_request.rb +11 -1
- data/lib/repull/models/update_connect_write_policy_request.rb +157 -0
- data/lib/repull/models/update_connect_write_policy_request_calendar.rb +165 -0
- data/lib/repull/models/update_connect_write_policy_request_reservations.rb +165 -0
- data/lib/repull/models/vrbo_import_status.rb +249 -0
- data/lib/repull/models/vrbo_login200_response.rb +235 -0
- data/lib/repull/models/vrbo_login_request.rb +271 -0
- data/lib/repull/models/webhook_event.rb +2 -0
- data/lib/repull/models/webhook_event_type.rb +2 -1
- data/lib/repull/models/withdraw_conversation_preapproval200_response.rb +226 -0
- data/lib/repull/models/withdraw_conversation_special_offer200_response.rb +29 -1
- data/lib/repull/version.rb +1 -1
- data/lib/repull.rb +47 -0
- data/openapi/v1.json +2810 -74
- data/scripts/regen.sh +1 -1
- metadata +49 -2
data/openapi/v1.json
CHANGED
|
@@ -151,8 +151,15 @@
|
|
|
151
151
|
"schemas": {
|
|
152
152
|
"Property": {
|
|
153
153
|
"type": "object",
|
|
154
|
-
"description": "A vacation rental property in your Repull workspace. Backed by the core `listings` row \u2014 enriched per-PMS fields (bedrooms, property type, provider id, etc.) live in provider-specific detail tables and are NOT returned here.\n\nField availability differs by endpoint:\n- `channels` is returned by the list endpoint (`GET /v1/properties`) only.\n- `latitude`, `longitude`, `createdAt`, and `amenities` are returned by the detail endpoint (`GET /v1/properties/{id}`) only. `amenities` requires `?include=amenities`.\n\nAn **inactive** property (`status: inactive`) appears only in the list endpoint, and only when `?status=inactive|all` asks for it. Such a row carries identity fields only \u2014 `id`, `name`, `status`, `lifecycleStatus`, `channels`, `updatedAt` \u2014 so every other field is absent until the property is activated. Every other endpoint answers `403 listing_inactive` for it.",
|
|
154
|
+
"description": "A vacation rental property in your Repull workspace. Backed by the core `listings` row \u2014 enriched per-PMS fields (bedrooms, property type, provider id, etc.) live in provider-specific detail tables and are NOT returned here.\n\nField availability differs by endpoint:\n- `channels` is returned by the list endpoint (`GET /v1/properties`) only.\n- `latitude`, `longitude`, `createdAt`, and `amenities` are returned by the detail endpoint (`GET /v1/properties/{id}`) only. `amenities` requires `?include=amenities`.\n\nAn **inactive** property (`status: inactive`) appears only in the list endpoint, and only when `?status=inactive|all` asks for it. Such a row carries identity fields only \u2014 `id`, `name`, `status`, `lifecycleStatus`, `channels`, `accounts`, `updatedAt` \u2014 so every other field is absent until the property is activated. Every other endpoint answers `403 listing_inactive` for it.",
|
|
155
155
|
"properties": {
|
|
156
|
+
"accounts": {
|
|
157
|
+
"type": "array",
|
|
158
|
+
"items": {
|
|
159
|
+
"$ref": "#/components/schemas/RecordAccount"
|
|
160
|
+
},
|
|
161
|
+
"description": "The connected account the property belongs to on each channel it is on. List endpoint."
|
|
162
|
+
},
|
|
156
163
|
"id": {
|
|
157
164
|
"type": "string",
|
|
158
165
|
"description": "Internal Repull property ID. Equal to the listing id (`listings.id`); the same integer is used as `listingId` on reservations and `propertyId` on availability."
|
|
@@ -537,6 +544,14 @@
|
|
|
537
544
|
"type": "object",
|
|
538
545
|
"description": "A booking/reservation from a connected PMS. Identical shape between list-row (`GET /v1/reservations`) and detail (`GET /v1/reservations/{id}`) \u2014 SDK consumers can use the same type for both.\n\nThe canonical (post-2026-05) shape uses nested `primaryGuest`, `occupancy`, `financials` blocks. The legacy flat fields (`guestId`, `totalPrice`, `currency`, `guestDetails`) remain populated for back-compat and are marked `deprecated` here. New consumers should read from the nested blocks; existing consumers continue to work unchanged.",
|
|
539
546
|
"properties": {
|
|
547
|
+
"account": {
|
|
548
|
+
"allOf": [
|
|
549
|
+
{
|
|
550
|
+
"$ref": "#/components/schemas/RecordAccount"
|
|
551
|
+
}
|
|
552
|
+
],
|
|
553
|
+
"description": "The connected account this reservation belongs to. List endpoint."
|
|
554
|
+
},
|
|
540
555
|
"id": {
|
|
541
556
|
"type": "string",
|
|
542
557
|
"description": "Internal Repull reservation ID"
|
|
@@ -977,6 +992,14 @@
|
|
|
977
992
|
"type": "object",
|
|
978
993
|
"description": "Channel-agnostic message thread between the host workspace and a guest. Returned by `GET /v1/conversations`. The `id` is the internal Repull thread id (integer) \u2014 pass it back as the `{id}` path param on detail / messages calls.",
|
|
979
994
|
"properties": {
|
|
995
|
+
"account": {
|
|
996
|
+
"allOf": [
|
|
997
|
+
{
|
|
998
|
+
"$ref": "#/components/schemas/RecordAccount"
|
|
999
|
+
}
|
|
1000
|
+
],
|
|
1001
|
+
"description": "The connected account this conversation belongs to. List endpoint."
|
|
1002
|
+
},
|
|
980
1003
|
"id": {
|
|
981
1004
|
"type": "string"
|
|
982
1005
|
},
|
|
@@ -1124,11 +1147,55 @@
|
|
|
1124
1147
|
"$ref": "#/components/schemas/ConversationGuest"
|
|
1125
1148
|
}
|
|
1126
1149
|
]
|
|
1150
|
+
},
|
|
1151
|
+
"capabilities": {
|
|
1152
|
+
"$ref": "#/components/schemas/ConversationCapabilities"
|
|
1127
1153
|
}
|
|
1128
1154
|
}
|
|
1129
1155
|
}
|
|
1130
1156
|
]
|
|
1131
1157
|
},
|
|
1158
|
+
"ConversationCapabilities": {
|
|
1159
|
+
"type": "object",
|
|
1160
|
+
"description": "What the inquiry actions can do on this conversation right now \u2014 one set of endpoints for every channel, so an app shows the right actions instead of learning from a `422`. All `false` / `null` when nothing applies (a booked or closed inquiry, Booking.com, direct, an Airbnb inquiry relayed by a PMS).",
|
|
1161
|
+
"required": [
|
|
1162
|
+
"canPreApprove",
|
|
1163
|
+
"canWithdraw",
|
|
1164
|
+
"canSendOffer",
|
|
1165
|
+
"offerPrice",
|
|
1166
|
+
"canPreviewOffer"
|
|
1167
|
+
],
|
|
1168
|
+
"properties": {
|
|
1169
|
+
"canPreApprove": {
|
|
1170
|
+
"type": "boolean",
|
|
1171
|
+
"description": "`POST /v1/conversations/{id}/pre-approval` would pre-approve the open inquiry (Airbnb connected directly, VRBO)."
|
|
1172
|
+
},
|
|
1173
|
+
"canWithdraw": {
|
|
1174
|
+
"type": "boolean",
|
|
1175
|
+
"description": "A pre-approval or offer is live and can be withdrawn \u2014 `DELETE /v1/conversations/{id}/pre-approval` (VRBO) or `DELETE \u2026/special-offers/{offerId}` (Airbnb)."
|
|
1176
|
+
},
|
|
1177
|
+
"canSendOffer": {
|
|
1178
|
+
"type": "boolean",
|
|
1179
|
+
"description": "`POST /v1/conversations/{id}/special-offers` would send an offer."
|
|
1180
|
+
},
|
|
1181
|
+
"offerPrice": {
|
|
1182
|
+
"type": "string",
|
|
1183
|
+
"nullable": true,
|
|
1184
|
+
"description": "How an offer is priced here: `total` \u2014 one `totalPrice` for the stay (Airbnb); `breakdown` \u2014 `rentalAmount`, `fees`, `damageDeposit`, and the channel computes the guest total (VRBO)."
|
|
1185
|
+
},
|
|
1186
|
+
"canPreviewOffer": {
|
|
1187
|
+
"type": "boolean",
|
|
1188
|
+
"description": "`POST /v1/conversations/{id}/special-offers/preview` returns the channel\u2019s recalculated offer (VRBO)."
|
|
1189
|
+
}
|
|
1190
|
+
},
|
|
1191
|
+
"example": {
|
|
1192
|
+
"canPreApprove": false,
|
|
1193
|
+
"canWithdraw": true,
|
|
1194
|
+
"canSendOffer": true,
|
|
1195
|
+
"offerPrice": "breakdown",
|
|
1196
|
+
"canPreviewOffer": true
|
|
1197
|
+
}
|
|
1198
|
+
},
|
|
1132
1199
|
"ConversationMessageAttachment": {
|
|
1133
1200
|
"type": "object",
|
|
1134
1201
|
"description": "A file on a message \u2014 a photo the guest sent, or a file sent to the guest. Files are copied to durable storage, so `url` keeps working after the channel's own link expires. Treat `url` as opaque.",
|
|
@@ -1275,6 +1342,14 @@
|
|
|
1275
1342
|
"type": "object",
|
|
1276
1343
|
"description": "A guest or host review unified across channels. Returned by `GET /v1/reviews` and `GET /v1/reviews/{id}`. Includes every channel's reviews once they have been imported.",
|
|
1277
1344
|
"properties": {
|
|
1345
|
+
"account": {
|
|
1346
|
+
"allOf": [
|
|
1347
|
+
{
|
|
1348
|
+
"$ref": "#/components/schemas/RecordAccount"
|
|
1349
|
+
}
|
|
1350
|
+
],
|
|
1351
|
+
"description": "The connected account this review belongs to. List endpoint."
|
|
1352
|
+
},
|
|
1278
1353
|
"id": {
|
|
1279
1354
|
"type": "string",
|
|
1280
1355
|
"description": "Internal Repull review id \u2014 pass back to `/v1/reviews/{id}`."
|
|
@@ -1986,7 +2061,7 @@
|
|
|
1986
2061
|
},
|
|
1987
2062
|
"accounts": {
|
|
1988
2063
|
"type": "array",
|
|
1989
|
-
"description": "Airbnb
|
|
2064
|
+
"description": "Airbnb: every Airbnb account this workspace has connected, including ones since disconnected. Pass `externalAccountId` as `accountId` to `DELETE /v1/connect/airbnb` to disconnect one account. Vrbo (`GET /v1/connect/vrbo-login`): every signed-in Vrbo account, each with `accessType` and `import` (a `VrboImportStatus`), plus a top-level `dataFreshness`.",
|
|
1990
2065
|
"items": {
|
|
1991
2066
|
"type": "object",
|
|
1992
2067
|
"properties": {
|
|
@@ -2013,9 +2088,164 @@
|
|
|
2013
2088
|
"type": "boolean",
|
|
2014
2089
|
"description": "True while the account is active and its authorization is usable.",
|
|
2015
2090
|
"example": true
|
|
2091
|
+
},
|
|
2092
|
+
"email": {
|
|
2093
|
+
"type": "string",
|
|
2094
|
+
"nullable": true,
|
|
2095
|
+
"description": "Vrbo only: the account email."
|
|
2096
|
+
},
|
|
2097
|
+
"accessType": {
|
|
2098
|
+
"type": "string",
|
|
2099
|
+
"nullable": true,
|
|
2100
|
+
"enum": [
|
|
2101
|
+
"messaging",
|
|
2102
|
+
"full_access"
|
|
2103
|
+
],
|
|
2104
|
+
"description": "Vrbo only."
|
|
2105
|
+
},
|
|
2106
|
+
"import": {
|
|
2107
|
+
"nullable": true,
|
|
2108
|
+
"allOf": [
|
|
2109
|
+
{
|
|
2110
|
+
"$ref": "#/components/schemas/VrboImportStatus"
|
|
2111
|
+
}
|
|
2112
|
+
],
|
|
2113
|
+
"description": "Vrbo only: where the account import stands."
|
|
2016
2114
|
}
|
|
2017
2115
|
}
|
|
2018
2116
|
}
|
|
2117
|
+
},
|
|
2118
|
+
"writePolicy": {
|
|
2119
|
+
"allOf": [
|
|
2120
|
+
{
|
|
2121
|
+
"$ref": "#/components/schemas/PmsWritePolicy"
|
|
2122
|
+
}
|
|
2123
|
+
],
|
|
2124
|
+
"description": "PMS connections only: what the app may change in the PMS. Change it with `PATCH /v1/connect/{provider}/write-policy`."
|
|
2125
|
+
},
|
|
2126
|
+
"dataFreshness": {
|
|
2127
|
+
"type": "object",
|
|
2128
|
+
"description": "Vrbo only: the same freshness envelope the Airbnb read endpoints return, per account and in aggregate. Its reason is never_synced until a mapping is confirmed and importing while upcoming bookings come in."
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
},
|
|
2132
|
+
"PmsWritePolicy": {
|
|
2133
|
+
"type": "object",
|
|
2134
|
+
"description": "What the app may change in a connected PMS. Hotel PMSs (Cloudbeds, Mews) start with every `calendar` switch off, because the PMS owns its room inventory; every other PMS starts with everything on. Reading from the PMS is never affected.",
|
|
2135
|
+
"properties": {
|
|
2136
|
+
"calendar": {
|
|
2137
|
+
"type": "object",
|
|
2138
|
+
"properties": {
|
|
2139
|
+
"availability": {
|
|
2140
|
+
"type": "boolean",
|
|
2141
|
+
"description": "Open and close nights. Off also means the PMS's bookings never block the calendar on other channels."
|
|
2142
|
+
},
|
|
2143
|
+
"rates": {
|
|
2144
|
+
"type": "boolean",
|
|
2145
|
+
"description": "Nightly prices."
|
|
2146
|
+
},
|
|
2147
|
+
"restrictions": {
|
|
2148
|
+
"type": "boolean",
|
|
2149
|
+
"description": "Minimum stay and other stay restrictions."
|
|
2150
|
+
}
|
|
2151
|
+
},
|
|
2152
|
+
"required": [
|
|
2153
|
+
"availability",
|
|
2154
|
+
"rates",
|
|
2155
|
+
"restrictions"
|
|
2156
|
+
]
|
|
2157
|
+
},
|
|
2158
|
+
"reservations": {
|
|
2159
|
+
"type": "object",
|
|
2160
|
+
"properties": {
|
|
2161
|
+
"website": {
|
|
2162
|
+
"type": "boolean",
|
|
2163
|
+
"description": "Create bookings from booking websites."
|
|
2164
|
+
},
|
|
2165
|
+
"dashboard": {
|
|
2166
|
+
"type": "boolean",
|
|
2167
|
+
"description": "Change and cancel bookings from the dashboard."
|
|
2168
|
+
},
|
|
2169
|
+
"api": {
|
|
2170
|
+
"type": "boolean",
|
|
2171
|
+
"description": "Create, change and cancel bookings through the reservations API."
|
|
2172
|
+
}
|
|
2173
|
+
},
|
|
2174
|
+
"required": [
|
|
2175
|
+
"website",
|
|
2176
|
+
"dashboard",
|
|
2177
|
+
"api"
|
|
2178
|
+
]
|
|
2179
|
+
}
|
|
2180
|
+
},
|
|
2181
|
+
"required": [
|
|
2182
|
+
"calendar",
|
|
2183
|
+
"reservations"
|
|
2184
|
+
],
|
|
2185
|
+
"example": {
|
|
2186
|
+
"calendar": {
|
|
2187
|
+
"availability": false,
|
|
2188
|
+
"rates": true,
|
|
2189
|
+
"restrictions": false
|
|
2190
|
+
},
|
|
2191
|
+
"reservations": {
|
|
2192
|
+
"website": true,
|
|
2193
|
+
"dashboard": true,
|
|
2194
|
+
"api": true
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
},
|
|
2198
|
+
"VrboImportStatus": {
|
|
2199
|
+
"type": "object",
|
|
2200
|
+
"description": "Where a Vrbo account import stands. Nothing is imported until its unit mapping is confirmed; then upcoming bookings and the last 30 days of messages come first, and the whole account history after.",
|
|
2201
|
+
"properties": {
|
|
2202
|
+
"accountId": {
|
|
2203
|
+
"type": "integer"
|
|
2204
|
+
},
|
|
2205
|
+
"state": {
|
|
2206
|
+
"type": "string"
|
|
2207
|
+
},
|
|
2208
|
+
"accessType": {
|
|
2209
|
+
"type": "string",
|
|
2210
|
+
"nullable": true,
|
|
2211
|
+
"description": "`messaging`: bookings and messages only, the calendar is never pushed."
|
|
2212
|
+
},
|
|
2213
|
+
"requestedAt": {
|
|
2214
|
+
"type": "string",
|
|
2215
|
+
"format": "date-time",
|
|
2216
|
+
"nullable": true,
|
|
2217
|
+
"description": "When the mapping was confirmed."
|
|
2218
|
+
},
|
|
2219
|
+
"priorityImportedAt": {
|
|
2220
|
+
"type": "string",
|
|
2221
|
+
"format": "date-time",
|
|
2222
|
+
"nullable": true,
|
|
2223
|
+
"description": "Upcoming bookings and the last 30 days are in."
|
|
2224
|
+
},
|
|
2225
|
+
"historyCompletedAt": {
|
|
2226
|
+
"type": "string",
|
|
2227
|
+
"format": "date-time",
|
|
2228
|
+
"nullable": true
|
|
2229
|
+
},
|
|
2230
|
+
"historyComplete": {
|
|
2231
|
+
"type": "boolean",
|
|
2232
|
+
"description": "The whole account history is imported."
|
|
2233
|
+
},
|
|
2234
|
+
"lastSyncedAt": {
|
|
2235
|
+
"type": "string",
|
|
2236
|
+
"format": "date-time",
|
|
2237
|
+
"nullable": true,
|
|
2238
|
+
"description": "Last completed sync (Vrbo is read every few minutes and on each Vrbo notification email)."
|
|
2239
|
+
},
|
|
2240
|
+
"conversationsSeen": {
|
|
2241
|
+
"type": "integer"
|
|
2242
|
+
},
|
|
2243
|
+
"conversationsImported": {
|
|
2244
|
+
"type": "integer"
|
|
2245
|
+
},
|
|
2246
|
+
"reservations": {
|
|
2247
|
+
"type": "integer",
|
|
2248
|
+
"description": "Bookings imported so far."
|
|
2019
2249
|
}
|
|
2020
2250
|
}
|
|
2021
2251
|
},
|
|
@@ -2292,6 +2522,7 @@
|
|
|
2292
2522
|
"listing.reactivated",
|
|
2293
2523
|
"calendar.updated",
|
|
2294
2524
|
"account.created",
|
|
2525
|
+
"connect.session.completed",
|
|
2295
2526
|
"account.disconnected",
|
|
2296
2527
|
"review.created",
|
|
2297
2528
|
"review.responded",
|
|
@@ -3344,6 +3575,46 @@
|
|
|
3344
3575
|
}
|
|
3345
3576
|
}
|
|
3346
3577
|
},
|
|
3578
|
+
"ConnectSessionCompletedPayload": {
|
|
3579
|
+
"type": "object",
|
|
3580
|
+
"description": "Payload for `connect.session.completed`. A user finished a Connect session, on any channel or PMS. Use `state` (your token from session creation) or `sessionId` to tie the connection to your own user; the account it names is keyed the same way as every other event's `account` block.",
|
|
3581
|
+
"properties": {
|
|
3582
|
+
"sessionId": {
|
|
3583
|
+
"type": "string",
|
|
3584
|
+
"example": "cs_abc123"
|
|
3585
|
+
},
|
|
3586
|
+
"state": {
|
|
3587
|
+
"type": "string",
|
|
3588
|
+
"nullable": true,
|
|
3589
|
+
"description": "The `state` you passed when creating the session.",
|
|
3590
|
+
"example": "user_8421"
|
|
3591
|
+
},
|
|
3592
|
+
"provider": {
|
|
3593
|
+
"type": "string",
|
|
3594
|
+
"nullable": true,
|
|
3595
|
+
"description": "Channel or PMS: airbnb, booking, booking_extranet, vrbo, plumguide, hostaway, \u2026",
|
|
3596
|
+
"example": "vrbo"
|
|
3597
|
+
},
|
|
3598
|
+
"externalAccountId": {
|
|
3599
|
+
"type": "string",
|
|
3600
|
+
"nullable": true,
|
|
3601
|
+
"description": "The provider's own account id \u2014 Airbnb host id, Booking.com hotel id, Vrbo account id, or the PMS account.",
|
|
3602
|
+
"example": "36"
|
|
3603
|
+
},
|
|
3604
|
+
"connectionId": {
|
|
3605
|
+
"type": "integer",
|
|
3606
|
+
"nullable": true,
|
|
3607
|
+
"description": "Repull connection id, when the account has one (the `X-Account-Id` value)."
|
|
3608
|
+
},
|
|
3609
|
+
"purpose": {
|
|
3610
|
+
"type": "string"
|
|
3611
|
+
},
|
|
3612
|
+
"completedAt": {
|
|
3613
|
+
"type": "string",
|
|
3614
|
+
"format": "date-time"
|
|
3615
|
+
}
|
|
3616
|
+
}
|
|
3617
|
+
},
|
|
3347
3618
|
"AccountDisconnectedPayload": {
|
|
3348
3619
|
"type": "object",
|
|
3349
3620
|
"description": "Payload for `account.disconnected`. A PMS or channel connection was revoked, expired, or rejected by the upstream provider.",
|
|
@@ -3693,6 +3964,29 @@
|
|
|
3693
3964
|
}
|
|
3694
3965
|
}
|
|
3695
3966
|
},
|
|
3967
|
+
"RecordAccount": {
|
|
3968
|
+
"type": "object",
|
|
3969
|
+
"nullable": true,
|
|
3970
|
+
"description": "The connected account a record belongs to \u2014 keyed exactly like the webhook `account` block and `connect.session.completed`, so one `provider:externalAccountId` key routes reads and events to the same user. `null` when it cannot be resolved (never guessed).",
|
|
3971
|
+
"properties": {
|
|
3972
|
+
"provider": {
|
|
3973
|
+
"type": "string",
|
|
3974
|
+
"example": "airbnb",
|
|
3975
|
+
"description": "airbnb, booking, booking_extranet, vrbo, or the PMS id (hostaway, cloudbeds, \u2026)."
|
|
3976
|
+
},
|
|
3977
|
+
"externalAccountId": {
|
|
3978
|
+
"type": "string",
|
|
3979
|
+
"example": "79730216",
|
|
3980
|
+
"description": "The provider's own account id \u2014 Airbnb host id, Booking.com hotel id, Extranet login, Vrbo account, or the PMS account."
|
|
3981
|
+
},
|
|
3982
|
+
"connectionId": {
|
|
3983
|
+
"type": "string",
|
|
3984
|
+
"nullable": true,
|
|
3985
|
+
"description": "Repull connection id (`X-Account-Id`), when the account has one. A string, like every id in API responses.",
|
|
3986
|
+
"example": "126"
|
|
3987
|
+
}
|
|
3988
|
+
}
|
|
3989
|
+
},
|
|
3696
3990
|
"WebhookEventAccount": {
|
|
3697
3991
|
"type": "object",
|
|
3698
3992
|
"nullable": true,
|
|
@@ -4400,6 +4694,42 @@
|
|
|
4400
4694
|
}
|
|
4401
4695
|
}
|
|
4402
4696
|
},
|
|
4697
|
+
"ConnectSessionCompletedEvent": {
|
|
4698
|
+
"type": "object",
|
|
4699
|
+
"required": [
|
|
4700
|
+
"event",
|
|
4701
|
+
"eventId",
|
|
4702
|
+
"apiVersion",
|
|
4703
|
+
"timestamp",
|
|
4704
|
+
"data"
|
|
4705
|
+
],
|
|
4706
|
+
"properties": {
|
|
4707
|
+
"event": {
|
|
4708
|
+
"type": "string",
|
|
4709
|
+
"description": "The event name. This field is `event`, not `type`."
|
|
4710
|
+
},
|
|
4711
|
+
"eventId": {
|
|
4712
|
+
"type": "string",
|
|
4713
|
+
"format": "uuid",
|
|
4714
|
+
"description": "Stable across every delivery and replay of this logical event \u2014 dedupe on it."
|
|
4715
|
+
},
|
|
4716
|
+
"apiVersion": {
|
|
4717
|
+
"type": "string",
|
|
4718
|
+
"example": "2026-04"
|
|
4719
|
+
},
|
|
4720
|
+
"timestamp": {
|
|
4721
|
+
"type": "string",
|
|
4722
|
+
"format": "date-time",
|
|
4723
|
+
"description": "When this delivery was built."
|
|
4724
|
+
},
|
|
4725
|
+
"account": {
|
|
4726
|
+
"$ref": "#/components/schemas/WebhookEventAccount"
|
|
4727
|
+
},
|
|
4728
|
+
"data": {
|
|
4729
|
+
"$ref": "#/components/schemas/ConnectSessionCompletedPayload"
|
|
4730
|
+
}
|
|
4731
|
+
}
|
|
4732
|
+
},
|
|
4403
4733
|
"AccountDisconnectedEvent": {
|
|
4404
4734
|
"type": "object",
|
|
4405
4735
|
"required": [
|
|
@@ -4957,6 +5287,9 @@
|
|
|
4957
5287
|
{
|
|
4958
5288
|
"$ref": "#/components/schemas/AccountCreatedEvent"
|
|
4959
5289
|
},
|
|
5290
|
+
{
|
|
5291
|
+
"$ref": "#/components/schemas/ConnectSessionCompletedEvent"
|
|
5292
|
+
},
|
|
4960
5293
|
{
|
|
4961
5294
|
"$ref": "#/components/schemas/AccountDisconnectedEvent"
|
|
4962
5295
|
},
|
|
@@ -5016,6 +5349,7 @@
|
|
|
5016
5349
|
"listing.reactivated": "#/components/schemas/ListingReactivatedEvent",
|
|
5017
5350
|
"calendar.updated": "#/components/schemas/CalendarUpdatedEvent",
|
|
5018
5351
|
"account.created": "#/components/schemas/AccountCreatedEvent",
|
|
5352
|
+
"connect.session.completed": "#/components/schemas/ConnectSessionCompletedEvent",
|
|
5019
5353
|
"account.disconnected": "#/components/schemas/AccountDisconnectedEvent",
|
|
5020
5354
|
"review.created": "#/components/schemas/ReviewCreatedEvent",
|
|
5021
5355
|
"review.responded": "#/components/schemas/ReviewRespondedEvent",
|
|
@@ -8143,6 +8477,24 @@
|
|
|
8143
8477
|
"nullable": true,
|
|
8144
8478
|
"description": "ISO timestamp the connection was first established."
|
|
8145
8479
|
},
|
|
8480
|
+
"platformId": {
|
|
8481
|
+
"type": "string",
|
|
8482
|
+
"nullable": true,
|
|
8483
|
+
"description": "The listing's id on the channel \u2014 Airbnb listing id, Booking.com room/property id, VRBO listing number.",
|
|
8484
|
+
"example": "5121372"
|
|
8485
|
+
},
|
|
8486
|
+
"channelStatus": {
|
|
8487
|
+
"type": "string",
|
|
8488
|
+
"nullable": true,
|
|
8489
|
+
"description": "Where the listing stands on the channel itself, when the channel reports it (VRBO): `online` \u2014 live and bookable; `offline` \u2014 hidden by the owner (`POST /v1/listings/{id}/online` brings it back); `not_live` \u2014 expired, new, still onboarding or deactivated by the channel (see `channelStatusDetail`). Null when not reported.",
|
|
8490
|
+
"example": "online"
|
|
8491
|
+
},
|
|
8492
|
+
"channelStatusDetail": {
|
|
8493
|
+
"type": "string",
|
|
8494
|
+
"nullable": true,
|
|
8495
|
+
"description": "The channel's own status word behind `channelStatus` (VRBO: `LIVE`, `InactiveByOwnerRequest`, `Expired`, `New`, \u2026).",
|
|
8496
|
+
"example": "LIVE"
|
|
8497
|
+
},
|
|
8146
8498
|
"lockedFields": {
|
|
8147
8499
|
"type": "array",
|
|
8148
8500
|
"items": {
|
|
@@ -11069,7 +11421,7 @@
|
|
|
11069
11421
|
},
|
|
11070
11422
|
"SendMessageRequest": {
|
|
11071
11423
|
"type": "object",
|
|
11072
|
-
"description": "`message`, `attachments`, or both. Per-channel limits for `attachments`:\n\n| Channel | Accepted types | Per file | Per request | Text |\n|---|---|---|---|---|\n| Airbnb | JPEG, PNG, GIF, WebP (sent as JPEG), MP4, QuickTime | 10 MB | 5 | optional \u2014 each file is sent as its own message, then the text |\n| Booking.com | JPEG, PNG | 10 MB | 5 | **required** \u2014 all files ride on the one text message |\n| SMS, email, direct-booking site chat | \u2014 | \u2014 | \u2014 | `422 attachments_not_supported`; nothing is sent |",
|
|
11424
|
+
"description": "`message`, `attachments`, or both. Per-channel limits for `attachments`:\n\n| Channel | Accepted types | Per file | Per request | Text |\n|---|---|---|---|---|\n| Airbnb | JPEG, PNG, GIF, WebP (sent as JPEG), MP4, QuickTime | 10 MB | 5 | optional \u2014 each file is sent as its own message, then the text |\n| Booking.com | JPEG, PNG | 10 MB | 5 | **required** \u2014 all files ride on the one text message |\n| VRBO, SMS, email, direct-booking site chat | \u2014 | \u2014 | \u2014 | `422 attachments_not_supported`; nothing is sent |",
|
|
11073
11425
|
"properties": {
|
|
11074
11426
|
"message": {
|
|
11075
11427
|
"type": "string",
|
|
@@ -12057,7 +12409,7 @@
|
|
|
12057
12409
|
},
|
|
12058
12410
|
"ChannelMarketStateItem": {
|
|
12059
12411
|
"type": "object",
|
|
12060
|
-
"description": "What happened on ONE channel item \u2014 one Airbnb connection,
|
|
12412
|
+
"description": "What happened on ONE channel item \u2014 one Airbnb connection, one Booking.com property, or one VRBO unit. A listing can carry several Airbnb connections (a re-list, or a move between host accounts) and each gets its own entry.",
|
|
12061
12413
|
"required": [
|
|
12062
12414
|
"channel",
|
|
12063
12415
|
"state",
|
|
@@ -12085,9 +12437,14 @@
|
|
|
12085
12437
|
"nullable": true,
|
|
12086
12438
|
"description": "The Booking.com property acted on. Present on Booking.com items; null when the property could not be resolved."
|
|
12087
12439
|
},
|
|
12440
|
+
"platformId": {
|
|
12441
|
+
"type": "string",
|
|
12442
|
+
"nullable": true,
|
|
12443
|
+
"description": "The VRBO listing number of the unit hidden or reactivated. Present on VRBO items."
|
|
12444
|
+
},
|
|
12088
12445
|
"code": {
|
|
12089
12446
|
"type": "string",
|
|
12090
|
-
"description": "Error code when `ok` is false \u2014 the SAME code the channel-specific endpoint returns for this failure, so one vocabulary covers both surfaces. Absent when `ok` is true.\n\nThe channel codes come in pairs, and the pair is the retryable split \u2014 the most useful bit in the whole item:\n\n- `airbnb_rejected` / `booking_rejected` \u2014 the channel refused the request AS SENT. `message` carries its own reason. Correct it and send again; resending the same thing is refused again.\n- `airbnb_error` / `booking_error` \u2014 the channel did not complete the request (outage, timeout, server error). Nothing about the request needs to change: retry with backoff.\n\nPlus `ambiguous_booking_mapping` (name the property with `hotelId`) and `payment_required` (a billing refusal, which keeps its own code rather than being buried under a channel one)."
|
|
12447
|
+
"description": "Error code when `ok` is false \u2014 the SAME code the channel-specific endpoint returns for this failure, so one vocabulary covers both surfaces. Absent when `ok` is true.\n\nThe channel codes come in pairs, and the pair is the retryable split \u2014 the most useful bit in the whole item:\n\n- `airbnb_rejected` / `booking_rejected` \u2014 the channel refused the request AS SENT. `message` carries its own reason. Correct it and send again; resending the same thing is refused again.\n- `airbnb_error` / `booking_error` \u2014 the channel did not complete the request (outage, timeout, server error). Nothing about the request needs to change: retry with backoff.\n\nPlus `ambiguous_booking_mapping` (name the property with `hotelId`) and `payment_required` (a billing refusal, which keeps its own code rather than being buried under a channel one). VRBO items: `vrbo_rejected` (VRBO still shows the unit in the old state after the change), `vrbo_error` (VRBO did not complete it \u2014 retry), `vrbo_not_ready` (the unit's VRBO details have not synced yet \u2014 retry in a few minutes), `vrbo_session_expired` (reconnect the VRBO account)."
|
|
12091
12448
|
},
|
|
12092
12449
|
"previousCode": {
|
|
12093
12450
|
"type": "string",
|
|
@@ -12105,7 +12462,7 @@
|
|
|
12105
12462
|
},
|
|
12106
12463
|
"verified": {
|
|
12107
12464
|
"type": "boolean",
|
|
12108
|
-
"description": "Airbnb
|
|
12465
|
+
"description": "Airbnb and VRBO: the listing was READ BACK afterwards and is in the state asked for \u2014 down after `offline`, live after `online`. Airbnb can accept a deactivation and leave a listing live, or accept an activation and keep it offline; either is returned as a failure, never as success. `false` means the read-back could not run \u2014 an unknown, not a success."
|
|
12109
12466
|
}
|
|
12110
12467
|
}
|
|
12111
12468
|
},
|
|
@@ -12713,6 +13070,16 @@
|
|
|
12713
13070
|
"example": "2026-08-01T00:00:00Z"
|
|
12714
13071
|
}
|
|
12715
13072
|
},
|
|
13073
|
+
"Account": {
|
|
13074
|
+
"name": "account",
|
|
13075
|
+
"in": "query",
|
|
13076
|
+
"required": false,
|
|
13077
|
+
"schema": {
|
|
13078
|
+
"type": "string",
|
|
13079
|
+
"example": "airbnb:79730216"
|
|
13080
|
+
},
|
|
13081
|
+
"description": "Only the records of one connected account, as `provider:externalAccountId` \u2014 the pair from a webhook `account` block, `connect.session.completed`, or `GET /v1/connect/{provider}` \u2192 `accounts`. A record belongs to an account when it is on that account's listings and on its channel (a PMS account: came in through that PMS). An account with no listings returns an empty page."
|
|
13082
|
+
},
|
|
12716
13083
|
"Offset": {
|
|
12717
13084
|
"name": "offset",
|
|
12718
13085
|
"in": "query",
|
|
@@ -13324,6 +13691,9 @@
|
|
|
13324
13691
|
"Properties"
|
|
13325
13692
|
],
|
|
13326
13693
|
"parameters": [
|
|
13694
|
+
{
|
|
13695
|
+
"$ref": "#/components/parameters/Account"
|
|
13696
|
+
},
|
|
13327
13697
|
{
|
|
13328
13698
|
"name": "limit",
|
|
13329
13699
|
"in": "query",
|
|
@@ -13594,6 +13964,9 @@
|
|
|
13594
13964
|
"Reservations"
|
|
13595
13965
|
],
|
|
13596
13966
|
"parameters": [
|
|
13967
|
+
{
|
|
13968
|
+
"$ref": "#/components/parameters/Account"
|
|
13969
|
+
},
|
|
13597
13970
|
{
|
|
13598
13971
|
"$ref": "#/components/parameters/XSchemaHeader"
|
|
13599
13972
|
},
|
|
@@ -14205,6 +14578,9 @@
|
|
|
14205
14578
|
"Conversations"
|
|
14206
14579
|
],
|
|
14207
14580
|
"parameters": [
|
|
14581
|
+
{
|
|
14582
|
+
"$ref": "#/components/parameters/Account"
|
|
14583
|
+
},
|
|
14208
14584
|
{
|
|
14209
14585
|
"$ref": "#/components/parameters/XSchemaHeader"
|
|
14210
14586
|
},
|
|
@@ -14473,7 +14849,7 @@
|
|
|
14473
14849
|
"post": {
|
|
14474
14850
|
"operationId": "send_conversation_message",
|
|
14475
14851
|
"summary": "Send a message to the guest",
|
|
14476
|
-
"description": "Sends a message to the guest on this conversation and records it in the thread.\n\nOmit `channel` and the message goes out on whichever channel the conversation already uses (Airbnb, Booking.com, SMS, email or the direct-booking site) \u2014 that is the right default. Pass `channel` only to force a specific one.\n\nThe message is attributed to the API: it is recorded with `aiGenerated` false so an API send is never counted as an automated reply.\n\n### Airbnb rewrites links \u2014 check `contentRewritten`\n\nAirbnb rejects guest messages containing a link, an email address or a phone number, and names the offending text. When that happens the offending fragment is stripped and the remainder is re-sent once, which means **the guest receives a message that is not the one you wrote**. Reporting that as a plain success would be a lie, so every response carries `contentRewritten`; when it is `true`, `deliveredContent` is the text that actually reached the guest. Check it before assuming your message went out verbatim.\n\nWhen the text cannot be salvaged (the link is most of the message) nothing is delivered and the call returns `422 message_not_sent` with the channel's verbatim refusal in `statusReason`.\n\nSend `Idempotency-Key` \u2014 without it, retrying after a network timeout sends the guest the same message twice.\n\n### Attachments\n\nSend files with `attachments: [{ url, contentType?, filename? }]` \u2014 public `https://` URLs, up to 5 per request, 10 MB each. `message` may be omitted when there are attachments (except on Booking.com). Repull downloads each file, reads its real type from the bytes, keeps a durable copy and delivers it through the channel's own file flow. **Every file is checked before anything is sent**: if one is unreachable, too large or of a type the channel refuses, the call returns 422 naming the file (`index`) and the guest receives nothing.\n\n| Channel | Accepted types | Text | How it arrives |\n|---|---|---|---|\n| Airbnb | JPEG, PNG, GIF, WebP (converted to JPEG), MP4, QuickTime | optional | each file as its own message, then the text as a separate message |\n| Booking.com | JPEG, PNG | **required** | one message carrying the text and every file |\n| SMS, email, direct-booking site chat | \u2014 | \u2014 | `422 attachments_not_supported`, nothing sent |\n\nAirbnb does not allow files in pre-booking (inquiry) conversations; that refusal comes back as `422 message_not_sent`. Because Airbnb delivers files one message at a time, a later file can be refused after earlier ones arrived \u2014 that returns `422 message_partially_sent` with `parts` saying exactly which messages reached the guest; resend only the rest.\n\nThe response's `attachments` lists each file's durable `url`, and `parts` lists every channel message the send produced. Read-back (`GET /v1/conversations/{id}/messages`) shows the same files in each message's `attachments`.\n\n**Inactive listings:** a conversation that belongs to an inactive listing returns `403 listing_inactive` and no message is sent. Activate the listing first.",
|
|
14852
|
+
"description": "Sends a message to the guest on this conversation and records it in the thread.\n\nOmit `channel` and the message goes out on whichever channel the conversation already uses (Airbnb, Booking.com, VRBO, SMS, email or the direct-booking site) \u2014 that is the right default. Pass `channel` only to force a specific one.\n\nThe message is attributed to the API: it is recorded with `aiGenerated` false so an API send is never counted as an automated reply.\n\n### Airbnb rewrites links \u2014 check `contentRewritten`\n\nAirbnb rejects guest messages containing a link, an email address or a phone number, and names the offending text. When that happens the offending fragment is stripped and the remainder is re-sent once, which means **the guest receives a message that is not the one you wrote**. Reporting that as a plain success would be a lie, so every response carries `contentRewritten`; when it is `true`, `deliveredContent` is the text that actually reached the guest. Check it before assuming your message went out verbatim.\n\nWhen the text cannot be salvaged (the link is most of the message) nothing is delivered and the call returns `422 message_not_sent` with the channel's verbatim refusal in `statusReason`.\n\nSend `Idempotency-Key` \u2014 without it, retrying after a network timeout sends the guest the same message twice.\n\n### Attachments\n\nSend files with `attachments: [{ url, contentType?, filename? }]` \u2014 public `https://` URLs, up to 5 per request, 10 MB each. `message` may be omitted when there are attachments (except on Booking.com). Repull downloads each file, reads its real type from the bytes, keeps a durable copy and delivers it through the channel's own file flow. **Every file is checked before anything is sent**: if one is unreachable, too large or of a type the channel refuses, the call returns 422 naming the file (`index`) and the guest receives nothing.\n\n| Channel | Accepted types | Text | How it arrives |\n|---|---|---|---|\n| Airbnb | JPEG, PNG, GIF, WebP (converted to JPEG), MP4, QuickTime | optional | each file as its own message, then the text as a separate message |\n| Booking.com | JPEG, PNG | **required** | one message carrying the text and every file |\n| VRBO, SMS, email, direct-booking site chat | \u2014 | \u2014 | `422 attachments_not_supported`, nothing sent |\n\nAirbnb does not allow files in pre-booking (inquiry) conversations; that refusal comes back as `422 message_not_sent`. Because Airbnb delivers files one message at a time, a later file can be refused after earlier ones arrived \u2014 that returns `422 message_partially_sent` with `parts` saying exactly which messages reached the guest; resend only the rest.\n\nThe response's `attachments` lists each file's durable `url`, and `parts` lists every channel message the send produced. Read-back (`GET /v1/conversations/{id}/messages`) shows the same files in each message's `attachments`.\n\n**Inactive listings:** a conversation that belongs to an inactive listing returns `403 listing_inactive` and no message is sent. Activate the listing first.",
|
|
14477
14853
|
"tags": [
|
|
14478
14854
|
"Conversations"
|
|
14479
14855
|
],
|
|
@@ -14843,6 +15219,9 @@
|
|
|
14843
15219
|
"Reviews"
|
|
14844
15220
|
],
|
|
14845
15221
|
"parameters": [
|
|
15222
|
+
{
|
|
15223
|
+
"$ref": "#/components/parameters/Account"
|
|
15224
|
+
},
|
|
14846
15225
|
{
|
|
14847
15226
|
"$ref": "#/components/parameters/XSchemaHeader"
|
|
14848
15227
|
},
|
|
@@ -15107,7 +15486,16 @@
|
|
|
15107
15486
|
"state": {
|
|
15108
15487
|
"type": "string",
|
|
15109
15488
|
"nullable": true,
|
|
15110
|
-
"description": "
|
|
15489
|
+
"description": "Your own correlation token, e.g. your user id (at most 500 characters). Echoed in this response, on the redirect back (`&state=`), in the popup message, and in the `connect.session.completed` webhook."
|
|
15490
|
+
},
|
|
15491
|
+
"accessType": {
|
|
15492
|
+
"type": "string",
|
|
15493
|
+
"enum": [
|
|
15494
|
+
"full_access",
|
|
15495
|
+
"messaging",
|
|
15496
|
+
"read_only"
|
|
15497
|
+
],
|
|
15498
|
+
"description": "What the connection may do. Airbnb: the OAuth scope tier. Vrbo: `messaging` (or `read_only`) imports bookings and messages and never pushes the calendar; `full_access` also pushes prices and availability. Setting it locks the choice; omit it to let the host choose on the hosted page (default `full_access`)."
|
|
15111
15499
|
},
|
|
15112
15500
|
"allowedProviders": {
|
|
15113
15501
|
"type": "array",
|
|
@@ -15321,7 +15709,7 @@
|
|
|
15321
15709
|
"post": {
|
|
15322
15710
|
"operationId": "create_connection",
|
|
15323
15711
|
"summary": "Connect to PMS/OTA provider",
|
|
15324
|
-
"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 designate FantasticStay in their Booking.com Extranet and paste their Hotel ID. Same response shape as Airbnb (`url`, `sessionId`, `expiresAt`).\n\
|
|
15712
|
+
"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 designate FantasticStay in their Booking.com Extranet and paste their Hotel ID. Same response shape as Airbnb (`url`, `sessionId`, `expiresAt`).\n\nPlumguide passes `clientId`/`clientSecret`. PMS 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`.",
|
|
15325
15713
|
"tags": [
|
|
15326
15714
|
"Connect"
|
|
15327
15715
|
],
|
|
@@ -15352,9 +15740,9 @@
|
|
|
15352
15740
|
"default": "full_access",
|
|
15353
15741
|
"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."
|
|
15354
15742
|
},
|
|
15355
|
-
"
|
|
15743
|
+
"state": {
|
|
15356
15744
|
"type": "string",
|
|
15357
|
-
"description": "
|
|
15745
|
+
"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."
|
|
15358
15746
|
},
|
|
15359
15747
|
"clientId": {
|
|
15360
15748
|
"type": "string",
|
|
@@ -16217,7 +16605,7 @@
|
|
|
16217
16605
|
"get": {
|
|
16218
16606
|
"operationId": "getChannelHealth",
|
|
16219
16607
|
"summary": "Per-channel connectivity health",
|
|
16220
|
-
"description": "Reports reachability and auth state for one channel (`airbnb`, `booking`, `vrbo`, `plumguide`). Use it to tell \"the channel is down\" apart from \"this workspace's connection expired\".",
|
|
16608
|
+
"description": "Reports reachability and auth state for one channel (`airbnb`, `booking`, `vrbo`, `plumguide`). 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 failed calendar pushes over finished ones in the last 3 hours (`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.",
|
|
16221
16609
|
"tags": [
|
|
16222
16610
|
"Health"
|
|
16223
16611
|
],
|
|
@@ -16245,8 +16633,46 @@
|
|
|
16245
16633
|
"application/json": {
|
|
16246
16634
|
"schema": {
|
|
16247
16635
|
"type": "object",
|
|
16248
|
-
"additionalProperties": true
|
|
16249
|
-
|
|
16636
|
+
"additionalProperties": true,
|
|
16637
|
+
"properties": {
|
|
16638
|
+
"status": {
|
|
16639
|
+
"type": "string",
|
|
16640
|
+
"enum": [
|
|
16641
|
+
"ok",
|
|
16642
|
+
"degraded",
|
|
16643
|
+
"down"
|
|
16644
|
+
]
|
|
16645
|
+
},
|
|
16646
|
+
"vrbo": {
|
|
16647
|
+
"type": "object",
|
|
16648
|
+
"description": "VRBO only \u2014 the connector's own signals.",
|
|
16649
|
+
"properties": {
|
|
16650
|
+
"accounts_connected": {
|
|
16651
|
+
"type": "integer"
|
|
16652
|
+
},
|
|
16653
|
+
"accounts_signed_out": {
|
|
16654
|
+
"type": "integer",
|
|
16655
|
+
"description": "Accounts VRBO signed out; `status` is `down` while any is."
|
|
16656
|
+
},
|
|
16657
|
+
"inbox_sync_late": {
|
|
16658
|
+
"type": "integer",
|
|
16659
|
+
"description": "Accounts whose last full inbox sync is older than 30 minutes (it runs every 5)."
|
|
16660
|
+
},
|
|
16661
|
+
"calendar_queue_backlog": {
|
|
16662
|
+
"type": "integer",
|
|
16663
|
+
"description": "Listings with a calendar push waiting."
|
|
16664
|
+
},
|
|
16665
|
+
"calendar_oldest_wait_minutes": {
|
|
16666
|
+
"type": "integer"
|
|
16667
|
+
},
|
|
16668
|
+
"window_hours": {
|
|
16669
|
+
"type": "integer",
|
|
16670
|
+
"description": "Hours the push failure rate is judged over."
|
|
16671
|
+
}
|
|
16672
|
+
}
|
|
16673
|
+
}
|
|
16674
|
+
}
|
|
16675
|
+
}
|
|
16250
16676
|
}
|
|
16251
16677
|
}
|
|
16252
16678
|
}
|
|
@@ -16421,7 +16847,7 @@
|
|
|
16421
16847
|
"post": {
|
|
16422
16848
|
"operationId": "replyToReview",
|
|
16423
16849
|
"summary": "Reply to a review on any channel",
|
|
16424
|
-
"description": "Resolves the review, reads its channel and dispatches the reply. Channel-neutral: you do not need to know where the review came from.\n\nReplies work on Airbnb
|
|
16850
|
+
"description": "Resolves the review, reads its channel and dispatches the reply. Channel-neutral: you do not need to know where the review came from.\n\nReplies work on Airbnb, Booking.com and VRBO. Each channel accepts one reply per review (VRBO: a second is `409 already_replied`; a review VRBO no longer takes a response to is `409 reply_not_allowed`). On VRBO the response is signed with a name \u2014 the connected account's host name, or `name` if you send it. A review from a channel without a reply API returns `422 unsupported_channel` naming the channels that do work.\n\nTo review a guest (Airbnb only), use `POST /v1/reviews/{id}/guest-review`.\n\n**Inactive listings:** a review of an inactive listing returns `403 listing_inactive` and no reply reaches the channel. Activate the listing first.",
|
|
16425
16851
|
"tags": [
|
|
16426
16852
|
"Reviews"
|
|
16427
16853
|
],
|
|
@@ -16446,6 +16872,11 @@
|
|
|
16446
16872
|
"message": {
|
|
16447
16873
|
"type": "string",
|
|
16448
16874
|
"description": "Reply text. `response` is accepted as an alias."
|
|
16875
|
+
},
|
|
16876
|
+
"name": {
|
|
16877
|
+
"type": "string",
|
|
16878
|
+
"maxLength": 80,
|
|
16879
|
+
"description": "VRBO: the name the response is signed with (the connected account's host name otherwise). Ignored on other channels."
|
|
16449
16880
|
}
|
|
16450
16881
|
},
|
|
16451
16882
|
"required": [
|
|
@@ -23907,7 +24338,7 @@
|
|
|
23907
24338
|
"get": {
|
|
23908
24339
|
"operationId": "list_vrbo_listings",
|
|
23909
24340
|
"summary": "List VRBO listings",
|
|
23910
|
-
"description": "List
|
|
24341
|
+
"description": "List the Vrbo units linked to this workspace's listings, from the host's connected Vrbo account (host sign-in, beta).\n\nInactive listings are left out; they keep syncing and reappear once activated. Use `GET /v1/listings?status=inactive` to find them.",
|
|
23911
24342
|
"tags": [
|
|
23912
24343
|
"VRBO"
|
|
23913
24344
|
],
|
|
@@ -23929,7 +24360,7 @@
|
|
|
23929
24360
|
"get": {
|
|
23930
24361
|
"operationId": "list_vrbo_reservations",
|
|
23931
24362
|
"summary": "List VRBO reservations",
|
|
23932
|
-
"description": "Cursor-paginated list of
|
|
24363
|
+
"description": "Cursor-paginated list of Vrbo reservations imported from the host's connected Vrbo account (host sign-in, beta). The full normalised record \u2014 guest, price breakdown, policy \u2014 is on `GET /v1/reservations?platform=vrbo`. `?offset=` is accepted as a first-class alias for `?cursor=` (mutually exclusive; offset capped at 10000).\n\nReservations on inactive listings are left out (counts and cursors included); they keep syncing and reappear once the listing is activated.",
|
|
23933
24364
|
"tags": [
|
|
23934
24365
|
"VRBO"
|
|
23935
24366
|
],
|
|
@@ -27521,8 +27952,8 @@
|
|
|
27521
27952
|
"/v1/conversations/{id}/pre-approval": {
|
|
27522
27953
|
"post": {
|
|
27523
27954
|
"operationId": "preapprove_conversation",
|
|
27524
|
-
"summary": "Pre-approve an inquiry",
|
|
27525
|
-
"description": "Pre-approve the
|
|
27955
|
+
"summary": "Pre-approve an inquiry (Airbnb, VRBO)",
|
|
27956
|
+
"description": "Pre-approve the inquiry on this conversation: the guest who asked about dates may now book them at the listed price, without waiting on you. To change the dates, guests or price, send a special offer instead (`POST /v1/conversations/{id}/special-offers`).\n\nFind inquiries that need an answer with `GET /v1/inquiries` (default `status=open`); each carries the `conversationId` to use here.\n\nOne endpoint for every channel with pre-approvals: **Airbnb** (listings connected directly) and **VRBO**. A Booking.com or direct-booking conversation, or an Airbnb one relayed through a PMS (Hostaway, Guesty), returns `422 channel_not_supported` and nothing is sent \u2014 `GET /v1/conversations/{id}` \u2192 `capabilities.canPreApprove` says where it works.\n\n`blockInstantBooking` is Airbnb only (VRBO has no such switch: `422 invalid_params`). `message` is sent to the guest with a VRBO pre-approval (a friendly default otherwise).\n\nThe inquiry is marked `pre_approved` everywhere, the same as pre-approving on the channel. Withdraw it with `DELETE /v1/conversations/{id}/pre-approval` (VRBO).\n\nA channel\u2019s refusal is never reported as a success: an inquiry that already moved on is `409 inquiry_no_longer_open`, an expired one `409 inquiry_expired`, a conversation that already has a booking `409 conversation_already_booked`.\n\nSend `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 \u2014 nothing was done \u2014 so retrying with the same key reaches Airbnb again.",
|
|
27526
27957
|
"tags": [
|
|
27527
27958
|
"Conversations"
|
|
27528
27959
|
],
|
|
@@ -27551,7 +27982,12 @@
|
|
|
27551
27982
|
"blockInstantBooking": {
|
|
27552
27983
|
"type": "boolean",
|
|
27553
27984
|
"default": false,
|
|
27554
|
-
"description": "
|
|
27985
|
+
"description": "Airbnb: when `true`, the guest cannot Instant Book the listing and must book through this pre-approval. Leave `false` unless you need that."
|
|
27986
|
+
},
|
|
27987
|
+
"message": {
|
|
27988
|
+
"type": "string",
|
|
27989
|
+
"maxLength": 2000,
|
|
27990
|
+
"description": "VRBO: the message sent to the guest with the pre-approval (a friendly default otherwise)."
|
|
27555
27991
|
}
|
|
27556
27992
|
}
|
|
27557
27993
|
},
|
|
@@ -27579,15 +28015,25 @@
|
|
|
27579
28015
|
"type": "object",
|
|
27580
28016
|
"required": [
|
|
27581
28017
|
"conversationId",
|
|
28018
|
+
"channel",
|
|
27582
28019
|
"status",
|
|
27583
28020
|
"blockInstantBooking",
|
|
27584
|
-
"expiresAt"
|
|
28021
|
+
"expiresAt",
|
|
28022
|
+
"message"
|
|
27585
28023
|
],
|
|
27586
28024
|
"properties": {
|
|
27587
28025
|
"conversationId": {
|
|
27588
28026
|
"type": "string",
|
|
27589
28027
|
"example": "164743"
|
|
27590
28028
|
},
|
|
28029
|
+
"channel": {
|
|
28030
|
+
"type": "string",
|
|
28031
|
+
"enum": [
|
|
28032
|
+
"airbnb",
|
|
28033
|
+
"vrbo"
|
|
28034
|
+
],
|
|
28035
|
+
"example": "airbnb"
|
|
28036
|
+
},
|
|
27591
28037
|
"status": {
|
|
27592
28038
|
"type": "string",
|
|
27593
28039
|
"enum": [
|
|
@@ -27602,15 +28048,22 @@
|
|
|
27602
28048
|
"type": "string",
|
|
27603
28049
|
"format": "date-time",
|
|
27604
28050
|
"nullable": true,
|
|
27605
|
-
"description": "When the guest can no longer book on the pre-approval, if
|
|
28051
|
+
"description": "When the guest can no longer book on the pre-approval, if the channel reported it."
|
|
28052
|
+
},
|
|
28053
|
+
"message": {
|
|
28054
|
+
"type": "string",
|
|
28055
|
+
"nullable": true,
|
|
28056
|
+
"description": "The message sent to the guest with the pre-approval (VRBO)."
|
|
27606
28057
|
}
|
|
27607
28058
|
}
|
|
27608
28059
|
},
|
|
27609
28060
|
"example": {
|
|
27610
28061
|
"conversationId": "164743",
|
|
28062
|
+
"channel": "airbnb",
|
|
27611
28063
|
"status": "pre_approved",
|
|
27612
28064
|
"blockInstantBooking": false,
|
|
27613
|
-
"expiresAt": "2026-09-23T17:40:38Z"
|
|
28065
|
+
"expiresAt": "2026-09-23T17:40:38Z",
|
|
28066
|
+
"message": null
|
|
27614
28067
|
}
|
|
27615
28068
|
}
|
|
27616
28069
|
}
|
|
@@ -27756,7 +28209,7 @@
|
|
|
27756
28209
|
"error": {
|
|
27757
28210
|
"code": "channel_not_supported",
|
|
27758
28211
|
"message": "Reservation 233530 came from Booking.com. Booking requests can only be accepted or declined on Airbnb \u2014 other channels confirm instantly or have no request step.",
|
|
27759
|
-
"fix": "Pre-approvals
|
|
28212
|
+
"fix": "Pre-approvals and special offers work on Airbnb (connected directly, not through a PMS such as Hostaway or Guesty) and VRBO; accepting/declining booking requests on Airbnb. `GET /v1/conversations/{id}` \u2192 `capabilities` says what works on a conversation. Booking.com and direct bookings confirm without a request step.",
|
|
27760
28213
|
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
27761
28214
|
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
27762
28215
|
"channel": "booking"
|
|
@@ -27878,13 +28331,233 @@
|
|
|
27878
28331
|
}
|
|
27879
28332
|
}
|
|
27880
28333
|
}
|
|
28334
|
+
},
|
|
28335
|
+
"delete": {
|
|
28336
|
+
"operationId": "withdraw_conversation_preapproval",
|
|
28337
|
+
"summary": "Withdraw a pre-approval",
|
|
28338
|
+
"description": "Withdraw the live pre-approval (or offer) on this conversation: the guest can no longer book on it, and the inquiry is open again. **VRBO**. On Airbnb a pre-approval is a special offer \u2014 withdraw it with `DELETE /v1/conversations/{id}/special-offers/{offerId}`; here it is `422 channel_not_supported`.\n\n`GET /v1/conversations/{id}` \u2192 `capabilities.canWithdraw` says whether there is something to withdraw.",
|
|
28339
|
+
"tags": [
|
|
28340
|
+
"Conversations"
|
|
28341
|
+
],
|
|
28342
|
+
"parameters": [
|
|
28343
|
+
{
|
|
28344
|
+
"name": "id",
|
|
28345
|
+
"in": "path",
|
|
28346
|
+
"required": true,
|
|
28347
|
+
"schema": {
|
|
28348
|
+
"type": "integer"
|
|
28349
|
+
},
|
|
28350
|
+
"description": "Repull conversation id (from `GET /v1/conversations` or `conversationId` on `GET /v1/inquiries`) \u2014 not the Airbnb thread id."
|
|
28351
|
+
}
|
|
28352
|
+
],
|
|
28353
|
+
"responses": {
|
|
28354
|
+
"200": {
|
|
28355
|
+
"description": "Withdrawn.",
|
|
28356
|
+
"content": {
|
|
28357
|
+
"application/json": {
|
|
28358
|
+
"schema": {
|
|
28359
|
+
"type": "object",
|
|
28360
|
+
"required": [
|
|
28361
|
+
"conversationId",
|
|
28362
|
+
"channel",
|
|
28363
|
+
"status"
|
|
28364
|
+
],
|
|
28365
|
+
"properties": {
|
|
28366
|
+
"conversationId": {
|
|
28367
|
+
"type": "string",
|
|
28368
|
+
"example": "166599"
|
|
28369
|
+
},
|
|
28370
|
+
"channel": {
|
|
28371
|
+
"type": "string",
|
|
28372
|
+
"nullable": true,
|
|
28373
|
+
"example": "vrbo"
|
|
28374
|
+
},
|
|
28375
|
+
"status": {
|
|
28376
|
+
"type": "string",
|
|
28377
|
+
"enum": [
|
|
28378
|
+
"withdrawn"
|
|
28379
|
+
]
|
|
28380
|
+
}
|
|
28381
|
+
}
|
|
28382
|
+
},
|
|
28383
|
+
"example": {
|
|
28384
|
+
"conversationId": "166599",
|
|
28385
|
+
"channel": "vrbo",
|
|
28386
|
+
"status": "withdrawn"
|
|
28387
|
+
}
|
|
28388
|
+
}
|
|
28389
|
+
}
|
|
28390
|
+
},
|
|
28391
|
+
"401": {
|
|
28392
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
28393
|
+
},
|
|
28394
|
+
"404": {
|
|
28395
|
+
"description": "The conversation does not exist in this workspace.",
|
|
28396
|
+
"content": {
|
|
28397
|
+
"application/json": {
|
|
28398
|
+
"schema": {
|
|
28399
|
+
"$ref": "#/components/schemas/Error"
|
|
28400
|
+
},
|
|
28401
|
+
"examples": {
|
|
28402
|
+
"notFound": {
|
|
28403
|
+
"summary": "No such conversation in this workspace",
|
|
28404
|
+
"value": {
|
|
28405
|
+
"error": {
|
|
28406
|
+
"code": "not_found",
|
|
28407
|
+
"message": "Conversation 164743 not found in this workspace.",
|
|
28408
|
+
"fix": "List reachable conversations with `GET /v1/conversations`, or open inquiries with `GET /v1/inquiries`.",
|
|
28409
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
28410
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678"
|
|
28411
|
+
}
|
|
28412
|
+
}
|
|
28413
|
+
}
|
|
28414
|
+
}
|
|
28415
|
+
}
|
|
28416
|
+
}
|
|
28417
|
+
},
|
|
28418
|
+
"409": {
|
|
28419
|
+
"description": "Nothing to withdraw: the inquiry is closed on the channel (`inquiry_no_longer_open`).",
|
|
28420
|
+
"content": {
|
|
28421
|
+
"application/json": {
|
|
28422
|
+
"schema": {
|
|
28423
|
+
"$ref": "#/components/schemas/Error"
|
|
28424
|
+
},
|
|
28425
|
+
"examples": {
|
|
28426
|
+
"noLongerOpen": {
|
|
28427
|
+
"summary": "Airbnb says the inquiry already moved on",
|
|
28428
|
+
"value": {
|
|
28429
|
+
"error": {
|
|
28430
|
+
"code": "inquiry_no_longer_open",
|
|
28431
|
+
"message": "This thread is not eligible for a special offer.",
|
|
28432
|
+
"fix": "The inquiry was already booked, declined, pre-approved or closed. Re-read the conversation \u2014 do not retry.",
|
|
28433
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
28434
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678"
|
|
28435
|
+
}
|
|
28436
|
+
}
|
|
28437
|
+
}
|
|
28438
|
+
}
|
|
28439
|
+
}
|
|
28440
|
+
}
|
|
28441
|
+
},
|
|
28442
|
+
"422": {
|
|
28443
|
+
"description": "`channel_not_supported` \u2014 not a VRBO conversation (on Airbnb, withdraw the special offer); `channel_rejected` \u2014 VRBO refused (its reason is in `message`).",
|
|
28444
|
+
"content": {
|
|
28445
|
+
"application/json": {
|
|
28446
|
+
"schema": {
|
|
28447
|
+
"$ref": "#/components/schemas/Error"
|
|
28448
|
+
},
|
|
28449
|
+
"examples": {
|
|
28450
|
+
"channelNotSupported": {
|
|
28451
|
+
"summary": "Not a direct Airbnb conversation or booking",
|
|
28452
|
+
"value": {
|
|
28453
|
+
"error": {
|
|
28454
|
+
"code": "channel_not_supported",
|
|
28455
|
+
"message": "Reservation 233530 came from Booking.com. Booking requests can only be accepted or declined on Airbnb \u2014 other channels confirm instantly or have no request step.",
|
|
28456
|
+
"fix": "Pre-approvals and special offers work on Airbnb (connected directly, not through a PMS such as Hostaway or Guesty) and VRBO; accepting/declining booking requests on Airbnb. `GET /v1/conversations/{id}` \u2192 `capabilities` says what works on a conversation. Booking.com and direct bookings confirm without a request step.",
|
|
28457
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
28458
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
28459
|
+
"channel": "booking"
|
|
28460
|
+
}
|
|
28461
|
+
}
|
|
28462
|
+
},
|
|
28463
|
+
"channelRejected": {
|
|
28464
|
+
"summary": "The channel refused the action",
|
|
28465
|
+
"value": {
|
|
28466
|
+
"error": {
|
|
28467
|
+
"code": "channel_rejected",
|
|
28468
|
+
"message": "The dates are no longer available.",
|
|
28469
|
+
"fix": "VRBO refused the action; its reason is in `message`. Do not retry unchanged.",
|
|
28470
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
28471
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
28472
|
+
"channel": "vrbo"
|
|
28473
|
+
}
|
|
28474
|
+
}
|
|
28475
|
+
}
|
|
28476
|
+
}
|
|
28477
|
+
}
|
|
28478
|
+
}
|
|
28479
|
+
},
|
|
28480
|
+
"429": {
|
|
28481
|
+
"description": "`airbnb_rate_limited` \u2014 back off and retry with the same `Idempotency-Key`.",
|
|
28482
|
+
"content": {
|
|
28483
|
+
"application/json": {
|
|
28484
|
+
"schema": {
|
|
28485
|
+
"$ref": "#/components/schemas/Error"
|
|
28486
|
+
},
|
|
28487
|
+
"examples": {
|
|
28488
|
+
"rateLimited": {
|
|
28489
|
+
"summary": "Airbnb rate-limited the request",
|
|
28490
|
+
"value": {
|
|
28491
|
+
"error": {
|
|
28492
|
+
"code": "airbnb_rate_limited",
|
|
28493
|
+
"message": "Too many requests.",
|
|
28494
|
+
"fix": "Back off and retry. Send the same `Idempotency-Key` so a retry cannot act twice.",
|
|
28495
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
28496
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678"
|
|
28497
|
+
}
|
|
28498
|
+
}
|
|
28499
|
+
}
|
|
28500
|
+
}
|
|
28501
|
+
}
|
|
28502
|
+
}
|
|
28503
|
+
},
|
|
28504
|
+
"500": {
|
|
28505
|
+
"description": "`service_misconfigured` \u2014 Repull could not reach the service that performs the action (its route was missing or refused our credentials). Nothing was sent to Airbnb. A fault on our side, not in the request: `retryable` is `false` and resending will not help until it is fixed. Any other 500 is `internal_error`.",
|
|
28506
|
+
"content": {
|
|
28507
|
+
"application/json": {
|
|
28508
|
+
"schema": {
|
|
28509
|
+
"$ref": "#/components/schemas/Error"
|
|
28510
|
+
},
|
|
28511
|
+
"examples": {
|
|
28512
|
+
"serviceMisconfigured": {
|
|
28513
|
+
"summary": "Repull could not reach the action (our fault, not retryable)",
|
|
28514
|
+
"value": {
|
|
28515
|
+
"error": {
|
|
28516
|
+
"code": "service_misconfigured",
|
|
28517
|
+
"message": "Pre-approval failed: Repull could not reach this action \u2014 the service that performs it answered HTTP 404 for its own endpoint. Nothing was sent to the channel.",
|
|
28518
|
+
"fix": "This is a fault in Repull, not in your request, and retrying will not help until it is fixed \u2014 do not change or resend the request. If it persists, contact support with the `request_id`.",
|
|
28519
|
+
"docs_url": "https://repull.dev/docs/errors/service_misconfigured",
|
|
28520
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
28521
|
+
"retryable": false
|
|
28522
|
+
}
|
|
28523
|
+
}
|
|
28524
|
+
}
|
|
28525
|
+
}
|
|
28526
|
+
}
|
|
28527
|
+
}
|
|
28528
|
+
},
|
|
28529
|
+
"502": {
|
|
28530
|
+
"description": "`airbnb_error` \u2014 Airbnb outage or timeout. Nothing about the request needs to change; retry with backoff.",
|
|
28531
|
+
"content": {
|
|
28532
|
+
"application/json": {
|
|
28533
|
+
"schema": {
|
|
28534
|
+
"$ref": "#/components/schemas/Error"
|
|
28535
|
+
},
|
|
28536
|
+
"examples": {
|
|
28537
|
+
"airbnbDown": {
|
|
28538
|
+
"summary": "Airbnb did not complete the request",
|
|
28539
|
+
"value": {
|
|
28540
|
+
"error": {
|
|
28541
|
+
"code": "airbnb_error",
|
|
28542
|
+
"message": "Airbnb error (503): Service Unavailable",
|
|
28543
|
+
"fix": "Airbnb did not complete the request (outage or timeout). Retry with backoff and the same `Idempotency-Key`.",
|
|
28544
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
28545
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678"
|
|
28546
|
+
}
|
|
28547
|
+
}
|
|
28548
|
+
}
|
|
28549
|
+
}
|
|
28550
|
+
}
|
|
28551
|
+
}
|
|
28552
|
+
}
|
|
28553
|
+
}
|
|
27881
28554
|
}
|
|
27882
28555
|
},
|
|
27883
28556
|
"/v1/conversations/{id}/special-offers": {
|
|
27884
28557
|
"post": {
|
|
27885
28558
|
"operationId": "create_conversation_special_offer",
|
|
27886
|
-
"summary": "Send a special offer",
|
|
27887
|
-
"description": "Send the guest on this conversation
|
|
28559
|
+
"summary": "Send a special offer (Airbnb, VRBO)",
|
|
28560
|
+
"description": "Send the guest on this conversation a special offer: your own dates, guest count and price. One endpoint for every channel that has offers \u2014 **Airbnb** (connected directly) and **VRBO** (its \u201cEdit quote\u201d). Use it to answer an inquiry with different terms. To accept the guest\u2019s own dates and price as they asked, pre-approve instead (`POST /v1/conversations/{id}/pre-approval`).\n\n**How the price is set depends on the channel** \u2014 `GET /v1/conversations/{id}` \u2192 `capabilities.offerPrice` says which:\n- `total` (Airbnb): send `totalPrice`, the whole stay in the listing\u2019s Airbnb currency, with `checkIn`, `checkOut` and `guests`.\n- `breakdown` (VRBO): send the price\u2019s parts \u2014 `rentalAmount` (rent, excluding fees), `fees` by VRBO fee type, `damageDeposit` \u2014 and VRBO computes the guest total, adding its taxes and service fee. Dates and party are optional (omitted \u2192 the inquiry\u2019s own). Only what you send is changed. Preview the result first with `POST /v1/conversations/{id}/special-offers/preview`.\n\nSending the other kind is `422 offer_price_total_required` / `offer_price_breakdown_required` naming the field; nothing is sent. A channel without offers (Booking.com, direct, an Airbnb inquiry relayed by a PMS) is `422 channel_not_supported`.\n\n`listingId` (Airbnb) is optional: omit it to offer the listing the guest asked about. It is a **Repull** listing id. `message` (VRBO) is sent to the guest with the offer.\n\nAn offer the channel refuses is never a `201`: dates that are taken, a price below the channel\u2019s minimum and the like are `422` with the channel\u2019s own reason in `message`.\n\nSend `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 \u2014 nothing was done \u2014 so retrying with the same key reaches Airbnb again. Without it, a retry after a timeout can send the guest two offers.\n\nRead or withdraw the offer with `GET` / `DELETE /v1/conversations/{id}/special-offers/{offerId}` (VRBO: `offerId` = `current`).",
|
|
27888
28561
|
"tags": [
|
|
27889
28562
|
"Conversations"
|
|
27890
28563
|
],
|
|
@@ -27909,12 +28582,7 @@
|
|
|
27909
28582
|
"schema": {
|
|
27910
28583
|
"type": "object",
|
|
27911
28584
|
"additionalProperties": false,
|
|
27912
|
-
"
|
|
27913
|
-
"checkIn",
|
|
27914
|
-
"checkOut",
|
|
27915
|
-
"guests",
|
|
27916
|
-
"totalPrice"
|
|
27917
|
-
],
|
|
28585
|
+
"description": "Priced by `totalPrice` (Airbnb) OR by its parts \u2014 `rentalAmount`, `fees`, `damageDeposit` (VRBO) \u2014 never both. With `totalPrice`, `checkIn`, `checkOut` and `guests` are required.",
|
|
27918
28586
|
"properties": {
|
|
27919
28587
|
"listingId": {
|
|
27920
28588
|
"type": "integer",
|
|
@@ -27965,25 +28633,85 @@
|
|
|
27965
28633
|
"type": "number",
|
|
27966
28634
|
"exclusiveMinimum": true,
|
|
27967
28635
|
"minimum": 0,
|
|
27968
|
-
"description": "
|
|
28636
|
+
"description": "Airbnb: the total the guest pays for the whole stay, in the listing\u2019s Airbnb currency.",
|
|
27969
28637
|
"example": 880
|
|
27970
|
-
}
|
|
27971
|
-
|
|
27972
|
-
|
|
27973
|
-
|
|
27974
|
-
|
|
27975
|
-
|
|
27976
|
-
|
|
27977
|
-
|
|
27978
|
-
"
|
|
27979
|
-
|
|
27980
|
-
|
|
27981
|
-
|
|
27982
|
-
|
|
27983
|
-
|
|
27984
|
-
|
|
27985
|
-
|
|
27986
|
-
|
|
28638
|
+
},
|
|
28639
|
+
"rentalAmount": {
|
|
28640
|
+
"type": "number",
|
|
28641
|
+
"exclusiveMinimum": true,
|
|
28642
|
+
"minimum": 0,
|
|
28643
|
+
"description": "VRBO: rent for the whole stay, excluding fees and taxes.",
|
|
28644
|
+
"example": 4636
|
|
28645
|
+
},
|
|
28646
|
+
"fees": {
|
|
28647
|
+
"type": "array",
|
|
28648
|
+
"description": "VRBO: the offer\u2019s fees \u2014 replaces its fee list. `type` is VRBO\u2019s fee type (`CLEANING`, `PET`, \u2026).",
|
|
28649
|
+
"items": {
|
|
28650
|
+
"type": "object",
|
|
28651
|
+
"required": [
|
|
28652
|
+
"type",
|
|
28653
|
+
"value"
|
|
28654
|
+
],
|
|
28655
|
+
"properties": {
|
|
28656
|
+
"type": {
|
|
28657
|
+
"type": "string",
|
|
28658
|
+
"example": "CLEANING"
|
|
28659
|
+
},
|
|
28660
|
+
"value": {
|
|
28661
|
+
"type": "number",
|
|
28662
|
+
"minimum": 0,
|
|
28663
|
+
"example": 390
|
|
28664
|
+
}
|
|
28665
|
+
}
|
|
28666
|
+
}
|
|
28667
|
+
},
|
|
28668
|
+
"damageDeposit": {
|
|
28669
|
+
"type": "number",
|
|
28670
|
+
"nullable": true,
|
|
28671
|
+
"minimum": 0,
|
|
28672
|
+
"description": "VRBO: refundable damage deposit; `null` for none.",
|
|
28673
|
+
"example": 500
|
|
28674
|
+
},
|
|
28675
|
+
"message": {
|
|
28676
|
+
"type": "string",
|
|
28677
|
+
"maxLength": 2000,
|
|
28678
|
+
"description": "VRBO: the message sent to the guest with the offer (a friendly default otherwise)."
|
|
28679
|
+
}
|
|
28680
|
+
}
|
|
28681
|
+
},
|
|
28682
|
+
"examples": {
|
|
28683
|
+
"airbnb": {
|
|
28684
|
+
"summary": "Airbnb \u2014 one total",
|
|
28685
|
+
"value": {
|
|
28686
|
+
"checkIn": "2026-10-01",
|
|
28687
|
+
"checkOut": "2026-10-05",
|
|
28688
|
+
"guests": {
|
|
28689
|
+
"adults": 2,
|
|
28690
|
+
"children": 1
|
|
28691
|
+
},
|
|
28692
|
+
"totalPrice": 880
|
|
28693
|
+
}
|
|
28694
|
+
},
|
|
28695
|
+
"vrbo": {
|
|
28696
|
+
"summary": "VRBO \u2014 the price\u2019s parts (VRBO computes the total)",
|
|
28697
|
+
"value": {
|
|
28698
|
+
"rentalAmount": 4636,
|
|
28699
|
+
"fees": [
|
|
28700
|
+
{
|
|
28701
|
+
"type": "CLEANING",
|
|
28702
|
+
"value": 390
|
|
28703
|
+
}
|
|
28704
|
+
],
|
|
28705
|
+
"damageDeposit": 500,
|
|
28706
|
+
"message": "Here is a custom quote for your stay."
|
|
28707
|
+
}
|
|
28708
|
+
}
|
|
28709
|
+
}
|
|
28710
|
+
}
|
|
28711
|
+
}
|
|
28712
|
+
},
|
|
28713
|
+
"responses": {
|
|
28714
|
+
"201": {
|
|
27987
28715
|
"description": "Offer sent. The guest can book it until `expiresAt`.",
|
|
27988
28716
|
"content": {
|
|
27989
28717
|
"application/json": {
|
|
@@ -28002,7 +28730,7 @@
|
|
|
28002
28730
|
"id": {
|
|
28003
28731
|
"type": "string",
|
|
28004
28732
|
"nullable": true,
|
|
28005
|
-
"description": "
|
|
28733
|
+
"description": "The offer id \u2014 use it to read or withdraw the offer. Airbnb\u2019s special-offer id; on VRBO, where a conversation has one live offer, `current`.",
|
|
28006
28734
|
"example": "1459920384"
|
|
28007
28735
|
},
|
|
28008
28736
|
"conversationId": {
|
|
@@ -28010,10 +28738,19 @@
|
|
|
28010
28738
|
"description": "Repull conversation id the offer was sent on.",
|
|
28011
28739
|
"example": "164743"
|
|
28012
28740
|
},
|
|
28741
|
+
"channel": {
|
|
28742
|
+
"type": "string",
|
|
28743
|
+
"enum": [
|
|
28744
|
+
"airbnb",
|
|
28745
|
+
"vrbo"
|
|
28746
|
+
],
|
|
28747
|
+
"description": "The channel the offer is on.",
|
|
28748
|
+
"example": "airbnb"
|
|
28749
|
+
},
|
|
28013
28750
|
"status": {
|
|
28014
28751
|
"type": "string",
|
|
28015
28752
|
"nullable": true,
|
|
28016
|
-
"description": "Airbnb
|
|
28753
|
+
"description": "Airbnb: its status for the offer \u2014 `active` (the guest can book it), `accepted`, `declined`, `expired` or `voided` (withdrawn). VRBO: `sent` (just sent), `current` (the live offer) or `preview` (recalculated, not sent).",
|
|
28017
28754
|
"example": "active"
|
|
28018
28755
|
},
|
|
28019
28756
|
"listingId": {
|
|
@@ -28080,9 +28817,75 @@
|
|
|
28080
28817
|
"totalPrice": {
|
|
28081
28818
|
"type": "number",
|
|
28082
28819
|
"nullable": true,
|
|
28083
|
-
"description": "
|
|
28820
|
+
"description": "What the guest pays for the stay. Airbnb: the total you set. VRBO: VRBO\u2019s own total, including its taxes and service fee.",
|
|
28084
28821
|
"example": 880
|
|
28085
28822
|
},
|
|
28823
|
+
"currency": {
|
|
28824
|
+
"type": "string",
|
|
28825
|
+
"nullable": true,
|
|
28826
|
+
"description": "Currency of the amounts, when the channel states it (VRBO).",
|
|
28827
|
+
"example": "CAD"
|
|
28828
|
+
},
|
|
28829
|
+
"rentalAmount": {
|
|
28830
|
+
"type": "number",
|
|
28831
|
+
"nullable": true,
|
|
28832
|
+
"description": "VRBO: rent for the stay, excluding fees and taxes. Null on Airbnb (priced by one total).",
|
|
28833
|
+
"example": 4041.9
|
|
28834
|
+
},
|
|
28835
|
+
"discount": {
|
|
28836
|
+
"type": "number",
|
|
28837
|
+
"nullable": true,
|
|
28838
|
+
"description": "VRBO: its automatic stay discount on the rent, when the offer carries one."
|
|
28839
|
+
},
|
|
28840
|
+
"fees": {
|
|
28841
|
+
"type": "array",
|
|
28842
|
+
"description": "VRBO: the offer\u2019s fees by type. Empty on Airbnb.",
|
|
28843
|
+
"items": {
|
|
28844
|
+
"type": "object",
|
|
28845
|
+
"properties": {
|
|
28846
|
+
"type": {
|
|
28847
|
+
"type": "string",
|
|
28848
|
+
"example": "CLEANING"
|
|
28849
|
+
},
|
|
28850
|
+
"value": {
|
|
28851
|
+
"type": "number",
|
|
28852
|
+
"example": 400
|
|
28853
|
+
},
|
|
28854
|
+
"label": {
|
|
28855
|
+
"type": "string",
|
|
28856
|
+
"nullable": true,
|
|
28857
|
+
"example": "Cleaning Fee"
|
|
28858
|
+
}
|
|
28859
|
+
}
|
|
28860
|
+
}
|
|
28861
|
+
},
|
|
28862
|
+
"damageDeposit": {
|
|
28863
|
+
"type": "number",
|
|
28864
|
+
"nullable": true,
|
|
28865
|
+
"description": "VRBO: refundable damage deposit; null for none.",
|
|
28866
|
+
"example": 500
|
|
28867
|
+
},
|
|
28868
|
+
"lines": {
|
|
28869
|
+
"type": "array",
|
|
28870
|
+
"description": "VRBO: its offer summary line by line, in VRBO\u2019s words (nights, fees, taxes, total traveler payment, payout).",
|
|
28871
|
+
"items": {
|
|
28872
|
+
"type": "object",
|
|
28873
|
+
"properties": {
|
|
28874
|
+
"label": {
|
|
28875
|
+
"type": "string"
|
|
28876
|
+
},
|
|
28877
|
+
"value": {
|
|
28878
|
+
"type": "string",
|
|
28879
|
+
"nullable": true
|
|
28880
|
+
}
|
|
28881
|
+
}
|
|
28882
|
+
}
|
|
28883
|
+
},
|
|
28884
|
+
"message": {
|
|
28885
|
+
"type": "string",
|
|
28886
|
+
"nullable": true,
|
|
28887
|
+
"description": "The message sent to the guest with the offer (VRBO)."
|
|
28888
|
+
},
|
|
28086
28889
|
"createdAt": {
|
|
28087
28890
|
"type": "string",
|
|
28088
28891
|
"format": "date-time",
|
|
@@ -28099,6 +28902,7 @@
|
|
|
28099
28902
|
"example": {
|
|
28100
28903
|
"id": "1459920384",
|
|
28101
28904
|
"conversationId": "164743",
|
|
28905
|
+
"channel": "airbnb",
|
|
28102
28906
|
"status": "active",
|
|
28103
28907
|
"listingId": "23892",
|
|
28104
28908
|
"airbnbListingId": "955656266214757921",
|
|
@@ -28113,6 +28917,13 @@
|
|
|
28113
28917
|
"pets": 0
|
|
28114
28918
|
},
|
|
28115
28919
|
"totalPrice": 880,
|
|
28920
|
+
"currency": null,
|
|
28921
|
+
"rentalAmount": null,
|
|
28922
|
+
"discount": null,
|
|
28923
|
+
"fees": [],
|
|
28924
|
+
"damageDeposit": null,
|
|
28925
|
+
"lines": [],
|
|
28926
|
+
"message": null,
|
|
28116
28927
|
"createdAt": "2026-09-22T18:00:00Z",
|
|
28117
28928
|
"expiresAt": "2026-09-23T18:00:00Z"
|
|
28118
28929
|
}
|
|
@@ -28199,7 +29010,7 @@
|
|
|
28199
29010
|
}
|
|
28200
29011
|
},
|
|
28201
29012
|
"409": {
|
|
28202
|
-
"description": "The inquiry cannot take an offer any more. `inquiry_no_longer_open` \u2014
|
|
29013
|
+
"description": "The inquiry cannot take an offer any more. `inquiry_no_longer_open` \u2014 the channel says it was booked or closed; `inquiry_expired` \u2014 it lapsed; `offer_already_sent` (VRBO) \u2014 a pre-approval or offer is live, withdraw it first. Do not retry unchanged.",
|
|
28203
29014
|
"content": {
|
|
28204
29015
|
"application/json": {
|
|
28205
29016
|
"schema": {
|
|
@@ -28229,19 +29040,71 @@
|
|
|
28229
29040
|
"request_id": "req_01J5X7Y8Z9ABCDEF12345678"
|
|
28230
29041
|
}
|
|
28231
29042
|
}
|
|
29043
|
+
},
|
|
29044
|
+
"alreadySent": {
|
|
29045
|
+
"summary": "A pre-approval or offer is already live (VRBO)",
|
|
29046
|
+
"value": {
|
|
29047
|
+
"error": {
|
|
29048
|
+
"code": "offer_already_sent",
|
|
29049
|
+
"message": "This conversation already has a live pre-approval.",
|
|
29050
|
+
"fix": "A pre-approval or offer is already live. Withdraw it first \u2014 `DELETE /v1/conversations/{id}/pre-approval` \u2014 then send the new one.",
|
|
29051
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
29052
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678"
|
|
29053
|
+
}
|
|
29054
|
+
}
|
|
28232
29055
|
}
|
|
28233
29056
|
}
|
|
28234
29057
|
}
|
|
28235
29058
|
}
|
|
28236
29059
|
},
|
|
28237
29060
|
"422": {
|
|
28238
|
-
"description": "`invalid_params` \u2014 the body is wrong and `field` names it; `airbnb_rejected` \u2014
|
|
29061
|
+
"description": "`invalid_params` \u2014 the body is wrong and `field` names it; `offer_price_total_required` / `offer_price_breakdown_required` \u2014 the price is the other kind than this channel takes; `airbnb_rejected` / `channel_rejected` \u2014 the channel refused the offer (its reason is in `message`); `listing_not_on_airbnb` \u2014 the offered listing is not on Airbnb; `channel_not_supported` \u2014 the conversation has no offers; `airbnb_link_missing` \u2014 no Airbnb thread or host on record.",
|
|
28239
29062
|
"content": {
|
|
28240
29063
|
"application/json": {
|
|
28241
29064
|
"schema": {
|
|
28242
29065
|
"$ref": "#/components/schemas/Error"
|
|
28243
29066
|
},
|
|
28244
29067
|
"examples": {
|
|
29068
|
+
"breakdownRequired": {
|
|
29069
|
+
"summary": "A total on VRBO, which prices an offer by its parts",
|
|
29070
|
+
"value": {
|
|
29071
|
+
"error": {
|
|
29072
|
+
"code": "offer_price_breakdown_required",
|
|
29073
|
+
"message": "VRBO calculates the guest total itself (it adds its taxes and service fee), so an offer on VRBO is priced by its parts: send `rentalAmount` and/or `fees` and `damageDeposit`, not `totalPrice`.",
|
|
29074
|
+
"fix": "Send the parts \u2014 `rentalAmount` and/or `fees`, `damageDeposit` \u2014 instead of `totalPrice`; VRBO adds its taxes and service fee to reach the guest total. Preview it first with `POST /v1/conversations/{id}/special-offers/preview`.",
|
|
29075
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
29076
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
29077
|
+
"field": "totalPrice",
|
|
29078
|
+
"channel": "vrbo"
|
|
29079
|
+
}
|
|
29080
|
+
}
|
|
29081
|
+
},
|
|
29082
|
+
"totalRequired": {
|
|
29083
|
+
"summary": "Price parts on Airbnb, which takes one total",
|
|
29084
|
+
"value": {
|
|
29085
|
+
"error": {
|
|
29086
|
+
"code": "offer_price_total_required",
|
|
29087
|
+
"message": "Airbnb takes one price for the whole stay: send `totalPrice`, not `rentalAmount` / `fees` / `damageDeposit`.",
|
|
29088
|
+
"fix": "Send `totalPrice` (the total for the stay) instead of `rentalAmount` / `fees` / `damageDeposit`.",
|
|
29089
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
29090
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
29091
|
+
"field": "totalPrice"
|
|
29092
|
+
}
|
|
29093
|
+
}
|
|
29094
|
+
},
|
|
29095
|
+
"channelRejected": {
|
|
29096
|
+
"summary": "The channel refused the action",
|
|
29097
|
+
"value": {
|
|
29098
|
+
"error": {
|
|
29099
|
+
"code": "channel_rejected",
|
|
29100
|
+
"message": "The dates are no longer available.",
|
|
29101
|
+
"fix": "VRBO refused the action; its reason is in `message`. Do not retry unchanged.",
|
|
29102
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
29103
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
29104
|
+
"channel": "vrbo"
|
|
29105
|
+
}
|
|
29106
|
+
}
|
|
29107
|
+
},
|
|
28245
29108
|
"checkOut": {
|
|
28246
29109
|
"summary": "Invalid `checkOut`",
|
|
28247
29110
|
"value": {
|
|
@@ -28299,7 +29162,7 @@
|
|
|
28299
29162
|
"error": {
|
|
28300
29163
|
"code": "channel_not_supported",
|
|
28301
29164
|
"message": "Reservation 233530 came from Booking.com. Booking requests can only be accepted or declined on Airbnb \u2014 other channels confirm instantly or have no request step.",
|
|
28302
|
-
"fix": "Pre-approvals
|
|
29165
|
+
"fix": "Pre-approvals and special offers work on Airbnb (connected directly, not through a PMS such as Hostaway or Guesty) and VRBO; accepting/declining booking requests on Airbnb. `GET /v1/conversations/{id}` \u2192 `capabilities` says what works on a conversation. Booking.com and direct bookings confirm without a request step.",
|
|
28303
29166
|
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
28304
29167
|
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
28305
29168
|
"channel": "booking"
|
|
@@ -28402,7 +29265,7 @@
|
|
|
28402
29265
|
"get": {
|
|
28403
29266
|
"operationId": "get_conversation_special_offer",
|
|
28404
29267
|
"summary": "Get a special offer",
|
|
28405
|
-
"description": "Read a special offer on this conversation
|
|
29268
|
+
"description": "Read a special offer on this conversation \u2014 typically to check its `status`. Airbnb: read live with the conversation\u2019s own Airbnb account (`active` until the guest books it, it expires, or you withdraw it). VRBO (`offerId` = `current`): the live offer as last synced from VRBO, priced by its parts with VRBO\u2019s total.",
|
|
28406
29269
|
"tags": [
|
|
28407
29270
|
"Conversations"
|
|
28408
29271
|
],
|
|
@@ -28423,7 +29286,7 @@
|
|
|
28423
29286
|
"schema": {
|
|
28424
29287
|
"type": "string"
|
|
28425
29288
|
},
|
|
28426
|
-
"description": "The special offer\u2019s `id`, as returned by `POST /v1/conversations/{id}/special-offers`.",
|
|
29289
|
+
"description": "The special offer\u2019s `id`, as returned by `POST /v1/conversations/{id}/special-offers`. On VRBO, where a conversation has one live offer, `current`.",
|
|
28427
29290
|
"example": "1459920384"
|
|
28428
29291
|
}
|
|
28429
29292
|
],
|
|
@@ -28447,7 +29310,7 @@
|
|
|
28447
29310
|
"id": {
|
|
28448
29311
|
"type": "string",
|
|
28449
29312
|
"nullable": true,
|
|
28450
|
-
"description": "
|
|
29313
|
+
"description": "The offer id \u2014 use it to read or withdraw the offer. Airbnb\u2019s special-offer id; on VRBO, where a conversation has one live offer, `current`.",
|
|
28451
29314
|
"example": "1459920384"
|
|
28452
29315
|
},
|
|
28453
29316
|
"conversationId": {
|
|
@@ -28455,10 +29318,19 @@
|
|
|
28455
29318
|
"description": "Repull conversation id the offer was sent on.",
|
|
28456
29319
|
"example": "164743"
|
|
28457
29320
|
},
|
|
29321
|
+
"channel": {
|
|
29322
|
+
"type": "string",
|
|
29323
|
+
"enum": [
|
|
29324
|
+
"airbnb",
|
|
29325
|
+
"vrbo"
|
|
29326
|
+
],
|
|
29327
|
+
"description": "The channel the offer is on.",
|
|
29328
|
+
"example": "airbnb"
|
|
29329
|
+
},
|
|
28458
29330
|
"status": {
|
|
28459
29331
|
"type": "string",
|
|
28460
29332
|
"nullable": true,
|
|
28461
|
-
"description": "Airbnb
|
|
29333
|
+
"description": "Airbnb: its status for the offer \u2014 `active` (the guest can book it), `accepted`, `declined`, `expired` or `voided` (withdrawn). VRBO: `sent` (just sent), `current` (the live offer) or `preview` (recalculated, not sent).",
|
|
28462
29334
|
"example": "active"
|
|
28463
29335
|
},
|
|
28464
29336
|
"listingId": {
|
|
@@ -28525,9 +29397,75 @@
|
|
|
28525
29397
|
"totalPrice": {
|
|
28526
29398
|
"type": "number",
|
|
28527
29399
|
"nullable": true,
|
|
28528
|
-
"description": "
|
|
29400
|
+
"description": "What the guest pays for the stay. Airbnb: the total you set. VRBO: VRBO\u2019s own total, including its taxes and service fee.",
|
|
28529
29401
|
"example": 880
|
|
28530
29402
|
},
|
|
29403
|
+
"currency": {
|
|
29404
|
+
"type": "string",
|
|
29405
|
+
"nullable": true,
|
|
29406
|
+
"description": "Currency of the amounts, when the channel states it (VRBO).",
|
|
29407
|
+
"example": "CAD"
|
|
29408
|
+
},
|
|
29409
|
+
"rentalAmount": {
|
|
29410
|
+
"type": "number",
|
|
29411
|
+
"nullable": true,
|
|
29412
|
+
"description": "VRBO: rent for the stay, excluding fees and taxes. Null on Airbnb (priced by one total).",
|
|
29413
|
+
"example": 4041.9
|
|
29414
|
+
},
|
|
29415
|
+
"discount": {
|
|
29416
|
+
"type": "number",
|
|
29417
|
+
"nullable": true,
|
|
29418
|
+
"description": "VRBO: its automatic stay discount on the rent, when the offer carries one."
|
|
29419
|
+
},
|
|
29420
|
+
"fees": {
|
|
29421
|
+
"type": "array",
|
|
29422
|
+
"description": "VRBO: the offer\u2019s fees by type. Empty on Airbnb.",
|
|
29423
|
+
"items": {
|
|
29424
|
+
"type": "object",
|
|
29425
|
+
"properties": {
|
|
29426
|
+
"type": {
|
|
29427
|
+
"type": "string",
|
|
29428
|
+
"example": "CLEANING"
|
|
29429
|
+
},
|
|
29430
|
+
"value": {
|
|
29431
|
+
"type": "number",
|
|
29432
|
+
"example": 400
|
|
29433
|
+
},
|
|
29434
|
+
"label": {
|
|
29435
|
+
"type": "string",
|
|
29436
|
+
"nullable": true,
|
|
29437
|
+
"example": "Cleaning Fee"
|
|
29438
|
+
}
|
|
29439
|
+
}
|
|
29440
|
+
}
|
|
29441
|
+
},
|
|
29442
|
+
"damageDeposit": {
|
|
29443
|
+
"type": "number",
|
|
29444
|
+
"nullable": true,
|
|
29445
|
+
"description": "VRBO: refundable damage deposit; null for none.",
|
|
29446
|
+
"example": 500
|
|
29447
|
+
},
|
|
29448
|
+
"lines": {
|
|
29449
|
+
"type": "array",
|
|
29450
|
+
"description": "VRBO: its offer summary line by line, in VRBO\u2019s words (nights, fees, taxes, total traveler payment, payout).",
|
|
29451
|
+
"items": {
|
|
29452
|
+
"type": "object",
|
|
29453
|
+
"properties": {
|
|
29454
|
+
"label": {
|
|
29455
|
+
"type": "string"
|
|
29456
|
+
},
|
|
29457
|
+
"value": {
|
|
29458
|
+
"type": "string",
|
|
29459
|
+
"nullable": true
|
|
29460
|
+
}
|
|
29461
|
+
}
|
|
29462
|
+
}
|
|
29463
|
+
},
|
|
29464
|
+
"message": {
|
|
29465
|
+
"type": "string",
|
|
29466
|
+
"nullable": true,
|
|
29467
|
+
"description": "The message sent to the guest with the offer (VRBO)."
|
|
29468
|
+
},
|
|
28531
29469
|
"createdAt": {
|
|
28532
29470
|
"type": "string",
|
|
28533
29471
|
"format": "date-time",
|
|
@@ -28624,7 +29562,7 @@
|
|
|
28624
29562
|
}
|
|
28625
29563
|
},
|
|
28626
29564
|
"422": {
|
|
28627
|
-
"description": "`invalid_params` \u2014 `id` or `offerId` is malformed; `channel_not_supported` \u2014
|
|
29565
|
+
"description": "`invalid_params` \u2014 `id` or `offerId` is malformed; `channel_not_supported` \u2014 the conversation has no offers (only Airbnb connected directly, and VRBO, do).",
|
|
28628
29566
|
"content": {
|
|
28629
29567
|
"application/json": {
|
|
28630
29568
|
"schema": {
|
|
@@ -28636,7 +29574,7 @@
|
|
|
28636
29574
|
"value": {
|
|
28637
29575
|
"error": {
|
|
28638
29576
|
"code": "invalid_params",
|
|
28639
|
-
"message": "`offerId` must be the special-offer id
|
|
29577
|
+
"message": "`offerId` must be the special-offer id the offer was sent with.",
|
|
28640
29578
|
"fix": "Correct the field named in `field` and resend.",
|
|
28641
29579
|
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
28642
29580
|
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
@@ -28650,7 +29588,7 @@
|
|
|
28650
29588
|
"error": {
|
|
28651
29589
|
"code": "channel_not_supported",
|
|
28652
29590
|
"message": "Reservation 233530 came from Booking.com. Booking requests can only be accepted or declined on Airbnb \u2014 other channels confirm instantly or have no request step.",
|
|
28653
|
-
"fix": "Pre-approvals
|
|
29591
|
+
"fix": "Pre-approvals and special offers work on Airbnb (connected directly, not through a PMS such as Hostaway or Guesty) and VRBO; accepting/declining booking requests on Airbnb. `GET /v1/conversations/{id}` \u2192 `capabilities` says what works on a conversation. Booking.com and direct bookings confirm without a request step.",
|
|
28654
29592
|
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
28655
29593
|
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
28656
29594
|
"channel": "booking"
|
|
@@ -28739,7 +29677,7 @@
|
|
|
28739
29677
|
"delete": {
|
|
28740
29678
|
"operationId": "withdraw_conversation_special_offer",
|
|
28741
29679
|
"summary": "Withdraw a special offer",
|
|
28742
|
-
"description": "Withdraw a special offer the guest has not booked yet, so it can no longer be booked. An offer the guest already booked cannot be withdrawn \u2014
|
|
29680
|
+
"description": "Withdraw a special offer the guest has not booked yet, so it can no longer be booked (VRBO: `offerId` = `current`, the same as `DELETE /v1/conversations/{id}/pre-approval`). An offer the guest already booked cannot be withdrawn \u2014 the channel refuses with `409 inquiry_no_longer_open`; cancel the booking instead.",
|
|
28743
29681
|
"tags": [
|
|
28744
29682
|
"Conversations"
|
|
28745
29683
|
],
|
|
@@ -28760,7 +29698,7 @@
|
|
|
28760
29698
|
"schema": {
|
|
28761
29699
|
"type": "string"
|
|
28762
29700
|
},
|
|
28763
|
-
"description": "The special offer\u2019s `id`, as returned by `POST /v1/conversations/{id}/special-offers`.",
|
|
29701
|
+
"description": "The special offer\u2019s `id`, as returned by `POST /v1/conversations/{id}/special-offers`. On VRBO, where a conversation has one live offer, `current`.",
|
|
28764
29702
|
"example": "1459920384"
|
|
28765
29703
|
}
|
|
28766
29704
|
],
|
|
@@ -28774,6 +29712,7 @@
|
|
|
28774
29712
|
"required": [
|
|
28775
29713
|
"id",
|
|
28776
29714
|
"conversationId",
|
|
29715
|
+
"channel",
|
|
28777
29716
|
"status"
|
|
28778
29717
|
],
|
|
28779
29718
|
"properties": {
|
|
@@ -28785,6 +29724,14 @@
|
|
|
28785
29724
|
"type": "string",
|
|
28786
29725
|
"example": "164743"
|
|
28787
29726
|
},
|
|
29727
|
+
"channel": {
|
|
29728
|
+
"type": "string",
|
|
29729
|
+
"enum": [
|
|
29730
|
+
"airbnb",
|
|
29731
|
+
"vrbo"
|
|
29732
|
+
],
|
|
29733
|
+
"example": "airbnb"
|
|
29734
|
+
},
|
|
28788
29735
|
"status": {
|
|
28789
29736
|
"type": "string",
|
|
28790
29737
|
"enum": [
|
|
@@ -28876,7 +29823,7 @@
|
|
|
28876
29823
|
}
|
|
28877
29824
|
},
|
|
28878
29825
|
"409": {
|
|
28879
|
-
"description": "
|
|
29826
|
+
"description": "The channel says the offer can no longer be withdrawn (the guest booked it, or it already expired).",
|
|
28880
29827
|
"content": {
|
|
28881
29828
|
"application/json": {
|
|
28882
29829
|
"schema": {
|
|
@@ -28900,7 +29847,7 @@
|
|
|
28900
29847
|
}
|
|
28901
29848
|
},
|
|
28902
29849
|
"422": {
|
|
28903
|
-
"description": "`invalid_params` \u2014 `id` or `offerId` is malformed; `channel_not_supported` \u2014
|
|
29850
|
+
"description": "`invalid_params` \u2014 `id` or `offerId` is malformed; `channel_not_supported` \u2014 the conversation has no offers (only Airbnb connected directly, and VRBO, do).",
|
|
28904
29851
|
"content": {
|
|
28905
29852
|
"application/json": {
|
|
28906
29853
|
"schema": {
|
|
@@ -28912,7 +29859,7 @@
|
|
|
28912
29859
|
"value": {
|
|
28913
29860
|
"error": {
|
|
28914
29861
|
"code": "invalid_params",
|
|
28915
|
-
"message": "`offerId` must be the special-offer id
|
|
29862
|
+
"message": "`offerId` must be the special-offer id the offer was sent with.",
|
|
28916
29863
|
"fix": "Correct the field named in `field` and resend.",
|
|
28917
29864
|
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
28918
29865
|
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
@@ -28926,7 +29873,7 @@
|
|
|
28926
29873
|
"error": {
|
|
28927
29874
|
"code": "channel_not_supported",
|
|
28928
29875
|
"message": "Reservation 233530 came from Booking.com. Booking requests can only be accepted or declined on Airbnb \u2014 other channels confirm instantly or have no request step.",
|
|
28929
|
-
"fix": "Pre-approvals
|
|
29876
|
+
"fix": "Pre-approvals and special offers work on Airbnb (connected directly, not through a PMS such as Hostaway or Guesty) and VRBO; accepting/declining booking requests on Airbnb. `GET /v1/conversations/{id}` \u2192 `capabilities` says what works on a conversation. Booking.com and direct bookings confirm without a request step.",
|
|
28930
29877
|
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
28931
29878
|
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
28932
29879
|
"channel": "booking"
|
|
@@ -29496,7 +30443,7 @@
|
|
|
29496
30443
|
"error": {
|
|
29497
30444
|
"code": "channel_not_supported",
|
|
29498
30445
|
"message": "Reservation 233530 came from Booking.com. Booking requests can only be accepted or declined on Airbnb \u2014 other channels confirm instantly or have no request step.",
|
|
29499
|
-
"fix": "Pre-approvals
|
|
30446
|
+
"fix": "Pre-approvals and special offers work on Airbnb (connected directly, not through a PMS such as Hostaway or Guesty) and VRBO; accepting/declining booking requests on Airbnb. `GET /v1/conversations/{id}` \u2192 `capabilities` says what works on a conversation. Booking.com and direct bookings confirm without a request step.",
|
|
29500
30447
|
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
29501
30448
|
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
29502
30449
|
"channel": "booking"
|
|
@@ -29932,7 +30879,7 @@
|
|
|
29932
30879
|
"error": {
|
|
29933
30880
|
"code": "channel_not_supported",
|
|
29934
30881
|
"message": "Reservation 233530 came from Booking.com. Booking requests can only be accepted or declined on Airbnb \u2014 other channels confirm instantly or have no request step.",
|
|
29935
|
-
"fix": "Pre-approvals
|
|
30882
|
+
"fix": "Pre-approvals and special offers work on Airbnb (connected directly, not through a PMS such as Hostaway or Guesty) and VRBO; accepting/declining booking requests on Airbnb. `GET /v1/conversations/{id}` \u2192 `capabilities` says what works on a conversation. Booking.com and direct bookings confirm without a request step.",
|
|
29936
30883
|
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
29937
30884
|
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
29938
30885
|
"channel": "booking"
|
|
@@ -30035,7 +30982,7 @@
|
|
|
30035
30982
|
"post": {
|
|
30036
30983
|
"operationId": "takeListingOffline",
|
|
30037
30984
|
"summary": "Take a listing off the market",
|
|
30038
|
-
"description": "Stop this listing being sold, on every channel it is connected to, in one call.\n\nWhat 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 \u2014 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
|
|
30985
|
+
"description": "Stop this listing being sold, on every channel it is connected to, in one call.\n\nWhat 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 \u2014 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. On **VRBO** each mapped unit is hidden (VRBO's own \"Hide listing\") and read back \u2014 a hidden unit is out of VRBO search and cannot be booked; its item carries the VRBO listing number as `platformId`.\n\n**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:\n\n| | Take offline (this endpoint) | Deactivate in Repull (`PATCH /v1/listings/{id}` `{\"active\": false}`) |\n|---|---|---|\n| The guest-facing listing | **Stops taking bookings** | Stays live and keeps taking bookings |\n| Billing and plan limits | Unchanged | No longer billed, no longer counts toward the cap |\n| API access to the listing | Unchanged \u2014 you can still read and write it | `403 listing_inactive` until reactivated |\n| Reverse it with | `POST /v1/listings/{id}/online` | `PATCH /v1/listings/{id}` `{\"active\": true}` |\n| Data kept | Yes | Yes, and it keeps syncing |\n\nNeither one deletes anything, on either side.\n\n**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 \u2014 re-send the same request to retry the items that did not land.\n\n**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.\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.",
|
|
30039
30986
|
"tags": [
|
|
30040
30987
|
"Listings"
|
|
30041
30988
|
],
|
|
@@ -30112,7 +31059,7 @@
|
|
|
30112
31059
|
"post": {
|
|
30113
31060
|
"operationId": "takeListingOnline",
|
|
30114
31061
|
"summary": "Put a listing back on the market",
|
|
30115
|
-
"description": "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.\n\n**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 \u2014 a reservation, an owner stay \u2014 stay blocked, and only the closure `offline` wrote lifts. The two directions are not mirror images, and that is deliberate.\n\n**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` \u2014 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.\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.",
|
|
31062
|
+
"description": "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.\n\n**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 \u2014 a reservation, an owner stay \u2014 stay blocked, and only the closure `offline` wrote lifts. On **VRBO** each hidden unit is reactivated (VRBO's own \"Reactivate\") and read back; VRBO can refuse a reactivation (e.g. while it is verifying the property), which comes back as that item's `message`. The two directions are not mirror images, and that is deliberate.\n\n**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` \u2014 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.\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.",
|
|
30116
31063
|
"tags": [
|
|
30117
31064
|
"Listings"
|
|
30118
31065
|
],
|
|
@@ -30937,6 +31884,15 @@
|
|
|
30937
31884
|
"type": "string",
|
|
30938
31885
|
"description": "Connect session id from `POST /v1/connect/cloudbeds`. Omit when calling with your API key."
|
|
30939
31886
|
},
|
|
31887
|
+
"writePolicy": {
|
|
31888
|
+
"type": "object",
|
|
31889
|
+
"description": "Optional: what the app may change in the PMS, set before the first sync. Same shape as `PATCH /v1/connect/{provider}/write-policy`; switches you leave out keep the provider default (calendar off for hotel PMSs, bookings on).",
|
|
31890
|
+
"example": {
|
|
31891
|
+
"calendar": {
|
|
31892
|
+
"rates": true
|
|
31893
|
+
}
|
|
31894
|
+
}
|
|
31895
|
+
},
|
|
30940
31896
|
"credentials": {
|
|
30941
31897
|
"type": "object",
|
|
30942
31898
|
"properties": {
|
|
@@ -30980,6 +31936,9 @@
|
|
|
30980
31936
|
"connected": {
|
|
30981
31937
|
"type": "boolean"
|
|
30982
31938
|
},
|
|
31939
|
+
"writePolicy": {
|
|
31940
|
+
"$ref": "#/components/schemas/PmsWritePolicy"
|
|
31941
|
+
},
|
|
30983
31942
|
"pmsConnectionId": {
|
|
30984
31943
|
"type": "string",
|
|
30985
31944
|
"description": "Id of the stored connection."
|
|
@@ -31064,6 +32023,15 @@
|
|
|
31064
32023
|
"type": "string",
|
|
31065
32024
|
"description": "Connect session id from `POST /v1/connect/mews`. Omit when calling with your API key."
|
|
31066
32025
|
},
|
|
32026
|
+
"writePolicy": {
|
|
32027
|
+
"type": "object",
|
|
32028
|
+
"description": "Optional: what the app may change in the PMS, set before the first sync. Same shape as `PATCH /v1/connect/{provider}/write-policy`; switches you leave out keep the provider default (calendar off for hotel PMSs, bookings on).",
|
|
32029
|
+
"example": {
|
|
32030
|
+
"calendar": {
|
|
32031
|
+
"rates": true
|
|
32032
|
+
}
|
|
32033
|
+
}
|
|
32034
|
+
},
|
|
31067
32035
|
"credentials": {
|
|
31068
32036
|
"type": "object",
|
|
31069
32037
|
"properties": {
|
|
@@ -31109,6 +32077,9 @@
|
|
|
31109
32077
|
"connected": {
|
|
31110
32078
|
"type": "boolean"
|
|
31111
32079
|
},
|
|
32080
|
+
"writePolicy": {
|
|
32081
|
+
"$ref": "#/components/schemas/PmsWritePolicy"
|
|
32082
|
+
},
|
|
31112
32083
|
"pmsConnectionId": {
|
|
31113
32084
|
"type": "string",
|
|
31114
32085
|
"description": "Id of the stored connection."
|
|
@@ -31480,6 +32451,1771 @@
|
|
|
31480
32451
|
}
|
|
31481
32452
|
}
|
|
31482
32453
|
}
|
|
32454
|
+
},
|
|
32455
|
+
"/v1/conversations/{id}/special-offers/preview": {
|
|
32456
|
+
"post": {
|
|
32457
|
+
"operationId": "preview_conversation_special_offer",
|
|
32458
|
+
"summary": "Preview a special offer",
|
|
32459
|
+
"description": "See what a special offer would be \u2014 as the channel itself recalculates it, with its taxes, service fee and guest total \u2014 **without sending anything** to the guest. Same body as `POST /v1/conversations/{id}/special-offers`; the price may be omitted to see only a date or party change, and `{}` shows the current offer recalculated.\n\n**VRBO** (its \u201cEdit quote\u201d recalculation). A channel without a preview \u2014 Airbnb takes your total as it is \u2014 returns `422 preview_not_supported`; `GET /v1/conversations/{id}` \u2192 `capabilities.canPreviewOffer` says which.\n\nRead-only: safe to call as often as you need while a user edits an offer.",
|
|
32460
|
+
"tags": [
|
|
32461
|
+
"Conversations"
|
|
32462
|
+
],
|
|
32463
|
+
"parameters": [
|
|
32464
|
+
{
|
|
32465
|
+
"name": "id",
|
|
32466
|
+
"in": "path",
|
|
32467
|
+
"required": true,
|
|
32468
|
+
"schema": {
|
|
32469
|
+
"type": "integer"
|
|
32470
|
+
},
|
|
32471
|
+
"description": "Repull conversation id (from `GET /v1/conversations` or `conversationId` on `GET /v1/inquiries`) \u2014 not the Airbnb thread id."
|
|
32472
|
+
}
|
|
32473
|
+
],
|
|
32474
|
+
"requestBody": {
|
|
32475
|
+
"required": false,
|
|
32476
|
+
"content": {
|
|
32477
|
+
"application/json": {
|
|
32478
|
+
"schema": {
|
|
32479
|
+
"type": "object",
|
|
32480
|
+
"additionalProperties": false,
|
|
32481
|
+
"description": "Any of the offer fields; only what is sent is changed.",
|
|
32482
|
+
"properties": {
|
|
32483
|
+
"checkIn": {
|
|
32484
|
+
"type": "string",
|
|
32485
|
+
"format": "date",
|
|
32486
|
+
"example": "2026-11-26"
|
|
32487
|
+
},
|
|
32488
|
+
"checkOut": {
|
|
32489
|
+
"type": "string",
|
|
32490
|
+
"format": "date",
|
|
32491
|
+
"example": "2026-12-06"
|
|
32492
|
+
},
|
|
32493
|
+
"guests": {
|
|
32494
|
+
"type": "object",
|
|
32495
|
+
"additionalProperties": false,
|
|
32496
|
+
"properties": {
|
|
32497
|
+
"adults": {
|
|
32498
|
+
"type": "integer",
|
|
32499
|
+
"minimum": 1,
|
|
32500
|
+
"example": 2
|
|
32501
|
+
},
|
|
32502
|
+
"children": {
|
|
32503
|
+
"type": "integer",
|
|
32504
|
+
"minimum": 0
|
|
32505
|
+
},
|
|
32506
|
+
"infants": {
|
|
32507
|
+
"type": "integer",
|
|
32508
|
+
"minimum": 0
|
|
32509
|
+
},
|
|
32510
|
+
"pets": {
|
|
32511
|
+
"type": "integer",
|
|
32512
|
+
"minimum": 0
|
|
32513
|
+
}
|
|
32514
|
+
}
|
|
32515
|
+
},
|
|
32516
|
+
"rentalAmount": {
|
|
32517
|
+
"type": "number",
|
|
32518
|
+
"exclusiveMinimum": true,
|
|
32519
|
+
"minimum": 0,
|
|
32520
|
+
"description": "Rent for the stay, excluding fees and taxes."
|
|
32521
|
+
},
|
|
32522
|
+
"fees": {
|
|
32523
|
+
"type": "array",
|
|
32524
|
+
"items": {
|
|
32525
|
+
"type": "object",
|
|
32526
|
+
"required": [
|
|
32527
|
+
"type",
|
|
32528
|
+
"value"
|
|
32529
|
+
],
|
|
32530
|
+
"properties": {
|
|
32531
|
+
"type": {
|
|
32532
|
+
"type": "string",
|
|
32533
|
+
"example": "CLEANING"
|
|
32534
|
+
},
|
|
32535
|
+
"value": {
|
|
32536
|
+
"type": "number",
|
|
32537
|
+
"minimum": 0,
|
|
32538
|
+
"example": 400
|
|
32539
|
+
}
|
|
32540
|
+
}
|
|
32541
|
+
}
|
|
32542
|
+
},
|
|
32543
|
+
"damageDeposit": {
|
|
32544
|
+
"type": "number",
|
|
32545
|
+
"nullable": true,
|
|
32546
|
+
"minimum": 0
|
|
32547
|
+
}
|
|
32548
|
+
}
|
|
32549
|
+
},
|
|
32550
|
+
"example": {
|
|
32551
|
+
"fees": [
|
|
32552
|
+
{
|
|
32553
|
+
"type": "CLEANING",
|
|
32554
|
+
"value": 400
|
|
32555
|
+
}
|
|
32556
|
+
]
|
|
32557
|
+
}
|
|
32558
|
+
}
|
|
32559
|
+
}
|
|
32560
|
+
},
|
|
32561
|
+
"responses": {
|
|
32562
|
+
"200": {
|
|
32563
|
+
"description": "The offer as the channel would make it. `status` is `preview`; nothing was sent.",
|
|
32564
|
+
"content": {
|
|
32565
|
+
"application/json": {
|
|
32566
|
+
"schema": {
|
|
32567
|
+
"type": "object",
|
|
32568
|
+
"required": [
|
|
32569
|
+
"id",
|
|
32570
|
+
"conversationId",
|
|
32571
|
+
"status",
|
|
32572
|
+
"checkIn",
|
|
32573
|
+
"checkOut",
|
|
32574
|
+
"nights",
|
|
32575
|
+
"totalPrice"
|
|
32576
|
+
],
|
|
32577
|
+
"properties": {
|
|
32578
|
+
"id": {
|
|
32579
|
+
"type": "string",
|
|
32580
|
+
"nullable": true,
|
|
32581
|
+
"description": "The offer id \u2014 use it to read or withdraw the offer. Airbnb\u2019s special-offer id; on VRBO, where a conversation has one live offer, `current`.",
|
|
32582
|
+
"example": "1459920384"
|
|
32583
|
+
},
|
|
32584
|
+
"conversationId": {
|
|
32585
|
+
"type": "string",
|
|
32586
|
+
"description": "Repull conversation id the offer was sent on.",
|
|
32587
|
+
"example": "164743"
|
|
32588
|
+
},
|
|
32589
|
+
"channel": {
|
|
32590
|
+
"type": "string",
|
|
32591
|
+
"enum": [
|
|
32592
|
+
"airbnb",
|
|
32593
|
+
"vrbo"
|
|
32594
|
+
],
|
|
32595
|
+
"description": "The channel the offer is on.",
|
|
32596
|
+
"example": "airbnb"
|
|
32597
|
+
},
|
|
32598
|
+
"status": {
|
|
32599
|
+
"type": "string",
|
|
32600
|
+
"nullable": true,
|
|
32601
|
+
"description": "Airbnb: its status for the offer \u2014 `active` (the guest can book it), `accepted`, `declined`, `expired` or `voided` (withdrawn). VRBO: `sent` (just sent), `current` (the live offer) or `preview` (recalculated, not sent).",
|
|
32602
|
+
"example": "active"
|
|
32603
|
+
},
|
|
32604
|
+
"listingId": {
|
|
32605
|
+
"type": "string",
|
|
32606
|
+
"nullable": true,
|
|
32607
|
+
"description": "Repull listing id, when known.",
|
|
32608
|
+
"example": "23892"
|
|
32609
|
+
},
|
|
32610
|
+
"airbnbListingId": {
|
|
32611
|
+
"type": "string",
|
|
32612
|
+
"nullable": true,
|
|
32613
|
+
"description": "Airbnb listing id the offer is for (a string \u2014 it exceeds 2^53).",
|
|
32614
|
+
"example": "955656266214757921"
|
|
32615
|
+
},
|
|
32616
|
+
"checkIn": {
|
|
32617
|
+
"type": "string",
|
|
32618
|
+
"format": "date",
|
|
32619
|
+
"nullable": true,
|
|
32620
|
+
"example": "2026-10-01"
|
|
32621
|
+
},
|
|
32622
|
+
"checkOut": {
|
|
32623
|
+
"type": "string",
|
|
32624
|
+
"format": "date",
|
|
32625
|
+
"nullable": true,
|
|
32626
|
+
"example": "2026-10-05"
|
|
32627
|
+
},
|
|
32628
|
+
"nights": {
|
|
32629
|
+
"type": "integer",
|
|
32630
|
+
"nullable": true,
|
|
32631
|
+
"example": 4
|
|
32632
|
+
},
|
|
32633
|
+
"guests": {
|
|
32634
|
+
"type": "object",
|
|
32635
|
+
"nullable": true,
|
|
32636
|
+
"description": "Guests on the offer. Airbnb counts adults + children as guests; infants and pets are extra.",
|
|
32637
|
+
"properties": {
|
|
32638
|
+
"total": {
|
|
32639
|
+
"type": "integer",
|
|
32640
|
+
"nullable": true,
|
|
32641
|
+
"example": 3
|
|
32642
|
+
},
|
|
32643
|
+
"adults": {
|
|
32644
|
+
"type": "integer",
|
|
32645
|
+
"nullable": true,
|
|
32646
|
+
"example": 2
|
|
32647
|
+
},
|
|
32648
|
+
"children": {
|
|
32649
|
+
"type": "integer",
|
|
32650
|
+
"nullable": true,
|
|
32651
|
+
"example": 1
|
|
32652
|
+
},
|
|
32653
|
+
"infants": {
|
|
32654
|
+
"type": "integer",
|
|
32655
|
+
"nullable": true,
|
|
32656
|
+
"example": 0
|
|
32657
|
+
},
|
|
32658
|
+
"pets": {
|
|
32659
|
+
"type": "integer",
|
|
32660
|
+
"nullable": true,
|
|
32661
|
+
"example": 0
|
|
32662
|
+
}
|
|
32663
|
+
}
|
|
32664
|
+
},
|
|
32665
|
+
"totalPrice": {
|
|
32666
|
+
"type": "number",
|
|
32667
|
+
"nullable": true,
|
|
32668
|
+
"description": "What the guest pays for the stay. Airbnb: the total you set. VRBO: VRBO\u2019s own total, including its taxes and service fee.",
|
|
32669
|
+
"example": 880
|
|
32670
|
+
},
|
|
32671
|
+
"currency": {
|
|
32672
|
+
"type": "string",
|
|
32673
|
+
"nullable": true,
|
|
32674
|
+
"description": "Currency of the amounts, when the channel states it (VRBO).",
|
|
32675
|
+
"example": "CAD"
|
|
32676
|
+
},
|
|
32677
|
+
"rentalAmount": {
|
|
32678
|
+
"type": "number",
|
|
32679
|
+
"nullable": true,
|
|
32680
|
+
"description": "VRBO: rent for the stay, excluding fees and taxes. Null on Airbnb (priced by one total).",
|
|
32681
|
+
"example": 4041.9
|
|
32682
|
+
},
|
|
32683
|
+
"discount": {
|
|
32684
|
+
"type": "number",
|
|
32685
|
+
"nullable": true,
|
|
32686
|
+
"description": "VRBO: its automatic stay discount on the rent, when the offer carries one."
|
|
32687
|
+
},
|
|
32688
|
+
"fees": {
|
|
32689
|
+
"type": "array",
|
|
32690
|
+
"description": "VRBO: the offer\u2019s fees by type. Empty on Airbnb.",
|
|
32691
|
+
"items": {
|
|
32692
|
+
"type": "object",
|
|
32693
|
+
"properties": {
|
|
32694
|
+
"type": {
|
|
32695
|
+
"type": "string",
|
|
32696
|
+
"example": "CLEANING"
|
|
32697
|
+
},
|
|
32698
|
+
"value": {
|
|
32699
|
+
"type": "number",
|
|
32700
|
+
"example": 400
|
|
32701
|
+
},
|
|
32702
|
+
"label": {
|
|
32703
|
+
"type": "string",
|
|
32704
|
+
"nullable": true,
|
|
32705
|
+
"example": "Cleaning Fee"
|
|
32706
|
+
}
|
|
32707
|
+
}
|
|
32708
|
+
}
|
|
32709
|
+
},
|
|
32710
|
+
"damageDeposit": {
|
|
32711
|
+
"type": "number",
|
|
32712
|
+
"nullable": true,
|
|
32713
|
+
"description": "VRBO: refundable damage deposit; null for none.",
|
|
32714
|
+
"example": 500
|
|
32715
|
+
},
|
|
32716
|
+
"lines": {
|
|
32717
|
+
"type": "array",
|
|
32718
|
+
"description": "VRBO: its offer summary line by line, in VRBO\u2019s words (nights, fees, taxes, total traveler payment, payout).",
|
|
32719
|
+
"items": {
|
|
32720
|
+
"type": "object",
|
|
32721
|
+
"properties": {
|
|
32722
|
+
"label": {
|
|
32723
|
+
"type": "string"
|
|
32724
|
+
},
|
|
32725
|
+
"value": {
|
|
32726
|
+
"type": "string",
|
|
32727
|
+
"nullable": true
|
|
32728
|
+
}
|
|
32729
|
+
}
|
|
32730
|
+
}
|
|
32731
|
+
},
|
|
32732
|
+
"message": {
|
|
32733
|
+
"type": "string",
|
|
32734
|
+
"nullable": true,
|
|
32735
|
+
"description": "The message sent to the guest with the offer (VRBO)."
|
|
32736
|
+
},
|
|
32737
|
+
"createdAt": {
|
|
32738
|
+
"type": "string",
|
|
32739
|
+
"format": "date-time",
|
|
32740
|
+
"nullable": true
|
|
32741
|
+
},
|
|
32742
|
+
"expiresAt": {
|
|
32743
|
+
"type": "string",
|
|
32744
|
+
"format": "date-time",
|
|
32745
|
+
"nullable": true,
|
|
32746
|
+
"description": "When the guest can no longer book the offer (Airbnb gives them 24 hours)."
|
|
32747
|
+
}
|
|
32748
|
+
}
|
|
32749
|
+
},
|
|
32750
|
+
"example": {
|
|
32751
|
+
"id": "current",
|
|
32752
|
+
"conversationId": "166599",
|
|
32753
|
+
"channel": "vrbo",
|
|
32754
|
+
"status": "preview",
|
|
32755
|
+
"listingId": null,
|
|
32756
|
+
"airbnbListingId": null,
|
|
32757
|
+
"checkIn": "2026-11-26",
|
|
32758
|
+
"checkOut": "2026-12-06",
|
|
32759
|
+
"nights": 10,
|
|
32760
|
+
"guests": {
|
|
32761
|
+
"total": 2,
|
|
32762
|
+
"adults": 2,
|
|
32763
|
+
"children": 0,
|
|
32764
|
+
"infants": null,
|
|
32765
|
+
"pets": 0
|
|
32766
|
+
},
|
|
32767
|
+
"totalPrice": 5519.17,
|
|
32768
|
+
"currency": "CAD",
|
|
32769
|
+
"rentalAmount": 4041.9,
|
|
32770
|
+
"discount": null,
|
|
32771
|
+
"fees": [
|
|
32772
|
+
{
|
|
32773
|
+
"type": "CLEANING",
|
|
32774
|
+
"value": 400,
|
|
32775
|
+
"label": "Cleaning Fee"
|
|
32776
|
+
}
|
|
32777
|
+
],
|
|
32778
|
+
"damageDeposit": 500,
|
|
32779
|
+
"lines": [
|
|
32780
|
+
{
|
|
32781
|
+
"label": "10 nights",
|
|
32782
|
+
"value": "C$ 4,041.90"
|
|
32783
|
+
},
|
|
32784
|
+
{
|
|
32785
|
+
"label": "Cleaning Fee",
|
|
32786
|
+
"value": "C$ 400.00"
|
|
32787
|
+
},
|
|
32788
|
+
{
|
|
32789
|
+
"label": "Total traveler payment",
|
|
32790
|
+
"value": "C$ 5,519.17"
|
|
32791
|
+
}
|
|
32792
|
+
],
|
|
32793
|
+
"message": null,
|
|
32794
|
+
"createdAt": null,
|
|
32795
|
+
"expiresAt": null
|
|
32796
|
+
}
|
|
32797
|
+
}
|
|
32798
|
+
}
|
|
32799
|
+
},
|
|
32800
|
+
"401": {
|
|
32801
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
32802
|
+
},
|
|
32803
|
+
"404": {
|
|
32804
|
+
"description": "The conversation does not exist in this workspace.",
|
|
32805
|
+
"content": {
|
|
32806
|
+
"application/json": {
|
|
32807
|
+
"schema": {
|
|
32808
|
+
"$ref": "#/components/schemas/Error"
|
|
32809
|
+
},
|
|
32810
|
+
"examples": {
|
|
32811
|
+
"notFound": {
|
|
32812
|
+
"summary": "No such conversation in this workspace",
|
|
32813
|
+
"value": {
|
|
32814
|
+
"error": {
|
|
32815
|
+
"code": "not_found",
|
|
32816
|
+
"message": "Conversation 164743 not found in this workspace.",
|
|
32817
|
+
"fix": "List reachable conversations with `GET /v1/conversations`, or open inquiries with `GET /v1/inquiries`.",
|
|
32818
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
32819
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678"
|
|
32820
|
+
}
|
|
32821
|
+
}
|
|
32822
|
+
}
|
|
32823
|
+
}
|
|
32824
|
+
}
|
|
32825
|
+
}
|
|
32826
|
+
},
|
|
32827
|
+
"409": {
|
|
32828
|
+
"description": "The inquiry is closed on the channel (`inquiry_no_longer_open`).",
|
|
32829
|
+
"content": {
|
|
32830
|
+
"application/json": {
|
|
32831
|
+
"schema": {
|
|
32832
|
+
"$ref": "#/components/schemas/Error"
|
|
32833
|
+
},
|
|
32834
|
+
"examples": {
|
|
32835
|
+
"noLongerOpen": {
|
|
32836
|
+
"summary": "Airbnb says the inquiry already moved on",
|
|
32837
|
+
"value": {
|
|
32838
|
+
"error": {
|
|
32839
|
+
"code": "inquiry_no_longer_open",
|
|
32840
|
+
"message": "This thread is not eligible for a special offer.",
|
|
32841
|
+
"fix": "The inquiry was already booked, declined, pre-approved or closed. Re-read the conversation \u2014 do not retry.",
|
|
32842
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
32843
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678"
|
|
32844
|
+
}
|
|
32845
|
+
}
|
|
32846
|
+
}
|
|
32847
|
+
}
|
|
32848
|
+
}
|
|
32849
|
+
}
|
|
32850
|
+
},
|
|
32851
|
+
"422": {
|
|
32852
|
+
"description": "`preview_not_supported` \u2014 the channel has no preview (Airbnb); `channel_not_supported` \u2014 the conversation has no offers; `invalid_params` \u2014 the body is wrong and `field` names it; `channel_rejected` \u2014 the channel refused the change (its reason is in `message`).",
|
|
32853
|
+
"content": {
|
|
32854
|
+
"application/json": {
|
|
32855
|
+
"schema": {
|
|
32856
|
+
"$ref": "#/components/schemas/Error"
|
|
32857
|
+
},
|
|
32858
|
+
"examples": {
|
|
32859
|
+
"previewNotSupported": {
|
|
32860
|
+
"summary": "A preview on a channel without one",
|
|
32861
|
+
"value": {
|
|
32862
|
+
"error": {
|
|
32863
|
+
"code": "preview_not_supported",
|
|
32864
|
+
"message": "Only VRBO recalculates an offer before it is sent; on this channel send the offer with its total directly.",
|
|
32865
|
+
"fix": "Send the offer directly with `POST /v1/conversations/{id}/special-offers`; `capabilities.canPreviewOffer` says where a preview exists.",
|
|
32866
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
32867
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678"
|
|
32868
|
+
}
|
|
32869
|
+
}
|
|
32870
|
+
},
|
|
32871
|
+
"channelNotSupported": {
|
|
32872
|
+
"summary": "Not a direct Airbnb conversation or booking",
|
|
32873
|
+
"value": {
|
|
32874
|
+
"error": {
|
|
32875
|
+
"code": "channel_not_supported",
|
|
32876
|
+
"message": "Reservation 233530 came from Booking.com. Booking requests can only be accepted or declined on Airbnb \u2014 other channels confirm instantly or have no request step.",
|
|
32877
|
+
"fix": "Pre-approvals and special offers work on Airbnb (connected directly, not through a PMS such as Hostaway or Guesty) and VRBO; accepting/declining booking requests on Airbnb. `GET /v1/conversations/{id}` \u2192 `capabilities` says what works on a conversation. Booking.com and direct bookings confirm without a request step.",
|
|
32878
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
32879
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
32880
|
+
"channel": "booking"
|
|
32881
|
+
}
|
|
32882
|
+
}
|
|
32883
|
+
},
|
|
32884
|
+
"fees": {
|
|
32885
|
+
"summary": "Invalid `fees`",
|
|
32886
|
+
"value": {
|
|
32887
|
+
"error": {
|
|
32888
|
+
"code": "invalid_params",
|
|
32889
|
+
"message": "Each fee needs a `type` (the channel's fee type, e.g. `CLEANING`, `PET`) and a `value` of 0 or more.",
|
|
32890
|
+
"fix": "Correct the field named in `field` and resend.",
|
|
32891
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
32892
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
32893
|
+
"field": "fees"
|
|
32894
|
+
}
|
|
32895
|
+
}
|
|
32896
|
+
},
|
|
32897
|
+
"channelRejected": {
|
|
32898
|
+
"summary": "The channel refused the action",
|
|
32899
|
+
"value": {
|
|
32900
|
+
"error": {
|
|
32901
|
+
"code": "channel_rejected",
|
|
32902
|
+
"message": "The dates are no longer available.",
|
|
32903
|
+
"fix": "VRBO refused the action; its reason is in `message`. Do not retry unchanged.",
|
|
32904
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
32905
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
32906
|
+
"channel": "vrbo"
|
|
32907
|
+
}
|
|
32908
|
+
}
|
|
32909
|
+
}
|
|
32910
|
+
}
|
|
32911
|
+
}
|
|
32912
|
+
}
|
|
32913
|
+
},
|
|
32914
|
+
"429": {
|
|
32915
|
+
"description": "`airbnb_rate_limited` \u2014 back off and retry with the same `Idempotency-Key`.",
|
|
32916
|
+
"content": {
|
|
32917
|
+
"application/json": {
|
|
32918
|
+
"schema": {
|
|
32919
|
+
"$ref": "#/components/schemas/Error"
|
|
32920
|
+
},
|
|
32921
|
+
"examples": {
|
|
32922
|
+
"rateLimited": {
|
|
32923
|
+
"summary": "Airbnb rate-limited the request",
|
|
32924
|
+
"value": {
|
|
32925
|
+
"error": {
|
|
32926
|
+
"code": "airbnb_rate_limited",
|
|
32927
|
+
"message": "Too many requests.",
|
|
32928
|
+
"fix": "Back off and retry. Send the same `Idempotency-Key` so a retry cannot act twice.",
|
|
32929
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
32930
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678"
|
|
32931
|
+
}
|
|
32932
|
+
}
|
|
32933
|
+
}
|
|
32934
|
+
}
|
|
32935
|
+
}
|
|
32936
|
+
}
|
|
32937
|
+
},
|
|
32938
|
+
"500": {
|
|
32939
|
+
"description": "`service_misconfigured` \u2014 Repull could not reach the service that performs the action (its route was missing or refused our credentials). Nothing was sent to Airbnb. A fault on our side, not in the request: `retryable` is `false` and resending will not help until it is fixed. Any other 500 is `internal_error`.",
|
|
32940
|
+
"content": {
|
|
32941
|
+
"application/json": {
|
|
32942
|
+
"schema": {
|
|
32943
|
+
"$ref": "#/components/schemas/Error"
|
|
32944
|
+
},
|
|
32945
|
+
"examples": {
|
|
32946
|
+
"serviceMisconfigured": {
|
|
32947
|
+
"summary": "Repull could not reach the action (our fault, not retryable)",
|
|
32948
|
+
"value": {
|
|
32949
|
+
"error": {
|
|
32950
|
+
"code": "service_misconfigured",
|
|
32951
|
+
"message": "Pre-approval failed: Repull could not reach this action \u2014 the service that performs it answered HTTP 404 for its own endpoint. Nothing was sent to the channel.",
|
|
32952
|
+
"fix": "This is a fault in Repull, not in your request, and retrying will not help until it is fixed \u2014 do not change or resend the request. If it persists, contact support with the `request_id`.",
|
|
32953
|
+
"docs_url": "https://repull.dev/docs/errors/service_misconfigured",
|
|
32954
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678",
|
|
32955
|
+
"retryable": false
|
|
32956
|
+
}
|
|
32957
|
+
}
|
|
32958
|
+
}
|
|
32959
|
+
}
|
|
32960
|
+
}
|
|
32961
|
+
}
|
|
32962
|
+
},
|
|
32963
|
+
"502": {
|
|
32964
|
+
"description": "`airbnb_error` \u2014 Airbnb outage or timeout. Nothing about the request needs to change; retry with backoff.",
|
|
32965
|
+
"content": {
|
|
32966
|
+
"application/json": {
|
|
32967
|
+
"schema": {
|
|
32968
|
+
"$ref": "#/components/schemas/Error"
|
|
32969
|
+
},
|
|
32970
|
+
"examples": {
|
|
32971
|
+
"airbnbDown": {
|
|
32972
|
+
"summary": "Airbnb did not complete the request",
|
|
32973
|
+
"value": {
|
|
32974
|
+
"error": {
|
|
32975
|
+
"code": "airbnb_error",
|
|
32976
|
+
"message": "Airbnb error (503): Service Unavailable",
|
|
32977
|
+
"fix": "Airbnb did not complete the request (outage or timeout). Retry with backoff and the same `Idempotency-Key`.",
|
|
32978
|
+
"docs_url": "https://repull.dev/docs/channels/airbnb/inquiries-and-requests",
|
|
32979
|
+
"request_id": "req_01J5X7Y8Z9ABCDEF12345678"
|
|
32980
|
+
}
|
|
32981
|
+
}
|
|
32982
|
+
}
|
|
32983
|
+
}
|
|
32984
|
+
}
|
|
32985
|
+
}
|
|
32986
|
+
}
|
|
32987
|
+
}
|
|
32988
|
+
}
|
|
32989
|
+
},
|
|
32990
|
+
"/v1/listings/{id}/calendar-sync": {
|
|
32991
|
+
"get": {
|
|
32992
|
+
"operationId": "get_listing_calendar_sync",
|
|
32993
|
+
"summary": "Calendar sync status per channel",
|
|
32994
|
+
"description": "Is this listing's calendar \u2014 prices, minimum stays, availability \u2014 actually on every channel it is connected to, and if not, which nights and why. One shape for every channel.\n\nEvery push records each night's outcome per channel; a night the channel does not show as sent is listed in `problems` with the channel's own reason (a price the channel still shows differently, a block it refused, a unit that is not live, a night held by a booking or an imported calendar). A later successful push clears it.\n\n**VRBO** pushes run through a paced queue \u2014 VRBO accepts about 90 calendar writes a minute per account, and only what differs on VRBO is sent \u2014 so the `vrbo` entry adds `queue`: whether a push is waiting or running now, and what the last one did (prices and minimum stays changed, blocks, calls, nights still differing).\n\nFuture nights only. `problems` lists up to 100 nights per channel; `nightsWithProblems` is always the full count.\n\nReturns `403 listing_inactive` for an inactive listing.",
|
|
32995
|
+
"tags": [
|
|
32996
|
+
"Listings"
|
|
32997
|
+
],
|
|
32998
|
+
"parameters": [
|
|
32999
|
+
{
|
|
33000
|
+
"name": "id",
|
|
33001
|
+
"in": "path",
|
|
33002
|
+
"required": true,
|
|
33003
|
+
"schema": {
|
|
33004
|
+
"type": "integer"
|
|
33005
|
+
},
|
|
33006
|
+
"description": "Repull listing id."
|
|
33007
|
+
}
|
|
33008
|
+
],
|
|
33009
|
+
"responses": {
|
|
33010
|
+
"200": {
|
|
33011
|
+
"description": "Calendar sync status per connected channel.",
|
|
33012
|
+
"content": {
|
|
33013
|
+
"application/json": {
|
|
33014
|
+
"schema": {
|
|
33015
|
+
"type": "object",
|
|
33016
|
+
"required": [
|
|
33017
|
+
"listingId",
|
|
33018
|
+
"channels"
|
|
33019
|
+
],
|
|
33020
|
+
"properties": {
|
|
33021
|
+
"listingId": {
|
|
33022
|
+
"type": "string",
|
|
33023
|
+
"example": "6199"
|
|
33024
|
+
},
|
|
33025
|
+
"channels": {
|
|
33026
|
+
"type": "array",
|
|
33027
|
+
"items": {
|
|
33028
|
+
"type": "object",
|
|
33029
|
+
"required": [
|
|
33030
|
+
"channel",
|
|
33031
|
+
"platformId",
|
|
33032
|
+
"syncEnabled",
|
|
33033
|
+
"status",
|
|
33034
|
+
"lastSyncAt",
|
|
33035
|
+
"nightsWithProblems",
|
|
33036
|
+
"problems"
|
|
33037
|
+
],
|
|
33038
|
+
"properties": {
|
|
33039
|
+
"channel": {
|
|
33040
|
+
"type": "string",
|
|
33041
|
+
"example": "vrbo"
|
|
33042
|
+
},
|
|
33043
|
+
"platformId": {
|
|
33044
|
+
"type": "string",
|
|
33045
|
+
"nullable": true,
|
|
33046
|
+
"description": "The listing's id on the channel.",
|
|
33047
|
+
"example": "5121372"
|
|
33048
|
+
},
|
|
33049
|
+
"syncEnabled": {
|
|
33050
|
+
"type": "boolean",
|
|
33051
|
+
"description": "Calendar pushes to this channel are on."
|
|
33052
|
+
},
|
|
33053
|
+
"status": {
|
|
33054
|
+
"type": "string",
|
|
33055
|
+
"enum": [
|
|
33056
|
+
"in_sync",
|
|
33057
|
+
"problems",
|
|
33058
|
+
"off"
|
|
33059
|
+
],
|
|
33060
|
+
"description": "`in_sync` \u2014 no future night has a problem; `problems` \u2014 see `problems`; `off` \u2014 calendar sync is off for this channel."
|
|
33061
|
+
},
|
|
33062
|
+
"lastSyncAt": {
|
|
33063
|
+
"type": "string",
|
|
33064
|
+
"format": "date-time",
|
|
33065
|
+
"nullable": true,
|
|
33066
|
+
"description": "When a push last wrote to this listing's calendar."
|
|
33067
|
+
},
|
|
33068
|
+
"nightsWithProblems": {
|
|
33069
|
+
"type": "integer",
|
|
33070
|
+
"example": 0
|
|
33071
|
+
},
|
|
33072
|
+
"problems": {
|
|
33073
|
+
"type": "array",
|
|
33074
|
+
"items": {
|
|
33075
|
+
"type": "object",
|
|
33076
|
+
"properties": {
|
|
33077
|
+
"date": {
|
|
33078
|
+
"type": "string",
|
|
33079
|
+
"format": "date",
|
|
33080
|
+
"example": "2026-12-18"
|
|
33081
|
+
},
|
|
33082
|
+
"error": {
|
|
33083
|
+
"type": "string",
|
|
33084
|
+
"description": "The channel's reason, in words \u2014 render it next to the night.",
|
|
33085
|
+
"example": "VRBO shows 305 instead of 293"
|
|
33086
|
+
}
|
|
33087
|
+
}
|
|
33088
|
+
}
|
|
33089
|
+
},
|
|
33090
|
+
"queue": {
|
|
33091
|
+
"type": "object",
|
|
33092
|
+
"description": "VRBO only \u2014 the paced push queue.",
|
|
33093
|
+
"properties": {
|
|
33094
|
+
"state": {
|
|
33095
|
+
"type": "string",
|
|
33096
|
+
"enum": [
|
|
33097
|
+
"idle",
|
|
33098
|
+
"queued",
|
|
33099
|
+
"running"
|
|
33100
|
+
]
|
|
33101
|
+
},
|
|
33102
|
+
"queuedNights": {
|
|
33103
|
+
"type": "integer",
|
|
33104
|
+
"description": "Nights waiting to be pushed."
|
|
33105
|
+
},
|
|
33106
|
+
"queuedAt": {
|
|
33107
|
+
"type": "string",
|
|
33108
|
+
"format": "date-time",
|
|
33109
|
+
"nullable": true
|
|
33110
|
+
},
|
|
33111
|
+
"lastPush": {
|
|
33112
|
+
"type": "object",
|
|
33113
|
+
"nullable": true,
|
|
33114
|
+
"properties": {
|
|
33115
|
+
"finishedAt": {
|
|
33116
|
+
"type": "string",
|
|
33117
|
+
"format": "date-time",
|
|
33118
|
+
"nullable": true
|
|
33119
|
+
},
|
|
33120
|
+
"result": {
|
|
33121
|
+
"type": "string",
|
|
33122
|
+
"enum": [
|
|
33123
|
+
"in_sync",
|
|
33124
|
+
"problems",
|
|
33125
|
+
"skipped"
|
|
33126
|
+
],
|
|
33127
|
+
"description": "`skipped` \u2014 not sent because the unit is not live on VRBO (`reason`)."
|
|
33128
|
+
},
|
|
33129
|
+
"reason": {
|
|
33130
|
+
"type": "string",
|
|
33131
|
+
"nullable": true
|
|
33132
|
+
},
|
|
33133
|
+
"nights": {
|
|
33134
|
+
"type": "integer",
|
|
33135
|
+
"description": "Nights the push covered."
|
|
33136
|
+
},
|
|
33137
|
+
"pricesChanged": {
|
|
33138
|
+
"type": "integer"
|
|
33139
|
+
},
|
|
33140
|
+
"minStaysChanged": {
|
|
33141
|
+
"type": "integer"
|
|
33142
|
+
},
|
|
33143
|
+
"blocksCreated": {
|
|
33144
|
+
"type": "integer"
|
|
33145
|
+
},
|
|
33146
|
+
"blocksRemoved": {
|
|
33147
|
+
"type": "integer"
|
|
33148
|
+
},
|
|
33149
|
+
"calls": {
|
|
33150
|
+
"type": "integer",
|
|
33151
|
+
"description": "VRBO calls made \u2014 only what differed was sent."
|
|
33152
|
+
},
|
|
33153
|
+
"nightsDiffering": {
|
|
33154
|
+
"type": "integer",
|
|
33155
|
+
"description": "Nights VRBO still showed differently after the push (they are retried)."
|
|
33156
|
+
}
|
|
33157
|
+
}
|
|
33158
|
+
}
|
|
33159
|
+
}
|
|
33160
|
+
}
|
|
33161
|
+
}
|
|
33162
|
+
}
|
|
33163
|
+
}
|
|
33164
|
+
}
|
|
33165
|
+
},
|
|
33166
|
+
"example": {
|
|
33167
|
+
"listingId": "6199",
|
|
33168
|
+
"channels": [
|
|
33169
|
+
{
|
|
33170
|
+
"channel": "airbnb",
|
|
33171
|
+
"platformId": "1608268807524171722",
|
|
33172
|
+
"syncEnabled": true,
|
|
33173
|
+
"status": "in_sync",
|
|
33174
|
+
"lastSyncAt": "2026-09-28T16:47:02.000Z",
|
|
33175
|
+
"nightsWithProblems": 0,
|
|
33176
|
+
"problems": []
|
|
33177
|
+
},
|
|
33178
|
+
{
|
|
33179
|
+
"channel": "vrbo",
|
|
33180
|
+
"platformId": "5121372",
|
|
33181
|
+
"syncEnabled": true,
|
|
33182
|
+
"status": "problems",
|
|
33183
|
+
"lastSyncAt": "2026-09-28T16:47:02.000Z",
|
|
33184
|
+
"nightsWithProblems": 1,
|
|
33185
|
+
"problems": [
|
|
33186
|
+
{
|
|
33187
|
+
"date": "2027-09-28",
|
|
33188
|
+
"error": "Closed on VRBO by an imported calendar (iCal)"
|
|
33189
|
+
}
|
|
33190
|
+
],
|
|
33191
|
+
"queue": {
|
|
33192
|
+
"state": "idle",
|
|
33193
|
+
"queuedNights": 0,
|
|
33194
|
+
"queuedAt": null,
|
|
33195
|
+
"lastPush": {
|
|
33196
|
+
"finishedAt": "2026-09-28T16:49:10.000Z",
|
|
33197
|
+
"result": "in_sync",
|
|
33198
|
+
"reason": null,
|
|
33199
|
+
"nights": 366,
|
|
33200
|
+
"pricesChanged": 12,
|
|
33201
|
+
"minStaysChanged": 0,
|
|
33202
|
+
"blocksCreated": 0,
|
|
33203
|
+
"blocksRemoved": 0,
|
|
33204
|
+
"calls": 4,
|
|
33205
|
+
"nightsDiffering": 0
|
|
33206
|
+
}
|
|
33207
|
+
}
|
|
33208
|
+
}
|
|
33209
|
+
]
|
|
33210
|
+
}
|
|
33211
|
+
}
|
|
33212
|
+
}
|
|
33213
|
+
},
|
|
33214
|
+
"401": {
|
|
33215
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
33216
|
+
},
|
|
33217
|
+
"403": {
|
|
33218
|
+
"$ref": "#/components/responses/ListingInactive"
|
|
33219
|
+
},
|
|
33220
|
+
"404": {
|
|
33221
|
+
"$ref": "#/components/responses/NotFound"
|
|
33222
|
+
},
|
|
33223
|
+
"422": {
|
|
33224
|
+
"$ref": "#/components/responses/UnprocessableEntity"
|
|
33225
|
+
}
|
|
33226
|
+
}
|
|
33227
|
+
}
|
|
33228
|
+
},
|
|
33229
|
+
"/v1/connect/booking-extranet-login/invite": {
|
|
33230
|
+
"post": {
|
|
33231
|
+
"operationId": "inviteBookingExtranetUser",
|
|
33232
|
+
"summary": "Connect Booking.com by inviting a user",
|
|
33233
|
+
"description": "Generates the user the host invites in their Extranet; progress is read from the status route.\n\nCalled by the hosted Connect page. No API key \u2014 the session ID is the capability token.",
|
|
33234
|
+
"tags": [
|
|
33235
|
+
"Connect"
|
|
33236
|
+
],
|
|
33237
|
+
"security": [],
|
|
33238
|
+
"requestBody": {
|
|
33239
|
+
"required": true,
|
|
33240
|
+
"content": {
|
|
33241
|
+
"application/json": {
|
|
33242
|
+
"schema": {
|
|
33243
|
+
"type": "object",
|
|
33244
|
+
"required": [
|
|
33245
|
+
"sessionId"
|
|
33246
|
+
],
|
|
33247
|
+
"properties": {
|
|
33248
|
+
"sessionId": {
|
|
33249
|
+
"type": "string"
|
|
33250
|
+
},
|
|
33251
|
+
"name": {
|
|
33252
|
+
"type": "string"
|
|
33253
|
+
}
|
|
33254
|
+
}
|
|
33255
|
+
}
|
|
33256
|
+
}
|
|
33257
|
+
}
|
|
33258
|
+
},
|
|
33259
|
+
"responses": {
|
|
33260
|
+
"200": {
|
|
33261
|
+
"description": "Invite details",
|
|
33262
|
+
"content": {
|
|
33263
|
+
"application/json": {
|
|
33264
|
+
"schema": {
|
|
33265
|
+
"type": "object",
|
|
33266
|
+
"properties": {
|
|
33267
|
+
"accountId": {
|
|
33268
|
+
"type": "integer"
|
|
33269
|
+
},
|
|
33270
|
+
"inviteEmail": {
|
|
33271
|
+
"type": "string"
|
|
33272
|
+
},
|
|
33273
|
+
"inviteName": {
|
|
33274
|
+
"type": "string"
|
|
33275
|
+
},
|
|
33276
|
+
"twoFactorNumber": {
|
|
33277
|
+
"type": "string"
|
|
33278
|
+
}
|
|
33279
|
+
}
|
|
33280
|
+
}
|
|
33281
|
+
}
|
|
33282
|
+
}
|
|
33283
|
+
}
|
|
33284
|
+
}
|
|
33285
|
+
}
|
|
33286
|
+
},
|
|
33287
|
+
"/v1/connect/booking-extranet-login/session": {
|
|
33288
|
+
"get": {
|
|
33289
|
+
"operationId": "getBookingExtranetLoginConfig",
|
|
33290
|
+
"summary": "Booking.com direct-login config",
|
|
33291
|
+
"description": "Returns the 2FA number the host adds to their Extranet user.\n\nCalled by the hosted Connect page. No API key \u2014 the session ID is the capability token.",
|
|
33292
|
+
"tags": [
|
|
33293
|
+
"Connect"
|
|
33294
|
+
],
|
|
33295
|
+
"security": [],
|
|
33296
|
+
"parameters": [
|
|
33297
|
+
{
|
|
33298
|
+
"name": "sessionId",
|
|
33299
|
+
"in": "query",
|
|
33300
|
+
"required": true,
|
|
33301
|
+
"schema": {
|
|
33302
|
+
"type": "string"
|
|
33303
|
+
},
|
|
33304
|
+
"description": "The Connect session ID (capability token)."
|
|
33305
|
+
}
|
|
33306
|
+
],
|
|
33307
|
+
"responses": {
|
|
33308
|
+
"200": {
|
|
33309
|
+
"description": "Config",
|
|
33310
|
+
"content": {
|
|
33311
|
+
"application/json": {
|
|
33312
|
+
"schema": {
|
|
33313
|
+
"type": "object",
|
|
33314
|
+
"properties": {
|
|
33315
|
+
"twoFactorNumber": {
|
|
33316
|
+
"type": "string"
|
|
33317
|
+
}
|
|
33318
|
+
}
|
|
33319
|
+
}
|
|
33320
|
+
}
|
|
33321
|
+
}
|
|
33322
|
+
}
|
|
33323
|
+
}
|
|
33324
|
+
},
|
|
33325
|
+
"post": {
|
|
33326
|
+
"operationId": "startBookingExtranetLogin",
|
|
33327
|
+
"summary": "Sign in with a Booking.com Extranet user",
|
|
33328
|
+
"description": "Starts the sign-in with the host's Extranet credentials.\n\nCalled by the hosted Connect page. No API key \u2014 the session ID is the capability token.",
|
|
33329
|
+
"tags": [
|
|
33330
|
+
"Connect"
|
|
33331
|
+
],
|
|
33332
|
+
"security": [],
|
|
33333
|
+
"requestBody": {
|
|
33334
|
+
"required": true,
|
|
33335
|
+
"content": {
|
|
33336
|
+
"application/json": {
|
|
33337
|
+
"schema": {
|
|
33338
|
+
"type": "object",
|
|
33339
|
+
"required": [
|
|
33340
|
+
"sessionId",
|
|
33341
|
+
"email",
|
|
33342
|
+
"password"
|
|
33343
|
+
],
|
|
33344
|
+
"properties": {
|
|
33345
|
+
"sessionId": {
|
|
33346
|
+
"type": "string"
|
|
33347
|
+
},
|
|
33348
|
+
"email": {
|
|
33349
|
+
"type": "string"
|
|
33350
|
+
},
|
|
33351
|
+
"password": {
|
|
33352
|
+
"type": "string"
|
|
33353
|
+
},
|
|
33354
|
+
"label": {
|
|
33355
|
+
"type": "string"
|
|
33356
|
+
}
|
|
33357
|
+
}
|
|
33358
|
+
}
|
|
33359
|
+
}
|
|
33360
|
+
}
|
|
33361
|
+
},
|
|
33362
|
+
"responses": {
|
|
33363
|
+
"200": {
|
|
33364
|
+
"description": "Sign-in started",
|
|
33365
|
+
"content": {
|
|
33366
|
+
"application/json": {
|
|
33367
|
+
"schema": {
|
|
33368
|
+
"type": "object",
|
|
33369
|
+
"properties": {
|
|
33370
|
+
"accountId": {
|
|
33371
|
+
"type": "integer"
|
|
33372
|
+
},
|
|
33373
|
+
"status": {
|
|
33374
|
+
"type": "string"
|
|
33375
|
+
},
|
|
33376
|
+
"twoFactorNumber": {
|
|
33377
|
+
"type": "string"
|
|
33378
|
+
},
|
|
33379
|
+
"notificationEmail": {
|
|
33380
|
+
"type": "string"
|
|
33381
|
+
}
|
|
33382
|
+
}
|
|
33383
|
+
}
|
|
33384
|
+
}
|
|
33385
|
+
}
|
|
33386
|
+
}
|
|
33387
|
+
}
|
|
33388
|
+
}
|
|
33389
|
+
},
|
|
33390
|
+
"/v1/connect/booking-extranet-login/status": {
|
|
33391
|
+
"get": {
|
|
33392
|
+
"operationId": "getBookingExtranetLoginStatus",
|
|
33393
|
+
"summary": "Booking.com direct-login status",
|
|
33394
|
+
"description": "Live sign-in status, polled by the hosted page.\n\nCalled by the hosted Connect page. No API key \u2014 the session ID is the capability token.",
|
|
33395
|
+
"tags": [
|
|
33396
|
+
"Connect"
|
|
33397
|
+
],
|
|
33398
|
+
"security": [],
|
|
33399
|
+
"parameters": [
|
|
33400
|
+
{
|
|
33401
|
+
"name": "sessionId",
|
|
33402
|
+
"in": "query",
|
|
33403
|
+
"required": true,
|
|
33404
|
+
"schema": {
|
|
33405
|
+
"type": "string"
|
|
33406
|
+
},
|
|
33407
|
+
"description": "The Connect session ID (capability token)."
|
|
33408
|
+
},
|
|
33409
|
+
{
|
|
33410
|
+
"name": "accountId",
|
|
33411
|
+
"in": "query",
|
|
33412
|
+
"required": true,
|
|
33413
|
+
"schema": {
|
|
33414
|
+
"type": "integer"
|
|
33415
|
+
}
|
|
33416
|
+
}
|
|
33417
|
+
],
|
|
33418
|
+
"responses": {
|
|
33419
|
+
"200": {
|
|
33420
|
+
"description": "Status",
|
|
33421
|
+
"content": {
|
|
33422
|
+
"application/json": {
|
|
33423
|
+
"schema": {
|
|
33424
|
+
"type": "object",
|
|
33425
|
+
"properties": {
|
|
33426
|
+
"accountId": {
|
|
33427
|
+
"type": "integer"
|
|
33428
|
+
},
|
|
33429
|
+
"status": {
|
|
33430
|
+
"type": "string"
|
|
33431
|
+
},
|
|
33432
|
+
"errorMessage": {
|
|
33433
|
+
"type": "string"
|
|
33434
|
+
},
|
|
33435
|
+
"friendlyError": {
|
|
33436
|
+
"type": "string"
|
|
33437
|
+
},
|
|
33438
|
+
"completed": {
|
|
33439
|
+
"type": "boolean"
|
|
33440
|
+
},
|
|
33441
|
+
"awaitingMapping": {
|
|
33442
|
+
"type": "boolean"
|
|
33443
|
+
}
|
|
33444
|
+
}
|
|
33445
|
+
}
|
|
33446
|
+
}
|
|
33447
|
+
}
|
|
33448
|
+
}
|
|
33449
|
+
}
|
|
33450
|
+
}
|
|
33451
|
+
},
|
|
33452
|
+
"/v1/connect/vrbo-login/session": {
|
|
33453
|
+
"post": {
|
|
33454
|
+
"operationId": "vrboLogin",
|
|
33455
|
+
"summary": "Sign in with a Vrbo host account",
|
|
33456
|
+
"description": "`action: login` checks the email and password and answers in seconds: `connected`, `otp_required` (Vrbo sent a code to `destination`) or `failed` with a `reason` (`bad_credentials`, `blocked`, \u2026). `action: otp` submits the code; a refused code comes back as `otp_required` with `reason: bad_code`.\n\nSigning in imports nothing. `accessType` (`full_access` or `messaging`, when the session did not lock it) is the host's choice of whether mapped listings push the calendar. The import starts when the mapping is confirmed.\n\nCalled by the hosted Connect page. No API key \u2014 the session ID is the capability token.",
|
|
33457
|
+
"tags": [
|
|
33458
|
+
"Connect"
|
|
33459
|
+
],
|
|
33460
|
+
"security": [],
|
|
33461
|
+
"requestBody": {
|
|
33462
|
+
"required": true,
|
|
33463
|
+
"content": {
|
|
33464
|
+
"application/json": {
|
|
33465
|
+
"schema": {
|
|
33466
|
+
"type": "object",
|
|
33467
|
+
"required": [
|
|
33468
|
+
"sessionId",
|
|
33469
|
+
"action"
|
|
33470
|
+
],
|
|
33471
|
+
"properties": {
|
|
33472
|
+
"sessionId": {
|
|
33473
|
+
"type": "string"
|
|
33474
|
+
},
|
|
33475
|
+
"action": {
|
|
33476
|
+
"type": "string",
|
|
33477
|
+
"enum": [
|
|
33478
|
+
"login",
|
|
33479
|
+
"otp"
|
|
33480
|
+
]
|
|
33481
|
+
},
|
|
33482
|
+
"email": {
|
|
33483
|
+
"type": "string"
|
|
33484
|
+
},
|
|
33485
|
+
"password": {
|
|
33486
|
+
"type": "string"
|
|
33487
|
+
},
|
|
33488
|
+
"accountId": {
|
|
33489
|
+
"type": "integer"
|
|
33490
|
+
},
|
|
33491
|
+
"code": {
|
|
33492
|
+
"type": "string"
|
|
33493
|
+
},
|
|
33494
|
+
"accessType": {
|
|
33495
|
+
"type": "string",
|
|
33496
|
+
"enum": [
|
|
33497
|
+
"full_access",
|
|
33498
|
+
"messaging"
|
|
33499
|
+
]
|
|
33500
|
+
}
|
|
33501
|
+
}
|
|
33502
|
+
}
|
|
33503
|
+
}
|
|
33504
|
+
}
|
|
33505
|
+
},
|
|
33506
|
+
"responses": {
|
|
33507
|
+
"200": {
|
|
33508
|
+
"description": "Sign-in outcome",
|
|
33509
|
+
"content": {
|
|
33510
|
+
"application/json": {
|
|
33511
|
+
"schema": {
|
|
33512
|
+
"type": "object",
|
|
33513
|
+
"properties": {
|
|
33514
|
+
"accountId": {
|
|
33515
|
+
"type": "integer"
|
|
33516
|
+
},
|
|
33517
|
+
"status": {
|
|
33518
|
+
"type": "string",
|
|
33519
|
+
"enum": [
|
|
33520
|
+
"connected",
|
|
33521
|
+
"otp_required",
|
|
33522
|
+
"pending",
|
|
33523
|
+
"failed"
|
|
33524
|
+
]
|
|
33525
|
+
},
|
|
33526
|
+
"reason": {
|
|
33527
|
+
"type": "string"
|
|
33528
|
+
},
|
|
33529
|
+
"error": {
|
|
33530
|
+
"type": "string"
|
|
33531
|
+
},
|
|
33532
|
+
"destination": {
|
|
33533
|
+
"type": "string"
|
|
33534
|
+
},
|
|
33535
|
+
"notificationEmail": {
|
|
33536
|
+
"type": "string"
|
|
33537
|
+
},
|
|
33538
|
+
"awaitingMapping": {
|
|
33539
|
+
"type": "boolean"
|
|
33540
|
+
}
|
|
33541
|
+
}
|
|
33542
|
+
}
|
|
33543
|
+
}
|
|
33544
|
+
}
|
|
33545
|
+
}
|
|
33546
|
+
}
|
|
33547
|
+
},
|
|
33548
|
+
"get": {
|
|
33549
|
+
"operationId": "getVrboConnectImport",
|
|
33550
|
+
"summary": "Import progress of the session's Vrbo account",
|
|
33551
|
+
"description": "After the mapping is confirmed: `importing` (upcoming bookings and the last 30 days of messages) \u2192 `importing_history` (the rest of the account, in the background) \u2192 `imported`.\n\nCalled by the hosted Connect page. No API key \u2014 the session ID is the capability token.",
|
|
33552
|
+
"tags": [
|
|
33553
|
+
"Connect"
|
|
33554
|
+
],
|
|
33555
|
+
"security": [],
|
|
33556
|
+
"parameters": [
|
|
33557
|
+
{
|
|
33558
|
+
"name": "sessionId",
|
|
33559
|
+
"in": "query",
|
|
33560
|
+
"required": true,
|
|
33561
|
+
"schema": {
|
|
33562
|
+
"type": "string"
|
|
33563
|
+
}
|
|
33564
|
+
}
|
|
33565
|
+
],
|
|
33566
|
+
"responses": {
|
|
33567
|
+
"200": {
|
|
33568
|
+
"description": "Import status",
|
|
33569
|
+
"content": {
|
|
33570
|
+
"application/json": {
|
|
33571
|
+
"schema": {
|
|
33572
|
+
"$ref": "#/components/schemas/VrboImportStatus"
|
|
33573
|
+
}
|
|
33574
|
+
}
|
|
33575
|
+
}
|
|
33576
|
+
}
|
|
33577
|
+
}
|
|
33578
|
+
}
|
|
33579
|
+
},
|
|
33580
|
+
"/v1/connections/{id}/mappings": {
|
|
33581
|
+
"post": {
|
|
33582
|
+
"operationId": "applyConnectionMappings",
|
|
33583
|
+
"summary": "Map, unmap or create listings for units",
|
|
33584
|
+
"description": "One instruction per unit: `{unitId, listingId}` maps, `{unitId, listingId: null}` unmaps, `{unitId, create: true}` creates a listing. Answers per unit.\n\nVrbo: nothing is imported when the account is signed in. Applying a mapping that maps at least one unit starts the import: upcoming bookings and the last 30 days of messages first, then the whole account history. Follow it on `GET /v1/connect/vrbo-login` (`accounts[].import`).\n\nAuth: a Repull API key, or a Connect session token (`sessionId`) while the hosted flow is mapping.",
|
|
33585
|
+
"tags": [
|
|
33586
|
+
"Connections"
|
|
33587
|
+
],
|
|
33588
|
+
"parameters": [
|
|
33589
|
+
{
|
|
33590
|
+
"name": "id",
|
|
33591
|
+
"in": "path",
|
|
33592
|
+
"required": true,
|
|
33593
|
+
"schema": {
|
|
33594
|
+
"type": "string"
|
|
33595
|
+
},
|
|
33596
|
+
"description": "Connection handle `{channel}:{externalAccountId}`, e.g. `vrbo:12` or `booking_extranet:36`."
|
|
33597
|
+
}
|
|
33598
|
+
],
|
|
33599
|
+
"requestBody": {
|
|
33600
|
+
"required": true,
|
|
33601
|
+
"content": {
|
|
33602
|
+
"application/json": {
|
|
33603
|
+
"schema": {
|
|
33604
|
+
"type": "object",
|
|
33605
|
+
"required": [
|
|
33606
|
+
"mappings"
|
|
33607
|
+
],
|
|
33608
|
+
"properties": {
|
|
33609
|
+
"sessionId": {
|
|
33610
|
+
"type": "string"
|
|
33611
|
+
},
|
|
33612
|
+
"mappings": {
|
|
33613
|
+
"type": "array",
|
|
33614
|
+
"items": {
|
|
33615
|
+
"type": "object",
|
|
33616
|
+
"required": [
|
|
33617
|
+
"unitId"
|
|
33618
|
+
],
|
|
33619
|
+
"properties": {
|
|
33620
|
+
"unitId": {
|
|
33621
|
+
"type": "string"
|
|
33622
|
+
},
|
|
33623
|
+
"listingId": {
|
|
33624
|
+
"type": "integer",
|
|
33625
|
+
"nullable": true
|
|
33626
|
+
},
|
|
33627
|
+
"create": {
|
|
33628
|
+
"type": "boolean"
|
|
33629
|
+
},
|
|
33630
|
+
"calendarSync": {
|
|
33631
|
+
"type": "boolean",
|
|
33632
|
+
"description": "Vrbo: push this listing's prices and availability to Vrbo. Omit to follow the connection's access type (`messaging` = off, `full_access` = on). A new listing (`create`) always follows the access type. Other channels ignore it."
|
|
33633
|
+
}
|
|
33634
|
+
}
|
|
33635
|
+
}
|
|
33636
|
+
}
|
|
33637
|
+
}
|
|
33638
|
+
}
|
|
33639
|
+
}
|
|
33640
|
+
}
|
|
33641
|
+
},
|
|
33642
|
+
"responses": {
|
|
33643
|
+
"200": {
|
|
33644
|
+
"description": "Per-unit results",
|
|
33645
|
+
"content": {
|
|
33646
|
+
"application/json": {
|
|
33647
|
+
"schema": {
|
|
33648
|
+
"type": "object",
|
|
33649
|
+
"properties": {
|
|
33650
|
+
"connection_id": {
|
|
33651
|
+
"type": "string"
|
|
33652
|
+
},
|
|
33653
|
+
"channel": {
|
|
33654
|
+
"type": "string"
|
|
33655
|
+
},
|
|
33656
|
+
"results": {
|
|
33657
|
+
"type": "array",
|
|
33658
|
+
"items": {
|
|
33659
|
+
"type": "object",
|
|
33660
|
+
"properties": {
|
|
33661
|
+
"unit_id": {
|
|
33662
|
+
"type": "string"
|
|
33663
|
+
},
|
|
33664
|
+
"listing_id": {
|
|
33665
|
+
"type": "integer",
|
|
33666
|
+
"nullable": true
|
|
33667
|
+
},
|
|
33668
|
+
"created": {
|
|
33669
|
+
"type": "boolean"
|
|
33670
|
+
},
|
|
33671
|
+
"ok": {
|
|
33672
|
+
"type": "boolean"
|
|
33673
|
+
},
|
|
33674
|
+
"error": {
|
|
33675
|
+
"type": "string"
|
|
33676
|
+
}
|
|
33677
|
+
}
|
|
33678
|
+
}
|
|
33679
|
+
}
|
|
33680
|
+
}
|
|
33681
|
+
}
|
|
33682
|
+
}
|
|
33683
|
+
}
|
|
33684
|
+
}
|
|
33685
|
+
}
|
|
33686
|
+
}
|
|
33687
|
+
},
|
|
33688
|
+
"/v1/connections/{id}/mappings/automap": {
|
|
33689
|
+
"post": {
|
|
33690
|
+
"operationId": "autoMapConnectionUnits",
|
|
33691
|
+
"summary": "Auto-map units by exact name",
|
|
33692
|
+
"description": "Proposes (or with `apply: true` applies) mappings where a unit's name exactly matches one listing. Never guesses on ambiguity.\n\nAuth: a Repull API key, or a Connect session token (`sessionId`) while the hosted flow is mapping.",
|
|
33693
|
+
"tags": [
|
|
33694
|
+
"Connections"
|
|
33695
|
+
],
|
|
33696
|
+
"parameters": [
|
|
33697
|
+
{
|
|
33698
|
+
"name": "id",
|
|
33699
|
+
"in": "path",
|
|
33700
|
+
"required": true,
|
|
33701
|
+
"schema": {
|
|
33702
|
+
"type": "string"
|
|
33703
|
+
},
|
|
33704
|
+
"description": "Connection handle `{channel}:{externalAccountId}`, e.g. `vrbo:12` or `booking_extranet:36`."
|
|
33705
|
+
}
|
|
33706
|
+
],
|
|
33707
|
+
"requestBody": {
|
|
33708
|
+
"required": false,
|
|
33709
|
+
"content": {
|
|
33710
|
+
"application/json": {
|
|
33711
|
+
"schema": {
|
|
33712
|
+
"type": "object",
|
|
33713
|
+
"properties": {
|
|
33714
|
+
"sessionId": {
|
|
33715
|
+
"type": "string"
|
|
33716
|
+
},
|
|
33717
|
+
"apply": {
|
|
33718
|
+
"type": "boolean"
|
|
33719
|
+
}
|
|
33720
|
+
}
|
|
33721
|
+
}
|
|
33722
|
+
}
|
|
33723
|
+
}
|
|
33724
|
+
},
|
|
33725
|
+
"responses": {
|
|
33726
|
+
"200": {
|
|
33727
|
+
"description": "Proposed or applied mappings",
|
|
33728
|
+
"content": {
|
|
33729
|
+
"application/json": {
|
|
33730
|
+
"schema": {
|
|
33731
|
+
"type": "object",
|
|
33732
|
+
"properties": {
|
|
33733
|
+
"connection_id": {
|
|
33734
|
+
"type": "string"
|
|
33735
|
+
},
|
|
33736
|
+
"channel": {
|
|
33737
|
+
"type": "string"
|
|
33738
|
+
},
|
|
33739
|
+
"applied": {
|
|
33740
|
+
"type": "boolean"
|
|
33741
|
+
},
|
|
33742
|
+
"results": {
|
|
33743
|
+
"type": "array",
|
|
33744
|
+
"items": {
|
|
33745
|
+
"type": "object",
|
|
33746
|
+
"properties": {
|
|
33747
|
+
"unit_id": {
|
|
33748
|
+
"type": "string"
|
|
33749
|
+
},
|
|
33750
|
+
"listing_id": {
|
|
33751
|
+
"type": "integer",
|
|
33752
|
+
"nullable": true
|
|
33753
|
+
},
|
|
33754
|
+
"created": {
|
|
33755
|
+
"type": "boolean"
|
|
33756
|
+
},
|
|
33757
|
+
"ok": {
|
|
33758
|
+
"type": "boolean"
|
|
33759
|
+
},
|
|
33760
|
+
"error": {
|
|
33761
|
+
"type": "string"
|
|
33762
|
+
}
|
|
33763
|
+
}
|
|
33764
|
+
}
|
|
33765
|
+
}
|
|
33766
|
+
}
|
|
33767
|
+
}
|
|
33768
|
+
}
|
|
33769
|
+
}
|
|
33770
|
+
}
|
|
33771
|
+
}
|
|
33772
|
+
}
|
|
33773
|
+
},
|
|
33774
|
+
"/v1/connections/{id}/units": {
|
|
33775
|
+
"get": {
|
|
33776
|
+
"operationId": "listConnectionUnits",
|
|
33777
|
+
"summary": "List a connection's mappable units",
|
|
33778
|
+
"description": "The units of a connected account with their current listing, a safe suggestion, and the workspace's listing options. `status: ready` with no units means the account has no properties.\n\nAuth: a Repull API key, or a Connect session token (`sessionId`) while the hosted flow is mapping.\n\n`listing_options` carries only the listings the units already point at (mapped or suggested); `listing_options_total` says how many the workspace has. Search the rest with `GET /v1/connections/{id}/listing-options?q=`.",
|
|
33779
|
+
"tags": [
|
|
33780
|
+
"Connections"
|
|
33781
|
+
],
|
|
33782
|
+
"parameters": [
|
|
33783
|
+
{
|
|
33784
|
+
"name": "id",
|
|
33785
|
+
"in": "path",
|
|
33786
|
+
"required": true,
|
|
33787
|
+
"schema": {
|
|
33788
|
+
"type": "string"
|
|
33789
|
+
},
|
|
33790
|
+
"description": "Connection handle `{channel}:{externalAccountId}`, e.g. `vrbo:12` or `booking_extranet:36`."
|
|
33791
|
+
},
|
|
33792
|
+
{
|
|
33793
|
+
"name": "sessionId",
|
|
33794
|
+
"in": "query",
|
|
33795
|
+
"required": false,
|
|
33796
|
+
"schema": {
|
|
33797
|
+
"type": "string"
|
|
33798
|
+
},
|
|
33799
|
+
"description": "The Connect session ID (capability token)."
|
|
33800
|
+
}
|
|
33801
|
+
],
|
|
33802
|
+
"responses": {
|
|
33803
|
+
"200": {
|
|
33804
|
+
"description": "Units",
|
|
33805
|
+
"content": {
|
|
33806
|
+
"application/json": {
|
|
33807
|
+
"schema": {
|
|
33808
|
+
"type": "object",
|
|
33809
|
+
"properties": {
|
|
33810
|
+
"connection_id": {
|
|
33811
|
+
"type": "string"
|
|
33812
|
+
},
|
|
33813
|
+
"channel": {
|
|
33814
|
+
"type": "string"
|
|
33815
|
+
},
|
|
33816
|
+
"status": {
|
|
33817
|
+
"type": "string",
|
|
33818
|
+
"enum": [
|
|
33819
|
+
"importing",
|
|
33820
|
+
"ready",
|
|
33821
|
+
"completed"
|
|
33822
|
+
]
|
|
33823
|
+
},
|
|
33824
|
+
"units": {
|
|
33825
|
+
"type": "array",
|
|
33826
|
+
"items": {
|
|
33827
|
+
"type": "object",
|
|
33828
|
+
"properties": {
|
|
33829
|
+
"unit_id": {
|
|
33830
|
+
"type": "string"
|
|
33831
|
+
},
|
|
33832
|
+
"unit_name": {
|
|
33833
|
+
"type": "string"
|
|
33834
|
+
},
|
|
33835
|
+
"grain": {
|
|
33836
|
+
"type": "string"
|
|
33837
|
+
},
|
|
33838
|
+
"current_listing_id": {
|
|
33839
|
+
"type": "integer",
|
|
33840
|
+
"nullable": true
|
|
33841
|
+
},
|
|
33842
|
+
"suggested_listing_id": {
|
|
33843
|
+
"type": "integer",
|
|
33844
|
+
"nullable": true
|
|
33845
|
+
},
|
|
33846
|
+
"meta": {
|
|
33847
|
+
"type": "object"
|
|
33848
|
+
}
|
|
33849
|
+
}
|
|
33850
|
+
}
|
|
33851
|
+
},
|
|
33852
|
+
"listing_options": {
|
|
33853
|
+
"type": "array",
|
|
33854
|
+
"items": {
|
|
33855
|
+
"type": "object",
|
|
33856
|
+
"properties": {
|
|
33857
|
+
"id": {
|
|
33858
|
+
"type": "integer"
|
|
33859
|
+
},
|
|
33860
|
+
"name": {
|
|
33861
|
+
"type": "string"
|
|
33862
|
+
},
|
|
33863
|
+
"city": {
|
|
33864
|
+
"type": "string"
|
|
33865
|
+
}
|
|
33866
|
+
}
|
|
33867
|
+
}
|
|
33868
|
+
},
|
|
33869
|
+
"missing_capabilities": {
|
|
33870
|
+
"type": "array",
|
|
33871
|
+
"items": {
|
|
33872
|
+
"type": "string"
|
|
33873
|
+
}
|
|
33874
|
+
},
|
|
33875
|
+
"listing_options_total": {
|
|
33876
|
+
"type": "integer",
|
|
33877
|
+
"description": "How many listings the workspace has to map to."
|
|
33878
|
+
}
|
|
33879
|
+
}
|
|
33880
|
+
}
|
|
33881
|
+
}
|
|
33882
|
+
}
|
|
33883
|
+
}
|
|
33884
|
+
}
|
|
33885
|
+
}
|
|
33886
|
+
},
|
|
33887
|
+
"/v1/connect/sessions/{sessionId}/listing-options": {
|
|
33888
|
+
"get": {
|
|
33889
|
+
"operationId": "searchConnectSessionListingOptions",
|
|
33890
|
+
"summary": "Search listings for a Connect mapping picker",
|
|
33891
|
+
"description": "The hosted Connect pages' listing search for their mapping pickers: the session workspace's active listings by name, city or id, `limit` at a time.\n\nCalled by the hosted Connect page. No API key \u2014 the session ID is the capability token.",
|
|
33892
|
+
"tags": [
|
|
33893
|
+
"Connect"
|
|
33894
|
+
],
|
|
33895
|
+
"security": [],
|
|
33896
|
+
"parameters": [
|
|
33897
|
+
{
|
|
33898
|
+
"name": "sessionId",
|
|
33899
|
+
"in": "path",
|
|
33900
|
+
"required": true,
|
|
33901
|
+
"schema": {
|
|
33902
|
+
"type": "string"
|
|
33903
|
+
}
|
|
33904
|
+
},
|
|
33905
|
+
{
|
|
33906
|
+
"name": "q",
|
|
33907
|
+
"in": "query",
|
|
33908
|
+
"required": false,
|
|
33909
|
+
"schema": {
|
|
33910
|
+
"type": "string"
|
|
33911
|
+
}
|
|
33912
|
+
},
|
|
33913
|
+
{
|
|
33914
|
+
"name": "limit",
|
|
33915
|
+
"in": "query",
|
|
33916
|
+
"required": false,
|
|
33917
|
+
"schema": {
|
|
33918
|
+
"type": "integer",
|
|
33919
|
+
"minimum": 1,
|
|
33920
|
+
"maximum": 50,
|
|
33921
|
+
"default": 20
|
|
33922
|
+
}
|
|
33923
|
+
}
|
|
33924
|
+
],
|
|
33925
|
+
"responses": {
|
|
33926
|
+
"200": {
|
|
33927
|
+
"description": "Matching listings",
|
|
33928
|
+
"content": {
|
|
33929
|
+
"application/json": {
|
|
33930
|
+
"schema": {
|
|
33931
|
+
"type": "object",
|
|
33932
|
+
"properties": {
|
|
33933
|
+
"data": {
|
|
33934
|
+
"type": "array",
|
|
33935
|
+
"items": {
|
|
33936
|
+
"type": "object",
|
|
33937
|
+
"properties": {
|
|
33938
|
+
"id": {
|
|
33939
|
+
"type": "integer"
|
|
33940
|
+
},
|
|
33941
|
+
"name": {
|
|
33942
|
+
"type": "string"
|
|
33943
|
+
},
|
|
33944
|
+
"city": {
|
|
33945
|
+
"type": "string",
|
|
33946
|
+
"nullable": true
|
|
33947
|
+
}
|
|
33948
|
+
}
|
|
33949
|
+
}
|
|
33950
|
+
},
|
|
33951
|
+
"total": {
|
|
33952
|
+
"type": "integer"
|
|
33953
|
+
}
|
|
33954
|
+
}
|
|
33955
|
+
}
|
|
33956
|
+
}
|
|
33957
|
+
}
|
|
33958
|
+
}
|
|
33959
|
+
}
|
|
33960
|
+
}
|
|
33961
|
+
},
|
|
33962
|
+
"/v1/connections/{id}/listing-options": {
|
|
33963
|
+
"get": {
|
|
33964
|
+
"operationId": "searchConnectionListingOptions",
|
|
33965
|
+
"summary": "Search listings a unit can be mapped to",
|
|
33966
|
+
"description": "Search the workspace's active listings by name, city or id, for a mapping picker. A workspace can hold tens of thousands of listings, so pickers search here as the user types rather than loading them all. Empty `q` returns the first `limit` listings by name.\n\nAuth: a Repull API key, or a Connect session token (`sessionId`) while the hosted flow is mapping.",
|
|
33967
|
+
"tags": [
|
|
33968
|
+
"Connections"
|
|
33969
|
+
],
|
|
33970
|
+
"parameters": [
|
|
33971
|
+
{
|
|
33972
|
+
"name": "id",
|
|
33973
|
+
"in": "path",
|
|
33974
|
+
"required": true,
|
|
33975
|
+
"schema": {
|
|
33976
|
+
"type": "string"
|
|
33977
|
+
},
|
|
33978
|
+
"description": "Connection handle `{channel}:{externalAccountId}`."
|
|
33979
|
+
},
|
|
33980
|
+
{
|
|
33981
|
+
"name": "q",
|
|
33982
|
+
"in": "query",
|
|
33983
|
+
"required": false,
|
|
33984
|
+
"schema": {
|
|
33985
|
+
"type": "string"
|
|
33986
|
+
},
|
|
33987
|
+
"description": "Text to match (name, city or listing id)."
|
|
33988
|
+
},
|
|
33989
|
+
{
|
|
33990
|
+
"name": "limit",
|
|
33991
|
+
"in": "query",
|
|
33992
|
+
"required": false,
|
|
33993
|
+
"schema": {
|
|
33994
|
+
"type": "integer",
|
|
33995
|
+
"minimum": 1,
|
|
33996
|
+
"maximum": 50,
|
|
33997
|
+
"default": 20
|
|
33998
|
+
}
|
|
33999
|
+
},
|
|
34000
|
+
{
|
|
34001
|
+
"name": "sessionId",
|
|
34002
|
+
"in": "query",
|
|
34003
|
+
"required": false,
|
|
34004
|
+
"schema": {
|
|
34005
|
+
"type": "string"
|
|
34006
|
+
}
|
|
34007
|
+
}
|
|
34008
|
+
],
|
|
34009
|
+
"responses": {
|
|
34010
|
+
"200": {
|
|
34011
|
+
"description": "Matching listings",
|
|
34012
|
+
"content": {
|
|
34013
|
+
"application/json": {
|
|
34014
|
+
"schema": {
|
|
34015
|
+
"type": "object",
|
|
34016
|
+
"properties": {
|
|
34017
|
+
"data": {
|
|
34018
|
+
"type": "array",
|
|
34019
|
+
"items": {
|
|
34020
|
+
"type": "object",
|
|
34021
|
+
"properties": {
|
|
34022
|
+
"id": {
|
|
34023
|
+
"type": "integer"
|
|
34024
|
+
},
|
|
34025
|
+
"name": {
|
|
34026
|
+
"type": "string"
|
|
34027
|
+
},
|
|
34028
|
+
"city": {
|
|
34029
|
+
"type": "string",
|
|
34030
|
+
"nullable": true
|
|
34031
|
+
}
|
|
34032
|
+
}
|
|
34033
|
+
}
|
|
34034
|
+
},
|
|
34035
|
+
"total": {
|
|
34036
|
+
"type": "integer",
|
|
34037
|
+
"description": "How many listings match `q` in total."
|
|
34038
|
+
}
|
|
34039
|
+
}
|
|
34040
|
+
}
|
|
34041
|
+
}
|
|
34042
|
+
}
|
|
34043
|
+
}
|
|
34044
|
+
}
|
|
34045
|
+
}
|
|
34046
|
+
},
|
|
34047
|
+
"/v1/connect/{provider}/write-policy": {
|
|
34048
|
+
"get": {
|
|
34049
|
+
"operationId": "get_connect_write_policy",
|
|
34050
|
+
"summary": "Get what the app may change in a PMS",
|
|
34051
|
+
"description": "Returns the connection's write policy: whether the app may open and close nights, change prices and minimum stay in the PMS, and whether bookings may be created or changed there from the booking website, the dashboard or the reservations API.\n\nHotel PMSs (Cloudbeds, Mews) start with every calendar switch off \u2014 the PMS owns its room inventory. Every other PMS starts with everything on. PMS connections only.",
|
|
34052
|
+
"tags": [
|
|
34053
|
+
"Connect"
|
|
34054
|
+
],
|
|
34055
|
+
"parameters": [
|
|
34056
|
+
{
|
|
34057
|
+
"$ref": "#/components/parameters/provider"
|
|
34058
|
+
}
|
|
34059
|
+
],
|
|
34060
|
+
"responses": {
|
|
34061
|
+
"200": {
|
|
34062
|
+
"description": "The connection's write policy",
|
|
34063
|
+
"content": {
|
|
34064
|
+
"application/json": {
|
|
34065
|
+
"schema": {
|
|
34066
|
+
"type": "object",
|
|
34067
|
+
"properties": {
|
|
34068
|
+
"provider": {
|
|
34069
|
+
"type": "string",
|
|
34070
|
+
"example": "cloudbeds"
|
|
34071
|
+
},
|
|
34072
|
+
"writePolicy": {
|
|
34073
|
+
"$ref": "#/components/schemas/PmsWritePolicy"
|
|
34074
|
+
},
|
|
34075
|
+
"defaults": {
|
|
34076
|
+
"allOf": [
|
|
34077
|
+
{
|
|
34078
|
+
"$ref": "#/components/schemas/PmsWritePolicy"
|
|
34079
|
+
}
|
|
34080
|
+
],
|
|
34081
|
+
"description": "What this provider starts with."
|
|
34082
|
+
}
|
|
34083
|
+
}
|
|
34084
|
+
}
|
|
34085
|
+
}
|
|
34086
|
+
}
|
|
34087
|
+
},
|
|
34088
|
+
"400": {
|
|
34089
|
+
"description": "Not a PMS provider, or an invalid switch",
|
|
34090
|
+
"content": {
|
|
34091
|
+
"application/json": {
|
|
34092
|
+
"schema": {
|
|
34093
|
+
"$ref": "#/components/schemas/Error"
|
|
34094
|
+
}
|
|
34095
|
+
}
|
|
34096
|
+
}
|
|
34097
|
+
},
|
|
34098
|
+
"404": {
|
|
34099
|
+
"description": "No connection for this provider (`no_connection`)",
|
|
34100
|
+
"content": {
|
|
34101
|
+
"application/json": {
|
|
34102
|
+
"schema": {
|
|
34103
|
+
"$ref": "#/components/schemas/Error"
|
|
34104
|
+
}
|
|
34105
|
+
}
|
|
34106
|
+
}
|
|
34107
|
+
}
|
|
34108
|
+
}
|
|
34109
|
+
},
|
|
34110
|
+
"patch": {
|
|
34111
|
+
"operationId": "update_connect_write_policy",
|
|
34112
|
+
"summary": "Change what the app may change in a PMS",
|
|
34113
|
+
"description": "Turns individual write switches on or off for the connection. Only the switches you send change. Takes effect on the next write \u2014 nothing already sent to the PMS is undone. The policy is kept when the PMS is reconnected.\n\nWith `reservations.api` off, the reservations API returns `409 pms_writes_off` for bookings on this PMS. With `reservations.website` off, booking sites stop taking bookings for it before the guest is charged.",
|
|
34114
|
+
"tags": [
|
|
34115
|
+
"Connect"
|
|
34116
|
+
],
|
|
34117
|
+
"parameters": [
|
|
34118
|
+
{
|
|
34119
|
+
"$ref": "#/components/parameters/provider"
|
|
34120
|
+
}
|
|
34121
|
+
],
|
|
34122
|
+
"requestBody": {
|
|
34123
|
+
"required": true,
|
|
34124
|
+
"content": {
|
|
34125
|
+
"application/json": {
|
|
34126
|
+
"schema": {
|
|
34127
|
+
"type": "object",
|
|
34128
|
+
"description": "Only the switches you send change. Every value must be a boolean.",
|
|
34129
|
+
"properties": {
|
|
34130
|
+
"calendar": {
|
|
34131
|
+
"type": "object",
|
|
34132
|
+
"properties": {
|
|
34133
|
+
"availability": {
|
|
34134
|
+
"type": "boolean"
|
|
34135
|
+
},
|
|
34136
|
+
"rates": {
|
|
34137
|
+
"type": "boolean"
|
|
34138
|
+
},
|
|
34139
|
+
"restrictions": {
|
|
34140
|
+
"type": "boolean"
|
|
34141
|
+
}
|
|
34142
|
+
}
|
|
34143
|
+
},
|
|
34144
|
+
"reservations": {
|
|
34145
|
+
"type": "object",
|
|
34146
|
+
"properties": {
|
|
34147
|
+
"website": {
|
|
34148
|
+
"type": "boolean"
|
|
34149
|
+
},
|
|
34150
|
+
"dashboard": {
|
|
34151
|
+
"type": "boolean"
|
|
34152
|
+
},
|
|
34153
|
+
"api": {
|
|
34154
|
+
"type": "boolean"
|
|
34155
|
+
}
|
|
34156
|
+
}
|
|
34157
|
+
}
|
|
34158
|
+
},
|
|
34159
|
+
"example": {
|
|
34160
|
+
"calendar": {
|
|
34161
|
+
"availability": false,
|
|
34162
|
+
"rates": true
|
|
34163
|
+
}
|
|
34164
|
+
}
|
|
34165
|
+
}
|
|
34166
|
+
}
|
|
34167
|
+
}
|
|
34168
|
+
},
|
|
34169
|
+
"responses": {
|
|
34170
|
+
"200": {
|
|
34171
|
+
"description": "The connection's write policy",
|
|
34172
|
+
"content": {
|
|
34173
|
+
"application/json": {
|
|
34174
|
+
"schema": {
|
|
34175
|
+
"type": "object",
|
|
34176
|
+
"properties": {
|
|
34177
|
+
"provider": {
|
|
34178
|
+
"type": "string",
|
|
34179
|
+
"example": "cloudbeds"
|
|
34180
|
+
},
|
|
34181
|
+
"writePolicy": {
|
|
34182
|
+
"$ref": "#/components/schemas/PmsWritePolicy"
|
|
34183
|
+
},
|
|
34184
|
+
"defaults": {
|
|
34185
|
+
"allOf": [
|
|
34186
|
+
{
|
|
34187
|
+
"$ref": "#/components/schemas/PmsWritePolicy"
|
|
34188
|
+
}
|
|
34189
|
+
],
|
|
34190
|
+
"description": "What this provider starts with."
|
|
34191
|
+
}
|
|
34192
|
+
}
|
|
34193
|
+
}
|
|
34194
|
+
}
|
|
34195
|
+
}
|
|
34196
|
+
},
|
|
34197
|
+
"400": {
|
|
34198
|
+
"description": "Not a PMS provider, or an invalid switch",
|
|
34199
|
+
"content": {
|
|
34200
|
+
"application/json": {
|
|
34201
|
+
"schema": {
|
|
34202
|
+
"$ref": "#/components/schemas/Error"
|
|
34203
|
+
}
|
|
34204
|
+
}
|
|
34205
|
+
}
|
|
34206
|
+
},
|
|
34207
|
+
"404": {
|
|
34208
|
+
"description": "No connection for this provider (`no_connection`)",
|
|
34209
|
+
"content": {
|
|
34210
|
+
"application/json": {
|
|
34211
|
+
"schema": {
|
|
34212
|
+
"$ref": "#/components/schemas/Error"
|
|
34213
|
+
}
|
|
34214
|
+
}
|
|
34215
|
+
}
|
|
34216
|
+
}
|
|
34217
|
+
}
|
|
34218
|
+
}
|
|
31483
34219
|
}
|
|
31484
34220
|
}
|
|
31485
34221
|
}
|