repull 0.2.8 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/repull/api/airbnb_api.rb +116 -129
- data/lib/repull/api/billing_api.rb +0 -55
- data/lib/repull/api/booking_com_api.rb +19 -118
- data/lib/repull/api/listings_api.rb +74 -0
- data/lib/repull/api/reservations_api.rb +0 -197
- data/lib/repull/api/{availability_api.rb → sandbox_api.rb} +35 -66
- data/lib/repull/api/vrbo_api.rb +0 -126
- data/lib/repull/models/{create_studio_project_request.rb → airbnb_availability_write_request.rb} +38 -52
- data/lib/repull/models/{create_studio_deployment201_response_data.rb → airbnb_calendar_operation.rb} +108 -57
- data/lib/repull/models/{update_studio_project_request.rb → airbnb_listing_action_request.rb} +55 -47
- data/lib/repull/models/{update_availability_request.rb → airbnb_pricing_write_request.rb} +100 -11
- data/lib/repull/models/{update_reservation_request.rb → booking_availability_update.rb} +124 -22
- data/lib/repull/models/{list_studio_deployments200_response.rb → booking_availability_update_request.rb} +90 -18
- data/lib/repull/models/{generate_studio_completion_request_project_id.rb → booking_availability_update_request_property_id.rb} +2 -2
- data/lib/repull/models/{get_studio_deployment200_response.rb → booking_availability_update_request_updates_inner.rb} +74 -117
- data/lib/repull/models/booking_pricing_rate_update.rb +1 -0
- data/lib/repull/models/booking_pricing_rate_update_restrictions.rb +65 -6
- data/lib/repull/models/{get_studio_project200_response.rb → listing_content_update_request.rb} +106 -10
- data/lib/repull/models/{upsert_studio_project_file200_response.rb → listing_content_update_request_address.rb} +53 -10
- data/lib/repull/models/listing_content_update_request_amenities.rb +105 -0
- data/lib/repull/models/{create_studio_deployment_request.rb → listing_content_update_request_amenities_one_of_inner.rb} +51 -20
- data/lib/repull/models/{create_studio_project_generation_request.rb → listing_content_update_request_occupancy.rb} +42 -28
- data/lib/repull/{api/ai_api.rb → models/listing_content_update_request_photos_inner.rb} +77 -59
- data/lib/repull/models/{generate_studio_completion200_response_data.rb → listing_content_update_request_photos_inner_one_of.rb} +81 -66
- data/lib/repull/models/{generate_studio_completion200_response.rb → listing_content_update_request_policies.rb} +116 -10
- data/lib/repull/models/{delete_studio_project200_response_data.rb → listing_content_update_response.rb} +26 -10
- data/lib/repull/models/map_airbnb_listing_request.rb +215 -0
- data/lib/repull/models/{create_reservation_request.rb → map_airbnb_listing_response.rb} +137 -116
- data/lib/repull/models/property.rb +42 -69
- data/lib/repull/models/reservation.rb +28 -1
- data/lib/repull/models/{upsert_studio_project_file_request.rb → sandbox_fixture_ref.rb} +48 -20
- data/lib/repull/models/{delete_studio_deployment200_response_data.rb → sandbox_reset_result.rb} +72 -11
- data/lib/repull/models/sandbox_reset_result_deleted.rb +216 -0
- data/lib/repull/models/sandbox_seed_result.rb +278 -0
- data/lib/repull/version.rb +1 -1
- data/lib/repull.rb +24 -35
- data/openapi/v1.json +1167 -2030
- metadata +26 -37
- data/lib/repull/api/studio_api.rb +0 -1094
- data/lib/repull/models/create_ai_operation200_response.rb +0 -156
- data/lib/repull/models/create_studio_deployment201_response.rb +0 -147
- data/lib/repull/models/create_studio_project201_response.rb +0 -147
- data/lib/repull/models/create_studio_project201_response_data.rb +0 -199
- data/lib/repull/models/create_studio_project_generation201_response.rb +0 -147
- data/lib/repull/models/create_studio_project_generation201_response_data.rb +0 -165
- data/lib/repull/models/delete_studio_deployment200_response.rb +0 -147
- data/lib/repull/models/delete_studio_project200_response.rb +0 -147
- data/lib/repull/models/delete_studio_project_file200_response.rb +0 -147
- data/lib/repull/models/delete_studio_project_file200_response_data.rb +0 -156
- data/lib/repull/models/generate_studio_completion_request.rb +0 -305
- data/lib/repull/models/list_studio_project_files200_response.rb +0 -149
- data/lib/repull/models/list_studio_projects200_response.rb +0 -149
- data/lib/repull/models/upsert_studio_project_file200_response_data.rb +0 -147
data/openapi/v1.json
CHANGED
|
@@ -127,6 +127,10 @@
|
|
|
127
127
|
"name": "System",
|
|
128
128
|
"description": "Health checks and API status"
|
|
129
129
|
},
|
|
130
|
+
{
|
|
131
|
+
"name": "Sandbox",
|
|
132
|
+
"description": "Test-mode fixtures for contract testing WITHOUT live provider accounts. A `sk_test_*` key seeds a deterministic set of fake listings, reservations, and connected provider accounts (Airbnb + Booking.com), reads them back through the normal endpoints, and resets them \u2014 all in a data space fully isolated from live inventory."
|
|
133
|
+
},
|
|
130
134
|
{
|
|
131
135
|
"name": "schema",
|
|
132
136
|
"description": "Custom field-mapping schemas to reshape response payloads to your app's data model. Built-in schemas (`native`, `calry`, `calry-v1`) ship out of the box; create custom schemas with `POST /v1/schema/custom` and select one per request via the `X-Schema` header."
|
|
@@ -150,17 +154,116 @@
|
|
|
150
154
|
}
|
|
151
155
|
},
|
|
152
156
|
"schemas": {
|
|
153
|
-
"
|
|
157
|
+
"SandboxFixtureRef": {
|
|
154
158
|
"type": "object",
|
|
155
|
-
"description": "A
|
|
159
|
+
"description": "A seeded fixture: its stable reference key plus the synthetic id the read endpoints return for it.",
|
|
156
160
|
"properties": {
|
|
161
|
+
"ref": {
|
|
162
|
+
"type": "string",
|
|
163
|
+
"example": "sbx-listing-oceanview",
|
|
164
|
+
"description": "Stable reference key \u2014 constant across re-seeds."
|
|
165
|
+
},
|
|
157
166
|
"id": {
|
|
158
167
|
"type": "string",
|
|
159
|
-
"
|
|
168
|
+
"example": "900000101",
|
|
169
|
+
"description": "Synthetic id (>= 900,000,000). Reference it against GET /v1/listings, /v1/reservations, /v1/connect."
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
"required": [
|
|
173
|
+
"ref",
|
|
174
|
+
"id"
|
|
175
|
+
]
|
|
176
|
+
},
|
|
177
|
+
"SandboxSeedResult": {
|
|
178
|
+
"type": "object",
|
|
179
|
+
"description": "Result of provisioning the sandbox fixture set.",
|
|
180
|
+
"properties": {
|
|
181
|
+
"customerId": {
|
|
182
|
+
"type": "string",
|
|
183
|
+
"example": "1"
|
|
160
184
|
},
|
|
161
|
-
"
|
|
185
|
+
"seededAt": {
|
|
186
|
+
"type": "string",
|
|
187
|
+
"format": "date-time"
|
|
188
|
+
},
|
|
189
|
+
"listings": {
|
|
190
|
+
"type": "array",
|
|
191
|
+
"items": {
|
|
192
|
+
"$ref": "#/components/schemas/SandboxFixtureRef"
|
|
193
|
+
},
|
|
194
|
+
"description": "3 sample listings."
|
|
195
|
+
},
|
|
196
|
+
"reservations": {
|
|
197
|
+
"type": "array",
|
|
198
|
+
"items": {
|
|
199
|
+
"$ref": "#/components/schemas/SandboxFixtureRef"
|
|
200
|
+
},
|
|
201
|
+
"description": "5 reservations across the lifecycle: created, modified, cancelled, date-changed, pending."
|
|
202
|
+
},
|
|
203
|
+
"connections": {
|
|
204
|
+
"type": "array",
|
|
205
|
+
"items": {
|
|
206
|
+
"$ref": "#/components/schemas/SandboxFixtureRef"
|
|
207
|
+
},
|
|
208
|
+
"description": "2 fake connected provider accounts: Airbnb + Booking.com."
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
"required": [
|
|
212
|
+
"customerId",
|
|
213
|
+
"seededAt",
|
|
214
|
+
"listings",
|
|
215
|
+
"reservations",
|
|
216
|
+
"connections"
|
|
217
|
+
]
|
|
218
|
+
},
|
|
219
|
+
"SandboxResetResult": {
|
|
220
|
+
"type": "object",
|
|
221
|
+
"description": "Result of clearing the sandbox fixture set. Only ever deletes rows in the isolated sandbox data space.",
|
|
222
|
+
"properties": {
|
|
223
|
+
"customerId": {
|
|
224
|
+
"type": "string",
|
|
225
|
+
"example": "1"
|
|
226
|
+
},
|
|
227
|
+
"resetAt": {
|
|
228
|
+
"type": "string",
|
|
229
|
+
"format": "date-time"
|
|
230
|
+
},
|
|
231
|
+
"deleted": {
|
|
232
|
+
"type": "object",
|
|
233
|
+
"properties": {
|
|
234
|
+
"listings": {
|
|
235
|
+
"type": "integer",
|
|
236
|
+
"example": 3
|
|
237
|
+
},
|
|
238
|
+
"reservations": {
|
|
239
|
+
"type": "integer",
|
|
240
|
+
"example": 5
|
|
241
|
+
},
|
|
242
|
+
"connections": {
|
|
243
|
+
"type": "integer",
|
|
244
|
+
"example": 2
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
"required": [
|
|
248
|
+
"listings",
|
|
249
|
+
"reservations",
|
|
250
|
+
"connections"
|
|
251
|
+
]
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
"required": [
|
|
255
|
+
"customerId",
|
|
256
|
+
"resetAt",
|
|
257
|
+
"deleted"
|
|
258
|
+
]
|
|
259
|
+
},
|
|
260
|
+
"Property": {
|
|
261
|
+
"type": "object",
|
|
262
|
+
"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`.",
|
|
263
|
+
"properties": {
|
|
264
|
+
"id": {
|
|
162
265
|
"type": "string",
|
|
163
|
-
"description": "ID
|
|
266
|
+
"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."
|
|
164
267
|
},
|
|
165
268
|
"name": {
|
|
166
269
|
"type": "string",
|
|
@@ -169,56 +272,52 @@
|
|
|
169
272
|
},
|
|
170
273
|
"address": {
|
|
171
274
|
"type": "string",
|
|
172
|
-
"
|
|
275
|
+
"nullable": true,
|
|
276
|
+
"description": "Street address (from the listing's `street` field)."
|
|
173
277
|
},
|
|
174
278
|
"city": {
|
|
175
279
|
"type": "string",
|
|
280
|
+
"nullable": true,
|
|
176
281
|
"example": "Miami Beach"
|
|
177
282
|
},
|
|
178
|
-
"state": {
|
|
179
|
-
"type": "string",
|
|
180
|
-
"example": "FL"
|
|
181
|
-
},
|
|
182
|
-
"country": {
|
|
183
|
-
"type": "string",
|
|
184
|
-
"example": "US"
|
|
185
|
-
},
|
|
186
283
|
"latitude": {
|
|
187
284
|
"type": "number",
|
|
285
|
+
"nullable": true,
|
|
286
|
+
"description": "Detail endpoint only.",
|
|
188
287
|
"example": 25.7617
|
|
189
288
|
},
|
|
190
289
|
"longitude": {
|
|
191
290
|
"type": "number",
|
|
291
|
+
"nullable": true,
|
|
292
|
+
"description": "Detail endpoint only.",
|
|
192
293
|
"example": -80.1918
|
|
193
294
|
},
|
|
194
|
-
"
|
|
195
|
-
"type": "
|
|
196
|
-
"
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
"type": "number",
|
|
200
|
-
"example": 1.5
|
|
295
|
+
"currency": {
|
|
296
|
+
"type": "string",
|
|
297
|
+
"nullable": true,
|
|
298
|
+
"description": "ISO 4217 currency code for this property's pricing.",
|
|
299
|
+
"example": "USD"
|
|
201
300
|
},
|
|
202
|
-
"
|
|
203
|
-
"type": "
|
|
204
|
-
"
|
|
301
|
+
"status": {
|
|
302
|
+
"type": "string",
|
|
303
|
+
"description": "Derived from `listings.active`."
|
|
205
304
|
},
|
|
206
|
-
"
|
|
305
|
+
"lifecycleStatus": {
|
|
207
306
|
"type": "string",
|
|
208
|
-
"
|
|
209
|
-
"description": "
|
|
307
|
+
"nullable": true,
|
|
308
|
+
"description": "The listing's lifecycle state (e.g. `live`, `draft`, `archived`)."
|
|
210
309
|
},
|
|
211
|
-
"
|
|
310
|
+
"createdAt": {
|
|
212
311
|
"type": "string",
|
|
213
|
-
"
|
|
214
|
-
"
|
|
312
|
+
"format": "date-time",
|
|
313
|
+
"description": "When the property was created. Detail endpoint only."
|
|
215
314
|
},
|
|
216
315
|
"channels": {
|
|
217
316
|
"type": "array",
|
|
218
317
|
"items": {
|
|
219
318
|
"type": "string"
|
|
220
319
|
},
|
|
221
|
-
"description": "OTAs/channels this property is actively published on (e.g. `airbnb`, `booking`, `vrbo`). Empty array when the property has no active channel links.",
|
|
320
|
+
"description": "OTAs/channels this property is actively published on, as channel-name strings (e.g. `airbnb`, `booking`, `vrbo`). Empty array when the property has no active channel links. List endpoint (`GET /v1/properties`) only.",
|
|
222
321
|
"example": [
|
|
223
322
|
"airbnb",
|
|
224
323
|
"booking"
|
|
@@ -229,7 +328,7 @@
|
|
|
229
328
|
"items": {
|
|
230
329
|
"$ref": "#/components/schemas/ListingAmenity"
|
|
231
330
|
},
|
|
232
|
-
"description": "Amenity rows for the property. **
|
|
331
|
+
"description": "Amenity rows for the property. Detail endpoint only, and **only present when the caller passes `?include=amenities`.** Empty array (`[]`) when the property has no amenity rows."
|
|
233
332
|
}
|
|
234
333
|
}
|
|
235
334
|
},
|
|
@@ -414,6 +513,11 @@
|
|
|
414
513
|
"format": "date-time",
|
|
415
514
|
"description": "When the reservation row was created in Repull (not the booking-on-channel timestamp)."
|
|
416
515
|
},
|
|
516
|
+
"updatedAt": {
|
|
517
|
+
"type": "string",
|
|
518
|
+
"format": "date-time",
|
|
519
|
+
"description": "Last time this reservation was modified (dates, status, price, or guest details). Advances on every amendment or cancellation \u2014 poll or compare this value to reconcile changes instead of fingerprinting individual fields."
|
|
520
|
+
},
|
|
417
521
|
"bookedAt": {
|
|
418
522
|
"type": "string",
|
|
419
523
|
"format": "date-time",
|
|
@@ -433,7 +537,8 @@
|
|
|
433
537
|
"checkOut",
|
|
434
538
|
"status",
|
|
435
539
|
"confirmationCode",
|
|
436
|
-
"createdAt"
|
|
540
|
+
"createdAt",
|
|
541
|
+
"updatedAt"
|
|
437
542
|
]
|
|
438
543
|
},
|
|
439
544
|
"Guest": {
|
|
@@ -3713,121 +3818,381 @@
|
|
|
3713
3818
|
}
|
|
3714
3819
|
}
|
|
3715
3820
|
},
|
|
3716
|
-
"
|
|
3717
|
-
"type": "object",
|
|
3718
|
-
"properties": {
|
|
3719
|
-
"photos": {
|
|
3720
|
-
"type": "array",
|
|
3721
|
-
"items": {
|
|
3722
|
-
"type": "string",
|
|
3723
|
-
"format": "uri"
|
|
3724
|
-
},
|
|
3725
|
-
"description": "Up to 8 reference photos. When present, Repull AI vision is used for grounded copy.",
|
|
3726
|
-
"maxItems": 8
|
|
3727
|
-
},
|
|
3728
|
-
"style": {
|
|
3729
|
-
"type": "string",
|
|
3730
|
-
"default": "warm"
|
|
3731
|
-
},
|
|
3732
|
-
"persist": {
|
|
3733
|
-
"type": "boolean",
|
|
3734
|
-
"default": true,
|
|
3735
|
-
"description": "Save the generated content to the listing (so subsequent publishes pick it up)."
|
|
3736
|
-
}
|
|
3737
|
-
}
|
|
3738
|
-
},
|
|
3739
|
-
"ListingContent": {
|
|
3821
|
+
"ListingContentUpdateRequest": {
|
|
3740
3822
|
"type": "object",
|
|
3741
|
-
"description": "
|
|
3823
|
+
"description": "Canonical PMS-owned listing content. Every field is optional \u2014 this is a partial update, only the fields you send are written; absent fields are left untouched. This is a LOCAL write only: it does NOT push to Airbnb/Booking.com. Distribution is a separate explicit publish step. `photos` are ingested by URL and attached to the listing in order (full-replace by default, or append via `photosMode`).",
|
|
3742
3824
|
"properties": {
|
|
3743
3825
|
"title": {
|
|
3744
3826
|
"type": "string",
|
|
3745
|
-
"maxLength": 50,
|
|
3746
3827
|
"nullable": true,
|
|
3747
|
-
"description": "
|
|
3748
|
-
},
|
|
3749
|
-
"summary": {
|
|
3750
|
-
"type": "string",
|
|
3751
|
-
"nullable": true
|
|
3752
|
-
},
|
|
3753
|
-
"description": {
|
|
3754
|
-
"type": "string",
|
|
3755
|
-
"nullable": true
|
|
3756
|
-
},
|
|
3757
|
-
"space": {
|
|
3758
|
-
"type": "string",
|
|
3759
|
-
"nullable": true
|
|
3760
|
-
},
|
|
3761
|
-
"guestAccess": {
|
|
3762
|
-
"type": "string",
|
|
3763
|
-
"nullable": true
|
|
3764
|
-
},
|
|
3765
|
-
"neighborhoodOverview": {
|
|
3766
|
-
"type": "string",
|
|
3767
|
-
"nullable": true
|
|
3828
|
+
"description": "Guest-facing title. Written to the listing name and the `en` description."
|
|
3768
3829
|
},
|
|
3769
|
-
"
|
|
3830
|
+
"name": {
|
|
3770
3831
|
"type": "string",
|
|
3771
3832
|
"nullable": true,
|
|
3772
|
-
"description": "
|
|
3773
|
-
},
|
|
3774
|
-
"transit": {
|
|
3775
|
-
"type": "string",
|
|
3776
|
-
"nullable": true
|
|
3833
|
+
"description": "Alias for `title`."
|
|
3777
3834
|
},
|
|
3778
|
-
"
|
|
3835
|
+
"description": {
|
|
3779
3836
|
"type": "string",
|
|
3780
|
-
"nullable": true
|
|
3781
|
-
},
|
|
3782
|
-
"additionalRules": {
|
|
3783
3837
|
"nullable": true,
|
|
3784
|
-
"description": "
|
|
3838
|
+
"description": "Long-form listing description."
|
|
3785
3839
|
},
|
|
3786
|
-
"
|
|
3787
|
-
"type": "string",
|
|
3788
|
-
"nullable": true
|
|
3789
|
-
},
|
|
3790
|
-
"interactionWithGuests": {
|
|
3840
|
+
"summary": {
|
|
3791
3841
|
"type": "string",
|
|
3792
3842
|
"nullable": true,
|
|
3793
|
-
"description": "
|
|
3843
|
+
"description": "Short summary / tagline."
|
|
3794
3844
|
},
|
|
3795
3845
|
"amenities": {
|
|
3796
|
-
"
|
|
3797
|
-
"
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3846
|
+
"description": "FULL replacement of the amenity set. Accepts canonical keys as a string[] or structured rows. Omit to leave amenities untouched; send `[]` to clear them.",
|
|
3847
|
+
"oneOf": [
|
|
3848
|
+
{
|
|
3849
|
+
"type": "array",
|
|
3850
|
+
"items": {
|
|
3851
|
+
"type": "string"
|
|
3852
|
+
},
|
|
3853
|
+
"example": [
|
|
3854
|
+
"wifi",
|
|
3855
|
+
"kitchen",
|
|
3856
|
+
"free_parking"
|
|
3857
|
+
]
|
|
3858
|
+
},
|
|
3859
|
+
{
|
|
3860
|
+
"type": "array",
|
|
3861
|
+
"items": {
|
|
3862
|
+
"type": "object",
|
|
3863
|
+
"required": [
|
|
3864
|
+
"amenityKey"
|
|
3865
|
+
],
|
|
3866
|
+
"properties": {
|
|
3867
|
+
"amenityKey": {
|
|
3868
|
+
"type": "string"
|
|
3869
|
+
},
|
|
3870
|
+
"category": {
|
|
3871
|
+
"type": "string",
|
|
3872
|
+
"nullable": true
|
|
3873
|
+
},
|
|
3874
|
+
"isPresent": {
|
|
3875
|
+
"type": "boolean",
|
|
3876
|
+
"nullable": true,
|
|
3877
|
+
"default": true
|
|
3878
|
+
},
|
|
3879
|
+
"instruction": {
|
|
3880
|
+
"type": "string",
|
|
3881
|
+
"nullable": true
|
|
3882
|
+
}
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
3885
|
+
}
|
|
3886
|
+
]
|
|
3826
3887
|
},
|
|
3827
|
-
"
|
|
3828
|
-
"type": "
|
|
3829
|
-
"
|
|
3830
|
-
"
|
|
3888
|
+
"address": {
|
|
3889
|
+
"type": "object",
|
|
3890
|
+
"description": "Partial address. Only provided sub-fields are written.",
|
|
3891
|
+
"properties": {
|
|
3892
|
+
"street": {
|
|
3893
|
+
"type": "string",
|
|
3894
|
+
"nullable": true
|
|
3895
|
+
},
|
|
3896
|
+
"city": {
|
|
3897
|
+
"type": "string",
|
|
3898
|
+
"nullable": true
|
|
3899
|
+
},
|
|
3900
|
+
"countryCode": {
|
|
3901
|
+
"type": "string",
|
|
3902
|
+
"nullable": true,
|
|
3903
|
+
"description": "ISO-3166 alpha-2 country code."
|
|
3904
|
+
},
|
|
3905
|
+
"lat": {
|
|
3906
|
+
"type": "number",
|
|
3907
|
+
"nullable": true
|
|
3908
|
+
},
|
|
3909
|
+
"lng": {
|
|
3910
|
+
"type": "number",
|
|
3911
|
+
"nullable": true
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3914
|
+
},
|
|
3915
|
+
"occupancy": {
|
|
3916
|
+
"type": "object",
|
|
3917
|
+
"properties": {
|
|
3918
|
+
"maxGuests": {
|
|
3919
|
+
"type": "integer",
|
|
3920
|
+
"nullable": true
|
|
3921
|
+
},
|
|
3922
|
+
"bedrooms": {
|
|
3923
|
+
"type": "integer",
|
|
3924
|
+
"nullable": true
|
|
3925
|
+
},
|
|
3926
|
+
"beds": {
|
|
3927
|
+
"type": "integer",
|
|
3928
|
+
"nullable": true
|
|
3929
|
+
},
|
|
3930
|
+
"bathrooms": {
|
|
3931
|
+
"type": "number",
|
|
3932
|
+
"nullable": true,
|
|
3933
|
+
"description": "Decimal, e.g. 1.5."
|
|
3934
|
+
}
|
|
3935
|
+
}
|
|
3936
|
+
},
|
|
3937
|
+
"policies": {
|
|
3938
|
+
"type": "object",
|
|
3939
|
+
"properties": {
|
|
3940
|
+
"checkInTimeStart": {
|
|
3941
|
+
"type": "string",
|
|
3942
|
+
"nullable": true,
|
|
3943
|
+
"description": "e.g. \"15\" (3pm)."
|
|
3944
|
+
},
|
|
3945
|
+
"checkInTimeEnd": {
|
|
3946
|
+
"type": "string",
|
|
3947
|
+
"nullable": true
|
|
3948
|
+
},
|
|
3949
|
+
"checkOutTime": {
|
|
3950
|
+
"type": "string",
|
|
3951
|
+
"nullable": true,
|
|
3952
|
+
"description": "e.g. \"11\" (11am)."
|
|
3953
|
+
},
|
|
3954
|
+
"houseRules": {
|
|
3955
|
+
"type": "string",
|
|
3956
|
+
"nullable": true,
|
|
3957
|
+
"description": "Free-text house rules."
|
|
3958
|
+
},
|
|
3959
|
+
"cancellationPolicy": {
|
|
3960
|
+
"type": "string",
|
|
3961
|
+
"nullable": true,
|
|
3962
|
+
"description": "Cancellation policy slug/label."
|
|
3963
|
+
},
|
|
3964
|
+
"cancellation": {
|
|
3965
|
+
"type": "string",
|
|
3966
|
+
"nullable": true,
|
|
3967
|
+
"description": "Alias for `cancellationPolicy`."
|
|
3968
|
+
},
|
|
3969
|
+
"allowsChildren": {
|
|
3970
|
+
"type": "boolean",
|
|
3971
|
+
"nullable": true
|
|
3972
|
+
},
|
|
3973
|
+
"allowsInfants": {
|
|
3974
|
+
"type": "boolean",
|
|
3975
|
+
"nullable": true
|
|
3976
|
+
},
|
|
3977
|
+
"allowsPets": {
|
|
3978
|
+
"type": "boolean",
|
|
3979
|
+
"nullable": true
|
|
3980
|
+
},
|
|
3981
|
+
"allowsSmoking": {
|
|
3982
|
+
"type": "boolean",
|
|
3983
|
+
"nullable": true
|
|
3984
|
+
},
|
|
3985
|
+
"allowsEvents": {
|
|
3986
|
+
"type": "boolean",
|
|
3987
|
+
"nullable": true
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
},
|
|
3991
|
+
"photos": {
|
|
3992
|
+
"type": "array",
|
|
3993
|
+
"description": "Photo set \u2014 full replacement by default (pass `photosMode: \"append\"` to add after existing photos, or `[]` to clear; omit to leave untouched). Each entry is a hosted image URL (string) or a structured ref. URL-ingest only: the URL is persisted and attached to the listing in order \u2014 the OTA push downloads it at publish time. Binary/multipart upload is a follow-up. A non-empty array with no valid http(s) URL is reported in `deferred` (existing photos left untouched).",
|
|
3994
|
+
"items": {
|
|
3995
|
+
"oneOf": [
|
|
3996
|
+
{
|
|
3997
|
+
"type": "string",
|
|
3998
|
+
"format": "uri",
|
|
3999
|
+
"description": "Hosted image URL (http/https).",
|
|
4000
|
+
"example": "https://cdn.example.com/photos/living-room.jpg"
|
|
4001
|
+
},
|
|
4002
|
+
{
|
|
4003
|
+
"type": "object",
|
|
4004
|
+
"required": [
|
|
4005
|
+
"url"
|
|
4006
|
+
],
|
|
4007
|
+
"properties": {
|
|
4008
|
+
"url": {
|
|
4009
|
+
"type": "string",
|
|
4010
|
+
"format": "uri",
|
|
4011
|
+
"description": "Hosted image URL (http/https)."
|
|
4012
|
+
},
|
|
4013
|
+
"thumbnailUrl": {
|
|
4014
|
+
"type": "string",
|
|
4015
|
+
"format": "uri",
|
|
4016
|
+
"nullable": true
|
|
4017
|
+
},
|
|
4018
|
+
"caption": {
|
|
4019
|
+
"type": "string",
|
|
4020
|
+
"nullable": true
|
|
4021
|
+
},
|
|
4022
|
+
"category": {
|
|
4023
|
+
"type": "string",
|
|
4024
|
+
"nullable": true,
|
|
4025
|
+
"default": "property"
|
|
4026
|
+
},
|
|
4027
|
+
"width": {
|
|
4028
|
+
"type": "integer",
|
|
4029
|
+
"nullable": true
|
|
4030
|
+
},
|
|
4031
|
+
"height": {
|
|
4032
|
+
"type": "integer",
|
|
4033
|
+
"nullable": true
|
|
4034
|
+
},
|
|
4035
|
+
"sortOrder": {
|
|
4036
|
+
"type": "integer",
|
|
4037
|
+
"nullable": true,
|
|
4038
|
+
"description": "Explicit position; defaults to the array index."
|
|
4039
|
+
},
|
|
4040
|
+
"sourceUrl": {
|
|
4041
|
+
"type": "string",
|
|
4042
|
+
"format": "uri",
|
|
4043
|
+
"nullable": true,
|
|
4044
|
+
"description": "Provenance URL; defaults to `url`."
|
|
4045
|
+
}
|
|
4046
|
+
}
|
|
4047
|
+
}
|
|
4048
|
+
]
|
|
4049
|
+
}
|
|
4050
|
+
},
|
|
4051
|
+
"photosMode": {
|
|
4052
|
+
"type": "string",
|
|
4053
|
+
"default": "replace",
|
|
4054
|
+
"description": "How `photos` is applied: `replace` (full replacement of the photo set) or `append` (add after the existing photos). Ignored when `photos` is absent."
|
|
4055
|
+
}
|
|
4056
|
+
}
|
|
4057
|
+
},
|
|
4058
|
+
"ListingContentUpdateResponse": {
|
|
4059
|
+
"type": "object",
|
|
4060
|
+
"properties": {
|
|
4061
|
+
"id": {
|
|
4062
|
+
"type": "string",
|
|
4063
|
+
"description": "The listing id (serialized as a string to preserve precision)."
|
|
4064
|
+
},
|
|
4065
|
+
"changed": {
|
|
4066
|
+
"type": "array",
|
|
4067
|
+
"items": {
|
|
4068
|
+
"type": "string"
|
|
4069
|
+
},
|
|
4070
|
+
"description": "Content slabs that were actually written, e.g. [\"title\",\"occupancy\",\"amenities\"]."
|
|
4071
|
+
},
|
|
4072
|
+
"deferred": {
|
|
4073
|
+
"type": "array",
|
|
4074
|
+
"items": {
|
|
4075
|
+
"type": "string"
|
|
4076
|
+
},
|
|
4077
|
+
"description": "Provided-but-not-applied fields \u2014 e.g. \"photos\" when a non-empty photos array carried no valid http(s) URL."
|
|
4078
|
+
}
|
|
4079
|
+
}
|
|
4080
|
+
},
|
|
4081
|
+
"ListingGenerateContentRequest": {
|
|
4082
|
+
"type": "object",
|
|
4083
|
+
"properties": {
|
|
4084
|
+
"photos": {
|
|
4085
|
+
"type": "array",
|
|
4086
|
+
"items": {
|
|
4087
|
+
"type": "string",
|
|
4088
|
+
"format": "uri"
|
|
4089
|
+
},
|
|
4090
|
+
"description": "Up to 8 reference photos. When present, Repull AI vision is used for grounded copy.",
|
|
4091
|
+
"maxItems": 8
|
|
4092
|
+
},
|
|
4093
|
+
"style": {
|
|
4094
|
+
"type": "string",
|
|
4095
|
+
"default": "warm"
|
|
4096
|
+
},
|
|
4097
|
+
"persist": {
|
|
4098
|
+
"type": "boolean",
|
|
4099
|
+
"default": true,
|
|
4100
|
+
"description": "Save the generated content to the listing (so subsequent publishes pick it up)."
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
4103
|
+
},
|
|
4104
|
+
"ListingContent": {
|
|
4105
|
+
"type": "object",
|
|
4106
|
+
"description": "Rich multilingual content slab for a listing \u2014 guest-facing copy sourced from `listings_descriptions` (the `en` row when surfaced via `?include=content`). Also returned as the AI-generated payload from `POST /v1/listings/{id}/generate-content` (where `title` and `amenities` are populated). All fields are individually nullable.",
|
|
4107
|
+
"properties": {
|
|
4108
|
+
"title": {
|
|
4109
|
+
"type": "string",
|
|
4110
|
+
"maxLength": 50,
|
|
4111
|
+
"nullable": true,
|
|
4112
|
+
"description": "Public listing title. Populated only by `generate-content`; not stored on `listings_descriptions`."
|
|
4113
|
+
},
|
|
4114
|
+
"summary": {
|
|
4115
|
+
"type": "string",
|
|
4116
|
+
"nullable": true
|
|
4117
|
+
},
|
|
4118
|
+
"description": {
|
|
4119
|
+
"type": "string",
|
|
4120
|
+
"nullable": true
|
|
4121
|
+
},
|
|
4122
|
+
"space": {
|
|
4123
|
+
"type": "string",
|
|
4124
|
+
"nullable": true
|
|
4125
|
+
},
|
|
4126
|
+
"guestAccess": {
|
|
4127
|
+
"type": "string",
|
|
4128
|
+
"nullable": true
|
|
4129
|
+
},
|
|
4130
|
+
"neighborhoodOverview": {
|
|
4131
|
+
"type": "string",
|
|
4132
|
+
"nullable": true
|
|
4133
|
+
},
|
|
4134
|
+
"gettingAround": {
|
|
4135
|
+
"type": "string",
|
|
4136
|
+
"nullable": true,
|
|
4137
|
+
"description": "Free-text directions for getting to + around the property (e.g. \"Take Highway 95 north for 12 miles\")."
|
|
4138
|
+
},
|
|
4139
|
+
"transit": {
|
|
4140
|
+
"type": "string",
|
|
4141
|
+
"nullable": true
|
|
4142
|
+
},
|
|
4143
|
+
"houseRules": {
|
|
4144
|
+
"type": "string",
|
|
4145
|
+
"nullable": true
|
|
4146
|
+
},
|
|
4147
|
+
"additionalRules": {
|
|
4148
|
+
"nullable": true,
|
|
4149
|
+
"description": "Structured supplementary rules (JSON; shape evolves with the listings_descriptions schema)."
|
|
4150
|
+
},
|
|
4151
|
+
"notes": {
|
|
4152
|
+
"type": "string",
|
|
4153
|
+
"nullable": true
|
|
4154
|
+
},
|
|
4155
|
+
"interactionWithGuests": {
|
|
4156
|
+
"type": "string",
|
|
4157
|
+
"nullable": true,
|
|
4158
|
+
"description": "Host\u2019s description of how they engage with guests (e.g. \"Self check-in, available via message\")."
|
|
4159
|
+
},
|
|
4160
|
+
"amenities": {
|
|
4161
|
+
"type": "array",
|
|
4162
|
+
"items": {
|
|
4163
|
+
"type": "string"
|
|
4164
|
+
},
|
|
4165
|
+
"description": "Free-text amenity strings. Populated only by `generate-content`; the `?include=amenities` expansion returns the structured `ListingAmenity[]` instead."
|
|
4166
|
+
}
|
|
4167
|
+
}
|
|
4168
|
+
},
|
|
4169
|
+
"ListingDetails": {
|
|
4170
|
+
"type": "object",
|
|
4171
|
+
"description": "Structural detail slab for a listing \u2014 bedrooms/bathrooms/beds, person capacity, check-in window, wifi credentials, house manual, directions. Sourced from `listings_details` (one row per listing). Surfaced on `GET /v1/listings/{id}` and `GET /v1/listings` only when the caller passes `?include=details`. All fields are individually nullable.",
|
|
4172
|
+
"properties": {
|
|
4173
|
+
"propertyType": {
|
|
4174
|
+
"type": "string",
|
|
4175
|
+
"nullable": true,
|
|
4176
|
+
"description": "Specific property type (e.g. `apartment`, `townhouse`, `cabin`)."
|
|
4177
|
+
},
|
|
4178
|
+
"propertyTypeCategory": {
|
|
4179
|
+
"type": "string",
|
|
4180
|
+
"nullable": true,
|
|
4181
|
+
"description": "Coarser grouping above propertyType (e.g. `house`, `apartment`)."
|
|
4182
|
+
},
|
|
4183
|
+
"roomTypeCategory": {
|
|
4184
|
+
"type": "string",
|
|
4185
|
+
"nullable": true,
|
|
4186
|
+
"description": "Sleeping arrangement (e.g. `entire_home`, `private_room`, `shared_room`)."
|
|
4187
|
+
},
|
|
4188
|
+
"bedrooms": {
|
|
4189
|
+
"type": "integer",
|
|
4190
|
+
"nullable": true
|
|
4191
|
+
},
|
|
4192
|
+
"bathrooms": {
|
|
4193
|
+
"type": "string",
|
|
4194
|
+
"nullable": true,
|
|
4195
|
+
"description": "Numeric value carried as a string to preserve fractional bathrooms (e.g. `\"1.5\"`)."
|
|
3831
4196
|
},
|
|
3832
4197
|
"beds": {
|
|
3833
4198
|
"type": "integer",
|
|
@@ -4895,23 +5260,52 @@
|
|
|
4895
5260
|
},
|
|
4896
5261
|
"BookingPricingRateUpdateRestrictions": {
|
|
4897
5262
|
"type": "object",
|
|
4898
|
-
"description": "Optional length-of-stay / availability restrictions for one rate update.",
|
|
5263
|
+
"description": "Optional length-of-stay / availability restrictions for one rate update. Every field here is forwarded verbatim into Booking.com's rates XML (`minimumstay`, `maximumstay`, `closedonarrival`, `closedondeparture`, \u2026) \u2014 omit a field to leave that restriction untouched.",
|
|
4899
5264
|
"properties": {
|
|
4900
5265
|
"minStay": {
|
|
4901
5266
|
"type": "integer",
|
|
4902
|
-
"nullable": true
|
|
5267
|
+
"nullable": true,
|
|
5268
|
+
"description": "Minimum length of stay (`minimumstay`)."
|
|
4903
5269
|
},
|
|
4904
5270
|
"maxStay": {
|
|
4905
5271
|
"type": "integer",
|
|
4906
|
-
"nullable": true
|
|
5272
|
+
"nullable": true,
|
|
5273
|
+
"description": "Maximum length of stay (`maximumstay`)."
|
|
4907
5274
|
},
|
|
4908
5275
|
"closedToArrival": {
|
|
4909
5276
|
"type": "boolean",
|
|
4910
|
-
"nullable": true
|
|
5277
|
+
"nullable": true,
|
|
5278
|
+
"description": "Closed-to-arrival \u2014 guests may not check in on the affected dates (`closedonarrival`)."
|
|
4911
5279
|
},
|
|
4912
5280
|
"closedToDeparture": {
|
|
4913
5281
|
"type": "boolean",
|
|
4914
|
-
"nullable": true
|
|
5282
|
+
"nullable": true,
|
|
5283
|
+
"description": "Closed-to-departure \u2014 guests may not check out on the affected dates (`closedondeparture`)."
|
|
5284
|
+
},
|
|
5285
|
+
"minStayArrival": {
|
|
5286
|
+
"type": "integer",
|
|
5287
|
+
"nullable": true,
|
|
5288
|
+
"description": "Arrival-based minimum length of stay (`minimumstay_arrival`)."
|
|
5289
|
+
},
|
|
5290
|
+
"maxStayArrival": {
|
|
5291
|
+
"type": "integer",
|
|
5292
|
+
"nullable": true,
|
|
5293
|
+
"description": "Arrival-based maximum length of stay (`maximumstay_arrival`)."
|
|
5294
|
+
},
|
|
5295
|
+
"exactStayArrival": {
|
|
5296
|
+
"type": "integer",
|
|
5297
|
+
"nullable": true,
|
|
5298
|
+
"description": "Arrival-based exact length of stay (`exactstay_arrival`)."
|
|
5299
|
+
},
|
|
5300
|
+
"minAdvanceRes": {
|
|
5301
|
+
"type": "string",
|
|
5302
|
+
"nullable": true,
|
|
5303
|
+
"description": "Minimum advance-reservation window, format `XDY` (X days Y hours) \u2014 `min_advance_res`."
|
|
5304
|
+
},
|
|
5305
|
+
"maxAdvanceRes": {
|
|
5306
|
+
"type": "string",
|
|
5307
|
+
"nullable": true,
|
|
5308
|
+
"description": "Maximum advance-reservation window, format `XDY` (X days Y hours) \u2014 `max_advance_res`."
|
|
4915
5309
|
}
|
|
4916
5310
|
}
|
|
4917
5311
|
},
|
|
@@ -4968,7 +5362,8 @@
|
|
|
4968
5362
|
},
|
|
4969
5363
|
"roomsToSell": {
|
|
4970
5364
|
"type": "integer",
|
|
4971
|
-
"nullable": true
|
|
5365
|
+
"nullable": true,
|
|
5366
|
+
"description": "Rooms to sell for the date range. Set to `0` to stop-sell this room/rate on the rates endpoint (Booking's dedicated `<closed>` stop-sell flag lives on the availability endpoint \u2014 see `BookingAvailabilityUpdate.closed`)."
|
|
4972
5367
|
},
|
|
4973
5368
|
"restrictions": {
|
|
4974
5369
|
"$ref": "#/components/schemas/BookingPricingRateUpdateRestrictions"
|
|
@@ -5035,19 +5430,247 @@
|
|
|
5035
5430
|
},
|
|
5036
5431
|
"additionalProperties": true
|
|
5037
5432
|
},
|
|
5038
|
-
"
|
|
5433
|
+
"BookingAvailabilityUpdate": {
|
|
5039
5434
|
"type": "object",
|
|
5040
|
-
"
|
|
5435
|
+
"required": [
|
|
5436
|
+
"roomId",
|
|
5437
|
+
"rateId",
|
|
5438
|
+
"dateRange",
|
|
5439
|
+
"availableRooms"
|
|
5440
|
+
],
|
|
5441
|
+
"description": "One (room, rate-plan, date-range) availability update. Carries inventory (`availableRooms`), the dedicated stop-sell flag (`closed`), and the same length-of-stay / arrival restrictions as a rate update.",
|
|
5041
5442
|
"properties": {
|
|
5042
|
-
"
|
|
5443
|
+
"roomId": {
|
|
5043
5444
|
"type": "string",
|
|
5044
|
-
"
|
|
5445
|
+
"description": "Booking.com room id."
|
|
5045
5446
|
},
|
|
5046
|
-
"
|
|
5047
|
-
"type": "
|
|
5447
|
+
"rateId": {
|
|
5448
|
+
"type": "string",
|
|
5449
|
+
"description": "Booking.com rate-plan id."
|
|
5048
5450
|
},
|
|
5049
|
-
"
|
|
5050
|
-
"type": "
|
|
5451
|
+
"dateRange": {
|
|
5452
|
+
"type": "object",
|
|
5453
|
+
"required": [
|
|
5454
|
+
"start",
|
|
5455
|
+
"end"
|
|
5456
|
+
],
|
|
5457
|
+
"properties": {
|
|
5458
|
+
"start": {
|
|
5459
|
+
"type": "string",
|
|
5460
|
+
"format": "date"
|
|
5461
|
+
},
|
|
5462
|
+
"end": {
|
|
5463
|
+
"type": "string",
|
|
5464
|
+
"format": "date"
|
|
5465
|
+
}
|
|
5466
|
+
}
|
|
5467
|
+
},
|
|
5468
|
+
"availableRooms": {
|
|
5469
|
+
"type": "integer",
|
|
5470
|
+
"description": "Rooms to sell (`roomstosell`). `0` blocks the room for the range."
|
|
5471
|
+
},
|
|
5472
|
+
"status": {
|
|
5473
|
+
"type": "string",
|
|
5474
|
+
"nullable": true
|
|
5475
|
+
},
|
|
5476
|
+
"closed": {
|
|
5477
|
+
"type": "boolean",
|
|
5478
|
+
"nullable": true,
|
|
5479
|
+
"description": "Dedicated stop-sell flag (`<closed>` in Booking's XML). `true` fully stops sale for the room/date-range regardless of `availableRooms`."
|
|
5480
|
+
},
|
|
5481
|
+
"restrictions": {
|
|
5482
|
+
"$ref": "#/components/schemas/BookingPricingRateUpdateRestrictions"
|
|
5483
|
+
}
|
|
5484
|
+
}
|
|
5485
|
+
},
|
|
5486
|
+
"BookingAvailabilityUpdateRequest": {
|
|
5487
|
+
"type": "object",
|
|
5488
|
+
"required": [
|
|
5489
|
+
"type",
|
|
5490
|
+
"property_id",
|
|
5491
|
+
"updates"
|
|
5492
|
+
],
|
|
5493
|
+
"description": "Body for `PUT /v1/channels/booking/availability`. Selects one of Booking's three ARI write paths via `type` and forwards `updates` verbatim to the connector.",
|
|
5494
|
+
"properties": {
|
|
5495
|
+
"type": {
|
|
5496
|
+
"type": "string",
|
|
5497
|
+
"description": "`rates` \u2192 price + restrictions (`updateRates`); `availability` \u2192 inventory + stop-sell + restrictions (`updateAvailability`); `derived-pricing` \u2192 occupancy-derived pricing rules (`updateDerivedPricing`)."
|
|
5498
|
+
},
|
|
5499
|
+
"property_id": {
|
|
5500
|
+
"oneOf": [
|
|
5501
|
+
{
|
|
5502
|
+
"type": "integer"
|
|
5503
|
+
},
|
|
5504
|
+
{
|
|
5505
|
+
"type": "string"
|
|
5506
|
+
}
|
|
5507
|
+
],
|
|
5508
|
+
"description": "Booking.com hotel/property id (numeric; accepted as int or numeric string)."
|
|
5509
|
+
},
|
|
5510
|
+
"updates": {
|
|
5511
|
+
"type": "array",
|
|
5512
|
+
"minItems": 1,
|
|
5513
|
+
"description": "For `type: \"rates\"` each item is a `BookingPricingRateUpdate`; for `type: \"availability\"` a `BookingAvailabilityUpdate`; for `type: \"derived-pricing\"` a derived-price rule set.",
|
|
5514
|
+
"items": {
|
|
5515
|
+
"oneOf": [
|
|
5516
|
+
{
|
|
5517
|
+
"$ref": "#/components/schemas/BookingPricingRateUpdate"
|
|
5518
|
+
},
|
|
5519
|
+
{
|
|
5520
|
+
"$ref": "#/components/schemas/BookingAvailabilityUpdate"
|
|
5521
|
+
}
|
|
5522
|
+
]
|
|
5523
|
+
}
|
|
5524
|
+
}
|
|
5525
|
+
}
|
|
5526
|
+
},
|
|
5527
|
+
"AirbnbCalendarOperation": {
|
|
5528
|
+
"type": "object",
|
|
5529
|
+
"description": "One calendar operation. Supply either `start_date` + `end_date` OR a `dates` array. Every restriction here is forwarded verbatim to Airbnb's batch calendar API.",
|
|
5530
|
+
"properties": {
|
|
5531
|
+
"start_date": {
|
|
5532
|
+
"type": "string",
|
|
5533
|
+
"format": "date",
|
|
5534
|
+
"nullable": true,
|
|
5535
|
+
"description": "Inclusive range start (pair with `end_date`)."
|
|
5536
|
+
},
|
|
5537
|
+
"end_date": {
|
|
5538
|
+
"type": "string",
|
|
5539
|
+
"format": "date",
|
|
5540
|
+
"nullable": true,
|
|
5541
|
+
"description": "Inclusive range end (pair with `start_date`)."
|
|
5542
|
+
},
|
|
5543
|
+
"dates": {
|
|
5544
|
+
"type": "array",
|
|
5545
|
+
"items": {
|
|
5546
|
+
"type": "string"
|
|
5547
|
+
},
|
|
5548
|
+
"nullable": true,
|
|
5549
|
+
"description": "Explicit date or `start:end` range strings, as an alternative to `start_date`/`end_date`."
|
|
5550
|
+
},
|
|
5551
|
+
"daily_price": {
|
|
5552
|
+
"type": "number",
|
|
5553
|
+
"nullable": true,
|
|
5554
|
+
"description": "Nightly price override."
|
|
5555
|
+
},
|
|
5556
|
+
"availability": {
|
|
5557
|
+
"type": "string",
|
|
5558
|
+
"nullable": true,
|
|
5559
|
+
"description": "Stop-sell is expressed here: `unavailable` blocks the date(s); `available` re-opens; `default` reverts to rule-based availability."
|
|
5560
|
+
},
|
|
5561
|
+
"min_nights": {
|
|
5562
|
+
"type": "integer",
|
|
5563
|
+
"nullable": true,
|
|
5564
|
+
"description": "Minimum length of stay for the date(s)."
|
|
5565
|
+
},
|
|
5566
|
+
"max_nights": {
|
|
5567
|
+
"type": "integer",
|
|
5568
|
+
"nullable": true,
|
|
5569
|
+
"description": "Maximum length of stay for the date(s)."
|
|
5570
|
+
},
|
|
5571
|
+
"closed_to_arrival": {
|
|
5572
|
+
"type": "boolean",
|
|
5573
|
+
"nullable": true,
|
|
5574
|
+
"description": "Closed-to-arrival \u2014 no check-ins on the affected date(s)."
|
|
5575
|
+
},
|
|
5576
|
+
"closed_to_departure": {
|
|
5577
|
+
"type": "boolean",
|
|
5578
|
+
"nullable": true,
|
|
5579
|
+
"description": "Closed-to-departure \u2014 no check-outs on the affected date(s)."
|
|
5580
|
+
},
|
|
5581
|
+
"notes": {
|
|
5582
|
+
"type": "string",
|
|
5583
|
+
"nullable": true
|
|
5584
|
+
}
|
|
5585
|
+
}
|
|
5586
|
+
},
|
|
5587
|
+
"AirbnbAvailabilityWriteRequest": {
|
|
5588
|
+
"type": "object",
|
|
5589
|
+
"required": [
|
|
5590
|
+
"type"
|
|
5591
|
+
],
|
|
5592
|
+
"description": "Body for `PUT /v1/channels/airbnb/listings/{id}/availability`. `type: \"calendar\"` carries per-date restrictions (min/max nights, closed-to-arrival/departure, stop-sell); `type: \"rules\"` carries listing-level availability rules (default min/max nights, booking lead time, turnover days).",
|
|
5593
|
+
"properties": {
|
|
5594
|
+
"type": {
|
|
5595
|
+
"type": "string"
|
|
5596
|
+
},
|
|
5597
|
+
"operations": {
|
|
5598
|
+
"type": "array",
|
|
5599
|
+
"description": "Required when `type: \"calendar\"`. Batch of per-date restriction operations.",
|
|
5600
|
+
"items": {
|
|
5601
|
+
"$ref": "#/components/schemas/AirbnbCalendarOperation"
|
|
5602
|
+
}
|
|
5603
|
+
},
|
|
5604
|
+
"rules": {
|
|
5605
|
+
"type": "object",
|
|
5606
|
+
"additionalProperties": true,
|
|
5607
|
+
"description": "Required when `type: \"rules\"`. Airbnb availability-rules object \u2014 `default_min_nights`, `default_max_nights`, `booking_lead_time`, `turnover_days`, `day_of_week_min_nights`, `seasonal_min_nights`, etc."
|
|
5608
|
+
}
|
|
5609
|
+
}
|
|
5610
|
+
},
|
|
5611
|
+
"AirbnbPricingWriteRequest": {
|
|
5612
|
+
"type": "object",
|
|
5613
|
+
"required": [
|
|
5614
|
+
"type"
|
|
5615
|
+
],
|
|
5616
|
+
"description": "Body for `PUT /v1/channels/airbnb/listings/{id}/pricing`. The `type` discriminator selects the pricing sub-resource. `type: \"calendar\"` shares the same per-date restriction shape as the availability endpoint (min/max nights, closed-to-arrival/departure, stop-sell via `availability: \"unavailable\"`).",
|
|
5617
|
+
"properties": {
|
|
5618
|
+
"type": {
|
|
5619
|
+
"type": "string"
|
|
5620
|
+
},
|
|
5621
|
+
"operations": {
|
|
5622
|
+
"type": "array",
|
|
5623
|
+
"description": "Required when `type: \"calendar\"`. Batch of per-date price + restriction operations.",
|
|
5624
|
+
"items": {
|
|
5625
|
+
"$ref": "#/components/schemas/AirbnbCalendarOperation"
|
|
5626
|
+
}
|
|
5627
|
+
},
|
|
5628
|
+
"modelType": {
|
|
5629
|
+
"type": "string",
|
|
5630
|
+
"nullable": true,
|
|
5631
|
+
"description": "Required when `type: \"model\"` \u2014 the pricing-availability model to switch the listing to."
|
|
5632
|
+
},
|
|
5633
|
+
"settings": {
|
|
5634
|
+
"type": "object",
|
|
5635
|
+
"additionalProperties": true,
|
|
5636
|
+
"nullable": true,
|
|
5637
|
+
"description": "Required for `type: \"standard\" | \"rate-plan\" | \"fees\"` \u2014 the pricing-settings object to PUT."
|
|
5638
|
+
},
|
|
5639
|
+
"records": {
|
|
5640
|
+
"type": "array",
|
|
5641
|
+
"items": {
|
|
5642
|
+
"type": "object",
|
|
5643
|
+
"additionalProperties": true
|
|
5644
|
+
},
|
|
5645
|
+
"nullable": true,
|
|
5646
|
+
"description": "Required for `type: \"los\"` \u2014 length-of-stay records."
|
|
5647
|
+
},
|
|
5648
|
+
"currency": {
|
|
5649
|
+
"type": "string",
|
|
5650
|
+
"nullable": true,
|
|
5651
|
+
"description": "Required for `type: \"currency\"` \u2014 ISO 4217 code."
|
|
5652
|
+
},
|
|
5653
|
+
"rule": {
|
|
5654
|
+
"type": "object",
|
|
5655
|
+
"additionalProperties": true,
|
|
5656
|
+
"nullable": true,
|
|
5657
|
+
"description": "Required for `type: \"rule\"` \u2014 a single pricing rule appended to the listing."
|
|
5658
|
+
}
|
|
5659
|
+
}
|
|
5660
|
+
},
|
|
5661
|
+
"MarketSummary": {
|
|
5662
|
+
"type": "object",
|
|
5663
|
+
"description": "Per-city KPIs combining the customer's own listings with Atlas comp aggregates.",
|
|
5664
|
+
"properties": {
|
|
5665
|
+
"city": {
|
|
5666
|
+
"type": "string",
|
|
5667
|
+
"example": "Radium Hot Springs"
|
|
5668
|
+
},
|
|
5669
|
+
"myListings": {
|
|
5670
|
+
"type": "integer"
|
|
5671
|
+
},
|
|
5672
|
+
"totalListings": {
|
|
5673
|
+
"type": "integer",
|
|
5051
5674
|
"description": "Atlas-tracked active comps in this city."
|
|
5052
5675
|
},
|
|
5053
5676
|
"marketSharePct": {
|
|
@@ -5868,6 +6491,103 @@
|
|
|
5868
6491
|
"connectionId"
|
|
5869
6492
|
]
|
|
5870
6493
|
},
|
|
6494
|
+
"MapAirbnbListingRequest": {
|
|
6495
|
+
"type": "object",
|
|
6496
|
+
"required": [
|
|
6497
|
+
"airbnbId",
|
|
6498
|
+
"listingId"
|
|
6499
|
+
],
|
|
6500
|
+
"description": "Body for `POST /v1/channels/airbnb/listings/map`.",
|
|
6501
|
+
"properties": {
|
|
6502
|
+
"airbnbId": {
|
|
6503
|
+
"type": "string",
|
|
6504
|
+
"description": "The Airbnb listing id to map. Discover it via `GET /v1/channels/airbnb/listings`."
|
|
6505
|
+
},
|
|
6506
|
+
"listingId": {
|
|
6507
|
+
"type": "integer",
|
|
6508
|
+
"description": "Canonical Repull listing id to link the Airbnb listing to. Must belong to your workspace. A numeric string is also accepted."
|
|
6509
|
+
},
|
|
6510
|
+
"hostId": {
|
|
6511
|
+
"type": "string",
|
|
6512
|
+
"description": "Optional. When present, must match the Airbnb listing's host id \u2014 guards against mapping the wrong host's listing."
|
|
6513
|
+
},
|
|
6514
|
+
"syncEnabled": {
|
|
6515
|
+
"type": "boolean",
|
|
6516
|
+
"default": true,
|
|
6517
|
+
"description": "Whether the resulting platform link has sync enabled."
|
|
6518
|
+
}
|
|
6519
|
+
}
|
|
6520
|
+
},
|
|
6521
|
+
"MapAirbnbListingResponse": {
|
|
6522
|
+
"type": "object",
|
|
6523
|
+
"required": [
|
|
6524
|
+
"success",
|
|
6525
|
+
"alreadyMapped",
|
|
6526
|
+
"airbnbId",
|
|
6527
|
+
"listingId",
|
|
6528
|
+
"hostId",
|
|
6529
|
+
"listingAirbnbId",
|
|
6530
|
+
"platformLinkId"
|
|
6531
|
+
],
|
|
6532
|
+
"description": "Id fields are strings (API-wide convention \u2014 bigint ids are stringified to avoid 53-bit JS-number precision loss).",
|
|
6533
|
+
"properties": {
|
|
6534
|
+
"success": {
|
|
6535
|
+
"type": "boolean",
|
|
6536
|
+
"example": true
|
|
6537
|
+
},
|
|
6538
|
+
"alreadyMapped": {
|
|
6539
|
+
"type": "boolean",
|
|
6540
|
+
"description": "True when the Airbnb listing was already mapped to this listing (no-op)."
|
|
6541
|
+
},
|
|
6542
|
+
"airbnbId": {
|
|
6543
|
+
"type": "string"
|
|
6544
|
+
},
|
|
6545
|
+
"listingId": {
|
|
6546
|
+
"type": "string"
|
|
6547
|
+
},
|
|
6548
|
+
"previousListingId": {
|
|
6549
|
+
"type": "string",
|
|
6550
|
+
"description": "The listing the Airbnb record pointed at before this call. Omitted on a no-op."
|
|
6551
|
+
},
|
|
6552
|
+
"hostId": {
|
|
6553
|
+
"type": "string"
|
|
6554
|
+
},
|
|
6555
|
+
"listingAirbnbId": {
|
|
6556
|
+
"type": "string",
|
|
6557
|
+
"description": "Internal id of the `listings_airbnb` record."
|
|
6558
|
+
},
|
|
6559
|
+
"platformLinkId": {
|
|
6560
|
+
"type": "string",
|
|
6561
|
+
"description": "Internal id of the resulting `listing_platform_links` row."
|
|
6562
|
+
}
|
|
6563
|
+
}
|
|
6564
|
+
},
|
|
6565
|
+
"AirbnbListingActionRequest": {
|
|
6566
|
+
"type": "object",
|
|
6567
|
+
"required": [
|
|
6568
|
+
"action"
|
|
6569
|
+
],
|
|
6570
|
+
"description": "Body for `POST /v1/channels/airbnb/listings/{id}`.",
|
|
6571
|
+
"properties": {
|
|
6572
|
+
"action": {
|
|
6573
|
+
"type": "string",
|
|
6574
|
+
"description": "`delete` deactivates the Repull record. `push`/`publish` push content to Airbnb."
|
|
6575
|
+
},
|
|
6576
|
+
"airbnbConnectionId": {
|
|
6577
|
+
"type": "string",
|
|
6578
|
+
"description": "For `push`/`publish`: the Airbnb connection to update (from `GET /v1/channels/airbnb/listings/{id}`). Pass this OR `hostId`."
|
|
6579
|
+
},
|
|
6580
|
+
"hostId": {
|
|
6581
|
+
"type": "string",
|
|
6582
|
+
"description": "For `push`/`publish`: create + publish a new Airbnb listing under this host. Pass this OR `airbnbConnectionId`."
|
|
6583
|
+
},
|
|
6584
|
+
"force": {
|
|
6585
|
+
"type": "boolean",
|
|
6586
|
+
"default": false,
|
|
6587
|
+
"description": "For `push`/`publish`: re-push every field, ignoring dirty-field tracking."
|
|
6588
|
+
}
|
|
6589
|
+
}
|
|
6590
|
+
},
|
|
5871
6591
|
"StudioError": {
|
|
5872
6592
|
"type": "object",
|
|
5873
6593
|
"description": "Repull-style structured error envelope. Surface the `fix` and `docs_url` to your end users so they can self-serve.",
|
|
@@ -6455,32 +7175,102 @@
|
|
|
6455
7175
|
}
|
|
6456
7176
|
}
|
|
6457
7177
|
},
|
|
6458
|
-
"/v1/
|
|
6459
|
-
"
|
|
6460
|
-
"operationId": "
|
|
6461
|
-
"summary": "
|
|
6462
|
-
"description": "
|
|
7178
|
+
"/v1/sandbox/seed": {
|
|
7179
|
+
"post": {
|
|
7180
|
+
"operationId": "seed_sandbox",
|
|
7181
|
+
"summary": "Seed sandbox fixtures",
|
|
7182
|
+
"description": "Provision a deterministic set of test fixtures for contract testing WITHOUT live provider accounts. **Requires a test key (`sk_test_*`)** \u2014 live or legacy keys are rejected with 403.\n\nSeeds, scoped to the authenticated test customer: 3 sample listings, 5 reservations across the lifecycle (created / modified / cancelled / date-changed / pending), and 2 fake connected provider accounts (Airbnb + Booking.com) so the pairing + connection-status flows are testable without real OAuth.\n\nIdempotent \u2014 re-seeding upserts the same rows and returns the same ids. The seeded rows are visible ONLY under a test key, via the normal read endpoints (`GET /v1/listings`, `/v1/reservations`, `/v1/connect`, `/v1/channels/airbnb/listings`, `/v1/channels/airbnb/connection`). They live in a data space fully isolated from live inventory.",
|
|
6463
7183
|
"tags": [
|
|
6464
|
-
"
|
|
7184
|
+
"Sandbox"
|
|
6465
7185
|
],
|
|
6466
|
-
"
|
|
6467
|
-
{
|
|
6468
|
-
"
|
|
6469
|
-
"
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
}
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
"
|
|
6482
|
-
|
|
6483
|
-
|
|
7186
|
+
"responses": {
|
|
7187
|
+
"200": {
|
|
7188
|
+
"description": "Fixtures seeded \u2014 returns the ref\u2192id map",
|
|
7189
|
+
"content": {
|
|
7190
|
+
"application/json": {
|
|
7191
|
+
"schema": {
|
|
7192
|
+
"$ref": "#/components/schemas/SandboxSeedResult"
|
|
7193
|
+
}
|
|
7194
|
+
}
|
|
7195
|
+
}
|
|
7196
|
+
},
|
|
7197
|
+
"401": {
|
|
7198
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
7199
|
+
},
|
|
7200
|
+
"403": {
|
|
7201
|
+
"description": "Not a test key \u2014 the sandbox is only reachable with `sk_test_*`",
|
|
7202
|
+
"content": {
|
|
7203
|
+
"application/json": {
|
|
7204
|
+
"schema": {
|
|
7205
|
+
"$ref": "#/components/schemas/Error"
|
|
7206
|
+
}
|
|
7207
|
+
}
|
|
7208
|
+
}
|
|
7209
|
+
}
|
|
7210
|
+
}
|
|
7211
|
+
}
|
|
7212
|
+
},
|
|
7213
|
+
"/v1/sandbox/reset": {
|
|
7214
|
+
"post": {
|
|
7215
|
+
"operationId": "reset_sandbox",
|
|
7216
|
+
"summary": "Reset sandbox fixtures",
|
|
7217
|
+
"description": "Clear the authenticated test customer's sandbox fixtures. **Requires a test key (`sk_test_*`)** \u2014 live or legacy keys are rejected with 403.\n\nDeletes ONLY the customer's rows in the isolated sandbox data space \u2014 it can never touch real inventory (`listings`, `reservations`, connections). Idempotent: resetting an empty sandbox returns zero counts (still 200). Returns per-resource deletion counts.",
|
|
7218
|
+
"tags": [
|
|
7219
|
+
"Sandbox"
|
|
7220
|
+
],
|
|
7221
|
+
"responses": {
|
|
7222
|
+
"200": {
|
|
7223
|
+
"description": "Fixtures cleared \u2014 returns per-resource deletion counts",
|
|
7224
|
+
"content": {
|
|
7225
|
+
"application/json": {
|
|
7226
|
+
"schema": {
|
|
7227
|
+
"$ref": "#/components/schemas/SandboxResetResult"
|
|
7228
|
+
}
|
|
7229
|
+
}
|
|
7230
|
+
}
|
|
7231
|
+
},
|
|
7232
|
+
"401": {
|
|
7233
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
7234
|
+
},
|
|
7235
|
+
"403": {
|
|
7236
|
+
"description": "Not a test key \u2014 the sandbox is only reachable with `sk_test_*`",
|
|
7237
|
+
"content": {
|
|
7238
|
+
"application/json": {
|
|
7239
|
+
"schema": {
|
|
7240
|
+
"$ref": "#/components/schemas/Error"
|
|
7241
|
+
}
|
|
7242
|
+
}
|
|
7243
|
+
}
|
|
7244
|
+
}
|
|
7245
|
+
}
|
|
7246
|
+
}
|
|
7247
|
+
},
|
|
7248
|
+
"/v1/properties": {
|
|
7249
|
+
"get": {
|
|
7250
|
+
"operationId": "list_properties",
|
|
7251
|
+
"summary": "List properties",
|
|
7252
|
+
"description": "Cursor-paginated list of properties for the authenticated workspace. Walk pages with `?cursor=<pagination.nextCursor>`; stop when `pagination.hasMore` is `false`. Cursor is opaque base64 \u2014 do not parse it.\n\n`?offset=` is also accepted as a first-class alias for shallow paging (0..10000) \u2014 see the `offset` parameter below. Mutually exclusive with `cursor`.\n\nFilters: `q` (substring on name/street/city), `status` (active|inactive|all), `lifecycle_status` (exact match on the listing's lifecycle state). Other unknown params (e.g. `?search=` or `?propertyId=`) are rejected with 422 \u2014 no silent unfiltered results.",
|
|
7253
|
+
"tags": [
|
|
7254
|
+
"Properties"
|
|
7255
|
+
],
|
|
7256
|
+
"parameters": [
|
|
7257
|
+
{
|
|
7258
|
+
"name": "limit",
|
|
7259
|
+
"in": "query",
|
|
7260
|
+
"schema": {
|
|
7261
|
+
"type": "integer",
|
|
7262
|
+
"default": 50,
|
|
7263
|
+
"minimum": 1,
|
|
7264
|
+
"maximum": 100
|
|
7265
|
+
},
|
|
7266
|
+
"description": "Page size (max 100). Requests over the cap return 422."
|
|
7267
|
+
},
|
|
7268
|
+
{
|
|
7269
|
+
"name": "cursor",
|
|
7270
|
+
"in": "query",
|
|
7271
|
+
"schema": {
|
|
7272
|
+
"type": "string"
|
|
7273
|
+
},
|
|
6484
7274
|
"description": "Opaque cursor returned in the previous response's `pagination.nextCursor`. Omit to fetch the first page."
|
|
6485
7275
|
},
|
|
6486
7276
|
{
|
|
@@ -6794,77 +7584,6 @@
|
|
|
6794
7584
|
"$ref": "#/components/responses/UnprocessableEntity"
|
|
6795
7585
|
}
|
|
6796
7586
|
}
|
|
6797
|
-
},
|
|
6798
|
-
"post": {
|
|
6799
|
-
"operationId": "create_reservation",
|
|
6800
|
-
"description": "Create a reservation in the source PMS. Required fields depend on the connected provider (e.g. Airbnb requires guest email; Booking.com requires hotel id). Validation errors return 422 with the offending `field` populated.",
|
|
6801
|
-
"summary": "Create a reservation",
|
|
6802
|
-
"tags": [
|
|
6803
|
-
"Reservations"
|
|
6804
|
-
],
|
|
6805
|
-
"requestBody": {
|
|
6806
|
-
"required": true,
|
|
6807
|
-
"content": {
|
|
6808
|
-
"application/json": {
|
|
6809
|
-
"schema": {
|
|
6810
|
-
"type": "object",
|
|
6811
|
-
"required": [
|
|
6812
|
-
"propertyId",
|
|
6813
|
-
"checkIn",
|
|
6814
|
-
"checkOut",
|
|
6815
|
-
"guestFirstName",
|
|
6816
|
-
"guestLastName"
|
|
6817
|
-
],
|
|
6818
|
-
"properties": {
|
|
6819
|
-
"propertyId": {
|
|
6820
|
-
"type": "string"
|
|
6821
|
-
},
|
|
6822
|
-
"checkIn": {
|
|
6823
|
-
"type": "string",
|
|
6824
|
-
"format": "date"
|
|
6825
|
-
},
|
|
6826
|
-
"checkOut": {
|
|
6827
|
-
"type": "string",
|
|
6828
|
-
"format": "date"
|
|
6829
|
-
},
|
|
6830
|
-
"guestFirstName": {
|
|
6831
|
-
"type": "string"
|
|
6832
|
-
},
|
|
6833
|
-
"guestLastName": {
|
|
6834
|
-
"type": "string"
|
|
6835
|
-
},
|
|
6836
|
-
"guestEmail": {
|
|
6837
|
-
"type": "string"
|
|
6838
|
-
},
|
|
6839
|
-
"guestPhone": {
|
|
6840
|
-
"type": "string"
|
|
6841
|
-
},
|
|
6842
|
-
"guestCount": {
|
|
6843
|
-
"type": "integer"
|
|
6844
|
-
},
|
|
6845
|
-
"totalPrice": {
|
|
6846
|
-
"type": "number"
|
|
6847
|
-
},
|
|
6848
|
-
"currency": {
|
|
6849
|
-
"type": "string"
|
|
6850
|
-
}
|
|
6851
|
-
}
|
|
6852
|
-
}
|
|
6853
|
-
}
|
|
6854
|
-
}
|
|
6855
|
-
},
|
|
6856
|
-
"responses": {
|
|
6857
|
-
"201": {
|
|
6858
|
-
"description": "Reservation created",
|
|
6859
|
-
"content": {
|
|
6860
|
-
"application/json": {
|
|
6861
|
-
"schema": {
|
|
6862
|
-
"$ref": "#/components/schemas/Reservation"
|
|
6863
|
-
}
|
|
6864
|
-
}
|
|
6865
|
-
}
|
|
6866
|
-
}
|
|
6867
|
-
}
|
|
6868
7587
|
}
|
|
6869
7588
|
},
|
|
6870
7589
|
"/v1/reservations/{id}": {
|
|
@@ -6913,250 +7632,89 @@
|
|
|
6913
7632
|
"$ref": "#/components/responses/InternalError"
|
|
6914
7633
|
}
|
|
6915
7634
|
}
|
|
6916
|
-
}
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
"
|
|
7635
|
+
}
|
|
7636
|
+
},
|
|
7637
|
+
"/v1/guests": {
|
|
7638
|
+
"get": {
|
|
7639
|
+
"operationId": "listGuests",
|
|
7640
|
+
"summary": "List guests",
|
|
7641
|
+
"description": "Cursor-paginated list of guests in the workspace. Walks `guests.id ASC` keyset for constant per-page cost regardless of how many guests the customer has. Use `pagination.nextCursor` from one response as the `cursor` query param of the next request.\n\n`?offset=` is also accepted as a first-class alias for shallow paging (0..10000) \u2014 see the `offset` parameter below. Mutually exclusive with `cursor`.\n\nFilters: `q` (substring on name/email/phone), `has_reservation` (`true`|`false`), `listing_id` (restrict to guests with at least one reservation on that listing).",
|
|
6921
7642
|
"tags": [
|
|
6922
|
-
"
|
|
7643
|
+
"Guests"
|
|
6923
7644
|
],
|
|
6924
7645
|
"parameters": [
|
|
6925
7646
|
{
|
|
6926
|
-
"
|
|
6927
|
-
|
|
6928
|
-
|
|
7647
|
+
"$ref": "#/components/parameters/XSchemaHeader"
|
|
7648
|
+
},
|
|
7649
|
+
{
|
|
7650
|
+
"name": "cursor",
|
|
7651
|
+
"in": "query",
|
|
6929
7652
|
"schema": {
|
|
6930
|
-
"type": "
|
|
6931
|
-
}
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
"requestBody": {
|
|
6935
|
-
"content": {
|
|
6936
|
-
"application/json": {
|
|
6937
|
-
"schema": {
|
|
6938
|
-
"type": "object",
|
|
6939
|
-
"properties": {
|
|
6940
|
-
"checkIn": {
|
|
6941
|
-
"type": "string",
|
|
6942
|
-
"format": "date"
|
|
6943
|
-
},
|
|
6944
|
-
"checkOut": {
|
|
6945
|
-
"type": "string",
|
|
6946
|
-
"format": "date"
|
|
6947
|
-
},
|
|
6948
|
-
"status": {
|
|
6949
|
-
"type": "string"
|
|
6950
|
-
},
|
|
6951
|
-
"totalPrice": {
|
|
6952
|
-
"type": "number"
|
|
6953
|
-
}
|
|
6954
|
-
}
|
|
6955
|
-
}
|
|
6956
|
-
}
|
|
6957
|
-
}
|
|
6958
|
-
},
|
|
6959
|
-
"responses": {
|
|
6960
|
-
"200": {
|
|
6961
|
-
"description": "Updated"
|
|
6962
|
-
}
|
|
6963
|
-
}
|
|
6964
|
-
},
|
|
6965
|
-
"delete": {
|
|
6966
|
-
"operationId": "cancel_reservation",
|
|
6967
|
-
"summary": "Cancel reservation",
|
|
6968
|
-
"description": "Cancel an existing reservation. Cancellation rules vary by provider \u2014 Airbnb host-cancellations carry penalties; Booking.com cancellations apply the per-rate-plan policy. Once 200 is returned, the upstream PMS state is committed.",
|
|
6969
|
-
"tags": [
|
|
6970
|
-
"Reservations"
|
|
6971
|
-
],
|
|
6972
|
-
"parameters": [
|
|
7653
|
+
"type": "string"
|
|
7654
|
+
},
|
|
7655
|
+
"description": "Opaque cursor returned in the previous response's `pagination.nextCursor`. Omit to fetch the first page."
|
|
7656
|
+
},
|
|
6973
7657
|
{
|
|
6974
|
-
"
|
|
6975
|
-
|
|
6976
|
-
|
|
7658
|
+
"$ref": "#/components/parameters/Offset"
|
|
7659
|
+
},
|
|
7660
|
+
{
|
|
7661
|
+
"name": "limit",
|
|
7662
|
+
"in": "query",
|
|
6977
7663
|
"schema": {
|
|
6978
|
-
"type": "integer"
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
}
|
|
6986
|
-
}
|
|
6987
|
-
}
|
|
6988
|
-
},
|
|
6989
|
-
"/v1/availability/{propertyId}": {
|
|
6990
|
-
"get": {
|
|
6991
|
-
"operationId": "get_availability",
|
|
6992
|
-
"summary": "Get availability calendar",
|
|
6993
|
-
"description": "Returns day-by-day availability, pricing, and minimum stay for a property.",
|
|
6994
|
-
"tags": [
|
|
6995
|
-
"Availability"
|
|
6996
|
-
],
|
|
6997
|
-
"parameters": [
|
|
7664
|
+
"type": "integer",
|
|
7665
|
+
"default": 20,
|
|
7666
|
+
"minimum": 1,
|
|
7667
|
+
"maximum": 100
|
|
7668
|
+
},
|
|
7669
|
+
"description": "Max items per page. Hard cap is 100."
|
|
7670
|
+
},
|
|
6998
7671
|
{
|
|
6999
|
-
"name": "
|
|
7000
|
-
"in": "
|
|
7001
|
-
"required": true,
|
|
7672
|
+
"name": "q",
|
|
7673
|
+
"in": "query",
|
|
7002
7674
|
"schema": {
|
|
7003
|
-
"type": "
|
|
7004
|
-
}
|
|
7675
|
+
"type": "string"
|
|
7676
|
+
},
|
|
7677
|
+
"description": "Case-insensitive substring search on name, email, or phone."
|
|
7005
7678
|
},
|
|
7006
7679
|
{
|
|
7007
|
-
"name": "
|
|
7680
|
+
"name": "has_reservation",
|
|
7008
7681
|
"in": "query",
|
|
7009
|
-
"required": true,
|
|
7010
7682
|
"schema": {
|
|
7011
|
-
"type": "
|
|
7012
|
-
|
|
7013
|
-
|
|
7683
|
+
"type": "boolean"
|
|
7684
|
+
},
|
|
7685
|
+
"description": "Restrict to guests that do (`true`) or do not (`false`) have any reservation on file."
|
|
7014
7686
|
},
|
|
7015
7687
|
{
|
|
7016
|
-
"name": "
|
|
7688
|
+
"name": "listingId",
|
|
7017
7689
|
"in": "query",
|
|
7018
|
-
"required": true,
|
|
7019
7690
|
"schema": {
|
|
7020
|
-
"type": "
|
|
7021
|
-
|
|
7022
|
-
|
|
7691
|
+
"type": "integer"
|
|
7692
|
+
},
|
|
7693
|
+
"description": "Restrict to guests with at least one reservation on the given internal Repull listing id."
|
|
7023
7694
|
}
|
|
7024
7695
|
],
|
|
7025
7696
|
"responses": {
|
|
7026
7697
|
"200": {
|
|
7027
|
-
"description": "
|
|
7698
|
+
"description": "Guests page",
|
|
7028
7699
|
"content": {
|
|
7029
7700
|
"application/json": {
|
|
7030
7701
|
"schema": {
|
|
7031
|
-
"$ref": "#/components/schemas/
|
|
7702
|
+
"$ref": "#/components/schemas/GuestListResponse"
|
|
7032
7703
|
}
|
|
7033
7704
|
}
|
|
7034
7705
|
}
|
|
7035
|
-
}
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
"name": "propertyId",
|
|
7048
|
-
"in": "path",
|
|
7049
|
-
"required": true,
|
|
7050
|
-
"schema": {
|
|
7051
|
-
"type": "integer"
|
|
7052
|
-
}
|
|
7053
|
-
}
|
|
7054
|
-
],
|
|
7055
|
-
"requestBody": {
|
|
7056
|
-
"content": {
|
|
7057
|
-
"application/json": {
|
|
7058
|
-
"schema": {
|
|
7059
|
-
"type": "object",
|
|
7060
|
-
"properties": {
|
|
7061
|
-
"dates": {
|
|
7062
|
-
"type": "array",
|
|
7063
|
-
"items": {
|
|
7064
|
-
"$ref": "#/components/schemas/CalendarDay"
|
|
7065
|
-
}
|
|
7066
|
-
}
|
|
7067
|
-
}
|
|
7068
|
-
}
|
|
7069
|
-
}
|
|
7070
|
-
}
|
|
7071
|
-
},
|
|
7072
|
-
"responses": {
|
|
7073
|
-
"200": {
|
|
7074
|
-
"description": "Updated"
|
|
7075
|
-
}
|
|
7076
|
-
}
|
|
7077
|
-
}
|
|
7078
|
-
},
|
|
7079
|
-
"/v1/guests": {
|
|
7080
|
-
"get": {
|
|
7081
|
-
"operationId": "listGuests",
|
|
7082
|
-
"summary": "List guests",
|
|
7083
|
-
"description": "Cursor-paginated list of guests in the workspace. Walks `guests.id ASC` keyset for constant per-page cost regardless of how many guests the customer has. Use `pagination.nextCursor` from one response as the `cursor` query param of the next request.\n\n`?offset=` is also accepted as a first-class alias for shallow paging (0..10000) \u2014 see the `offset` parameter below. Mutually exclusive with `cursor`.\n\nFilters: `q` (substring on name/email/phone), `has_reservation` (`true`|`false`), `listing_id` (restrict to guests with at least one reservation on that listing).",
|
|
7084
|
-
"tags": [
|
|
7085
|
-
"Guests"
|
|
7086
|
-
],
|
|
7087
|
-
"parameters": [
|
|
7088
|
-
{
|
|
7089
|
-
"$ref": "#/components/parameters/XSchemaHeader"
|
|
7090
|
-
},
|
|
7091
|
-
{
|
|
7092
|
-
"name": "cursor",
|
|
7093
|
-
"in": "query",
|
|
7094
|
-
"schema": {
|
|
7095
|
-
"type": "string"
|
|
7096
|
-
},
|
|
7097
|
-
"description": "Opaque cursor returned in the previous response's `pagination.nextCursor`. Omit to fetch the first page."
|
|
7098
|
-
},
|
|
7099
|
-
{
|
|
7100
|
-
"$ref": "#/components/parameters/Offset"
|
|
7101
|
-
},
|
|
7102
|
-
{
|
|
7103
|
-
"name": "limit",
|
|
7104
|
-
"in": "query",
|
|
7105
|
-
"schema": {
|
|
7106
|
-
"type": "integer",
|
|
7107
|
-
"default": 20,
|
|
7108
|
-
"minimum": 1,
|
|
7109
|
-
"maximum": 100
|
|
7110
|
-
},
|
|
7111
|
-
"description": "Max items per page. Hard cap is 100."
|
|
7112
|
-
},
|
|
7113
|
-
{
|
|
7114
|
-
"name": "q",
|
|
7115
|
-
"in": "query",
|
|
7116
|
-
"schema": {
|
|
7117
|
-
"type": "string"
|
|
7118
|
-
},
|
|
7119
|
-
"description": "Case-insensitive substring search on name, email, or phone."
|
|
7120
|
-
},
|
|
7121
|
-
{
|
|
7122
|
-
"name": "has_reservation",
|
|
7123
|
-
"in": "query",
|
|
7124
|
-
"schema": {
|
|
7125
|
-
"type": "boolean"
|
|
7126
|
-
},
|
|
7127
|
-
"description": "Restrict to guests that do (`true`) or do not (`false`) have any reservation on file."
|
|
7128
|
-
},
|
|
7129
|
-
{
|
|
7130
|
-
"name": "listingId",
|
|
7131
|
-
"in": "query",
|
|
7132
|
-
"schema": {
|
|
7133
|
-
"type": "integer"
|
|
7134
|
-
},
|
|
7135
|
-
"description": "Restrict to guests with at least one reservation on the given internal Repull listing id."
|
|
7136
|
-
}
|
|
7137
|
-
],
|
|
7138
|
-
"responses": {
|
|
7139
|
-
"200": {
|
|
7140
|
-
"description": "Guests page",
|
|
7141
|
-
"content": {
|
|
7142
|
-
"application/json": {
|
|
7143
|
-
"schema": {
|
|
7144
|
-
"$ref": "#/components/schemas/GuestListResponse"
|
|
7145
|
-
}
|
|
7146
|
-
}
|
|
7147
|
-
}
|
|
7148
|
-
},
|
|
7149
|
-
"400": {
|
|
7150
|
-
"$ref": "#/components/responses/BadRequest"
|
|
7151
|
-
},
|
|
7152
|
-
"401": {
|
|
7153
|
-
"$ref": "#/components/responses/Unauthorized"
|
|
7154
|
-
},
|
|
7155
|
-
"422": {
|
|
7156
|
-
"$ref": "#/components/responses/UnprocessableEntity"
|
|
7157
|
-
},
|
|
7158
|
-
"500": {
|
|
7159
|
-
"$ref": "#/components/responses/InternalError"
|
|
7706
|
+
},
|
|
7707
|
+
"400": {
|
|
7708
|
+
"$ref": "#/components/responses/BadRequest"
|
|
7709
|
+
},
|
|
7710
|
+
"401": {
|
|
7711
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
7712
|
+
},
|
|
7713
|
+
"422": {
|
|
7714
|
+
"$ref": "#/components/responses/UnprocessableEntity"
|
|
7715
|
+
},
|
|
7716
|
+
"500": {
|
|
7717
|
+
"$ref": "#/components/responses/InternalError"
|
|
7160
7718
|
}
|
|
7161
7719
|
}
|
|
7162
7720
|
}
|
|
@@ -8657,26 +9215,6 @@
|
|
|
8657
9215
|
}
|
|
8658
9216
|
}
|
|
8659
9217
|
}
|
|
8660
|
-
},
|
|
8661
|
-
"post": {
|
|
8662
|
-
"operationId": "create_airbnb_listing",
|
|
8663
|
-
"summary": "Create/push Airbnb listing",
|
|
8664
|
-
"description": "Create a new Airbnb listing or push an existing Repull listing to Airbnb. Requires a connected Airbnb account. Returns the created listing id; publishing happens via the listing-action endpoint.",
|
|
8665
|
-
"tags": [
|
|
8666
|
-
"Airbnb"
|
|
8667
|
-
],
|
|
8668
|
-
"responses": {
|
|
8669
|
-
"201": {
|
|
8670
|
-
"description": "Created",
|
|
8671
|
-
"content": {
|
|
8672
|
-
"application/json": {
|
|
8673
|
-
"schema": {
|
|
8674
|
-
"$ref": "#/components/schemas/AirbnbListing"
|
|
8675
|
-
}
|
|
8676
|
-
}
|
|
8677
|
-
}
|
|
8678
|
-
}
|
|
8679
|
-
}
|
|
8680
9218
|
}
|
|
8681
9219
|
},
|
|
8682
9220
|
"/v1/channels/airbnb/listings/{id}": {
|
|
@@ -8721,8 +9259,8 @@
|
|
|
8721
9259
|
},
|
|
8722
9260
|
"post": {
|
|
8723
9261
|
"operationId": "airbnb_listing_action",
|
|
8724
|
-
"summary": "Listing action (delete/push/publish
|
|
8725
|
-
"description": "Apply a state action to a listing by id.\n\n`delete` is
|
|
9262
|
+
"summary": "Listing action (delete/push/publish)",
|
|
9263
|
+
"description": "Apply a state action to a listing by id. The path `id` is the canonical Repull listing id.\n\n`delete` is a **deactivate of the Repull record only** \u2014 it sets the listing inactive and KEEPS the row; it does NOT touch the upstream Airbnb listing (Repull never deletes or deactivates on Airbnb's side). Use it to exclude a listing / trim back under the plan-listings cap; reactivate via `PATCH /v1/listings/{id}` with `{ \"active\": true }`. Idempotent.\n\n`push` / `publish` push the listing's content to Airbnb via the same host-side sync orchestrator as `POST /v1/listings/{id}/publish/airbnb` \u2014 pass `airbnbConnectionId` to update an already-mapped Airbnb listing, or `hostId` to create + publish a new one under that host. `force` re-pushes every field, ignoring dirty-field tracking.\n\nAny other action (e.g. `pull`, `unlist`) returns a structured 422 naming the supported actions.",
|
|
8726
9264
|
"tags": [
|
|
8727
9265
|
"Airbnb"
|
|
8728
9266
|
],
|
|
@@ -8736,9 +9274,62 @@
|
|
|
8736
9274
|
}
|
|
8737
9275
|
}
|
|
8738
9276
|
],
|
|
9277
|
+
"requestBody": {
|
|
9278
|
+
"content": {
|
|
9279
|
+
"application/json": {
|
|
9280
|
+
"schema": {
|
|
9281
|
+
"$ref": "#/components/schemas/AirbnbListingActionRequest"
|
|
9282
|
+
}
|
|
9283
|
+
}
|
|
9284
|
+
}
|
|
9285
|
+
},
|
|
8739
9286
|
"responses": {
|
|
8740
9287
|
"200": {
|
|
8741
9288
|
"description": "Action completed"
|
|
9289
|
+
},
|
|
9290
|
+
"422": {
|
|
9291
|
+
"$ref": "#/components/responses/UnprocessableEntity"
|
|
9292
|
+
}
|
|
9293
|
+
}
|
|
9294
|
+
}
|
|
9295
|
+
},
|
|
9296
|
+
"/v1/channels/airbnb/listings/map": {
|
|
9297
|
+
"post": {
|
|
9298
|
+
"operationId": "map_airbnb_listing",
|
|
9299
|
+
"summary": "Map an Airbnb listing to a Repull listing",
|
|
9300
|
+
"description": "Link an existing Airbnb listing to a canonical Repull listing/property. **API-key-scoped** (unlike the Booking room mapping, which is Connect-session-scoped).\n\nDiscover the `airbnbId` (+ `hostId`) via `GET /v1/channels/airbnb/listings`, then re-point it at the `listingId` of your choice \u2014 the dedup / consolidation case where the Airbnb sync auto-created its own listing but you want the inventory under an existing property.\n\nRepoints both the Airbnb record and its platform link to the target listing in one transaction. Idempotent \u2014 re-mapping to the same listing is a 200 no-op (`alreadyMapped: true`). Scope is enforced against your workspace on both the target listing and the existing Airbnb record; a listing that already links a different Airbnb listing returns 409.",
|
|
9301
|
+
"tags": [
|
|
9302
|
+
"Airbnb"
|
|
9303
|
+
],
|
|
9304
|
+
"requestBody": {
|
|
9305
|
+
"required": true,
|
|
9306
|
+
"content": {
|
|
9307
|
+
"application/json": {
|
|
9308
|
+
"schema": {
|
|
9309
|
+
"$ref": "#/components/schemas/MapAirbnbListingRequest"
|
|
9310
|
+
}
|
|
9311
|
+
}
|
|
9312
|
+
}
|
|
9313
|
+
},
|
|
9314
|
+
"responses": {
|
|
9315
|
+
"200": {
|
|
9316
|
+
"description": "Mapped",
|
|
9317
|
+
"content": {
|
|
9318
|
+
"application/json": {
|
|
9319
|
+
"schema": {
|
|
9320
|
+
"$ref": "#/components/schemas/MapAirbnbListingResponse"
|
|
9321
|
+
}
|
|
9322
|
+
}
|
|
9323
|
+
}
|
|
9324
|
+
},
|
|
9325
|
+
"404": {
|
|
9326
|
+
"$ref": "#/components/responses/NotFound"
|
|
9327
|
+
},
|
|
9328
|
+
"409": {
|
|
9329
|
+
"$ref": "#/components/responses/Conflict"
|
|
9330
|
+
},
|
|
9331
|
+
"422": {
|
|
9332
|
+
"$ref": "#/components/responses/UnprocessableEntity"
|
|
8742
9333
|
}
|
|
8743
9334
|
}
|
|
8744
9335
|
}
|
|
@@ -8770,7 +9361,7 @@
|
|
|
8770
9361
|
"put": {
|
|
8771
9362
|
"operationId": "update_airbnb_listing_pricing",
|
|
8772
9363
|
"summary": "Update Airbnb pricing",
|
|
8773
|
-
"description": "Push pricing changes to Airbnb. The
|
|
9364
|
+
"description": "Push pricing changes to Airbnb. The `type` discriminator selects the sub-resource (model, standard settings, LOS, rate-plan, fees, currency, rule, or per-date `calendar`). `type: \"calendar\"` carries the full per-date restriction set \u2014 nightly price, min/max nights, closed-to-arrival, closed-to-departure, and stop-sell (`availability: \"unavailable\"`). For settings sub-resources the full object is replaced \u2014 GET first, mutate locally, then PUT the whole object.",
|
|
8774
9365
|
"tags": [
|
|
8775
9366
|
"Airbnb"
|
|
8776
9367
|
],
|
|
@@ -8784,6 +9375,16 @@
|
|
|
8784
9375
|
}
|
|
8785
9376
|
}
|
|
8786
9377
|
],
|
|
9378
|
+
"requestBody": {
|
|
9379
|
+
"required": true,
|
|
9380
|
+
"content": {
|
|
9381
|
+
"application/json": {
|
|
9382
|
+
"schema": {
|
|
9383
|
+
"$ref": "#/components/schemas/AirbnbPricingWriteRequest"
|
|
9384
|
+
}
|
|
9385
|
+
}
|
|
9386
|
+
}
|
|
9387
|
+
},
|
|
8787
9388
|
"responses": {
|
|
8788
9389
|
"200": {
|
|
8789
9390
|
"description": "Updated"
|
|
@@ -8818,7 +9419,7 @@
|
|
|
8818
9419
|
"put": {
|
|
8819
9420
|
"operationId": "update_airbnb_listing_availability",
|
|
8820
9421
|
"summary": "Update Airbnb availability",
|
|
8821
|
-
"description": "Push
|
|
9422
|
+
"description": "Push availability + restrictions to Airbnb. `type: \"calendar\"` writes per-date restrictions \u2014 min/max nights, closed-to-arrival, closed-to-departure, and stop-sell (`availability: \"unavailable\"`) \u2014 via a batch of operations that each target either a date range or an explicit date list. `type: \"rules\"` writes listing-level availability rules (default min/max nights, booking lead time, turnover days, seasonal/day-of-week min nights). Restrictions never leak across channels \u2014 this endpoint writes only to Airbnb.",
|
|
8822
9423
|
"tags": [
|
|
8823
9424
|
"Airbnb"
|
|
8824
9425
|
],
|
|
@@ -8832,6 +9433,16 @@
|
|
|
8832
9433
|
}
|
|
8833
9434
|
}
|
|
8834
9435
|
],
|
|
9436
|
+
"requestBody": {
|
|
9437
|
+
"required": true,
|
|
9438
|
+
"content": {
|
|
9439
|
+
"application/json": {
|
|
9440
|
+
"schema": {
|
|
9441
|
+
"$ref": "#/components/schemas/AirbnbAvailabilityWriteRequest"
|
|
9442
|
+
}
|
|
9443
|
+
}
|
|
9444
|
+
}
|
|
9445
|
+
},
|
|
8835
9446
|
"responses": {
|
|
8836
9447
|
"200": {
|
|
8837
9448
|
"description": "Updated"
|
|
@@ -9276,21 +9887,6 @@
|
|
|
9276
9887
|
}
|
|
9277
9888
|
}
|
|
9278
9889
|
},
|
|
9279
|
-
"/v1/channels/airbnb/sync": {
|
|
9280
|
-
"post": {
|
|
9281
|
-
"operationId": "sync_airbnb",
|
|
9282
|
-
"summary": "Bulk sync to Airbnb",
|
|
9283
|
-
"description": "Push all property data to Airbnb in one call.",
|
|
9284
|
-
"tags": [
|
|
9285
|
-
"Airbnb"
|
|
9286
|
-
],
|
|
9287
|
-
"responses": {
|
|
9288
|
-
"200": {
|
|
9289
|
-
"description": "Sync started"
|
|
9290
|
-
}
|
|
9291
|
-
}
|
|
9292
|
-
}
|
|
9293
|
-
},
|
|
9294
9890
|
"/v1/listings": {
|
|
9295
9891
|
"get": {
|
|
9296
9892
|
"operationId": "listListings",
|
|
@@ -9570,6 +10166,58 @@
|
|
|
9570
10166
|
}
|
|
9571
10167
|
}
|
|
9572
10168
|
},
|
|
10169
|
+
"/v1/listings/{id}/content": {
|
|
10170
|
+
"put": {
|
|
10171
|
+
"operationId": "updateListingContent",
|
|
10172
|
+
"summary": "Update canonical listing content",
|
|
10173
|
+
"description": "Write your PMS's canonical listing content \u2014 title, description, amenities, address, occupancy, and policies \u2014 into a Repull listing, making it the source of truth. This is the flagship \"the PMS owns listing content, Repull distributes it\" enabler.\n\n**Partial update:** every field is optional. Only the fields you send are written; absent fields are left untouched. `amenities` is a FULL replacement of the amenity set (omit to leave untouched, send `[]` to clear).\n\n**Local write only \u2014 NOT a channel publish.** This mutates Repull's own copy of the content. It does NOT push to Airbnb / Booking.com; it marks the channels dirty so a later publish knows what changed. Distribution stays a separate explicit step.\n\n**Photos are deferred:** a provided `photos` array is echoed back in the `deferred` field and NOT persisted (media ingestion is a follow-up).\n\nCross-tenant access (a listing that belongs to a different workspace) returns 404 \u2014 never 403. This endpoint is served even when the account is over the plan-listings cap, since editing content on a listing you already own never grows the portfolio.",
|
|
10174
|
+
"tags": [
|
|
10175
|
+
"Listings"
|
|
10176
|
+
],
|
|
10177
|
+
"parameters": [
|
|
10178
|
+
{
|
|
10179
|
+
"name": "id",
|
|
10180
|
+
"in": "path",
|
|
10181
|
+
"required": true,
|
|
10182
|
+
"schema": {
|
|
10183
|
+
"type": "integer"
|
|
10184
|
+
},
|
|
10185
|
+
"description": "Repull listing id"
|
|
10186
|
+
}
|
|
10187
|
+
],
|
|
10188
|
+
"requestBody": {
|
|
10189
|
+
"required": true,
|
|
10190
|
+
"content": {
|
|
10191
|
+
"application/json": {
|
|
10192
|
+
"schema": {
|
|
10193
|
+
"$ref": "#/components/schemas/ListingContentUpdateRequest"
|
|
10194
|
+
}
|
|
10195
|
+
}
|
|
10196
|
+
}
|
|
10197
|
+
},
|
|
10198
|
+
"responses": {
|
|
10199
|
+
"200": {
|
|
10200
|
+
"description": "Content updated",
|
|
10201
|
+
"content": {
|
|
10202
|
+
"application/json": {
|
|
10203
|
+
"schema": {
|
|
10204
|
+
"$ref": "#/components/schemas/ListingContentUpdateResponse"
|
|
10205
|
+
}
|
|
10206
|
+
}
|
|
10207
|
+
}
|
|
10208
|
+
},
|
|
10209
|
+
"401": {
|
|
10210
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
10211
|
+
},
|
|
10212
|
+
"404": {
|
|
10213
|
+
"$ref": "#/components/responses/NotFound"
|
|
10214
|
+
},
|
|
10215
|
+
"422": {
|
|
10216
|
+
"$ref": "#/components/responses/UnprocessableEntity"
|
|
10217
|
+
}
|
|
10218
|
+
}
|
|
10219
|
+
}
|
|
10220
|
+
},
|
|
9573
10221
|
"/v1/listings/{id}/generate-content": {
|
|
9574
10222
|
"post": {
|
|
9575
10223
|
"operationId": "generateListingContent",
|
|
@@ -9754,39 +10402,41 @@
|
|
|
9754
10402
|
}
|
|
9755
10403
|
}
|
|
9756
10404
|
}
|
|
9757
|
-
},
|
|
9758
|
-
"post": {
|
|
9759
|
-
"operationId": "create_booking_property",
|
|
9760
|
-
"summary": "Create Booking.com property",
|
|
9761
|
-
"description": "Onboard a new Booking.com hotel via the OAuth Connect flow. Returns the hotel id once Stage-1 designation completes in the Extranet.",
|
|
9762
|
-
"tags": [
|
|
9763
|
-
"Booking.com"
|
|
9764
|
-
],
|
|
9765
|
-
"responses": {
|
|
9766
|
-
"201": {
|
|
9767
|
-
"description": "Created",
|
|
9768
|
-
"content": {
|
|
9769
|
-
"application/json": {
|
|
9770
|
-
"schema": {
|
|
9771
|
-
"$ref": "#/components/schemas/BookingProperty"
|
|
9772
|
-
}
|
|
9773
|
-
}
|
|
9774
|
-
}
|
|
9775
|
-
}
|
|
9776
|
-
}
|
|
9777
10405
|
}
|
|
9778
10406
|
},
|
|
9779
10407
|
"/v1/channels/booking/availability": {
|
|
9780
10408
|
"put": {
|
|
9781
10409
|
"operationId": "update_booking_availability",
|
|
9782
10410
|
"summary": "Update Booking.com rates/availability",
|
|
9783
|
-
"description": "Push availability
|
|
10411
|
+
"description": "Push availability, rates, and the full restriction set to Booking.com. `type` selects the write path:\n\n- `rates` \u2014 nightly price + length-of-stay / arrival restrictions (min/max stay, closed-to-arrival, closed-to-departure, advance-reservation window).\n- `availability` \u2014 inventory (`availableRooms`), the dedicated stop-sell flag (`closed`), and the same restriction set.\n- `derived-pricing` \u2014 occupancy-derived pricing rules.\n\nRestrictions never leak across channels \u2014 this endpoint writes only to Booking.com. Errors from upstream surface as `booking_error`.",
|
|
9784
10412
|
"tags": [
|
|
9785
10413
|
"Booking.com"
|
|
9786
10414
|
],
|
|
10415
|
+
"requestBody": {
|
|
10416
|
+
"required": true,
|
|
10417
|
+
"content": {
|
|
10418
|
+
"application/json": {
|
|
10419
|
+
"schema": {
|
|
10420
|
+
"$ref": "#/components/schemas/BookingAvailabilityUpdateRequest"
|
|
10421
|
+
}
|
|
10422
|
+
}
|
|
10423
|
+
}
|
|
10424
|
+
},
|
|
9787
10425
|
"responses": {
|
|
9788
10426
|
"200": {
|
|
9789
10427
|
"description": "Updated"
|
|
10428
|
+
},
|
|
10429
|
+
"400": {
|
|
10430
|
+
"$ref": "#/components/responses/BadRequest"
|
|
10431
|
+
},
|
|
10432
|
+
"401": {
|
|
10433
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
10434
|
+
},
|
|
10435
|
+
"404": {
|
|
10436
|
+
"$ref": "#/components/responses/NotFound"
|
|
10437
|
+
},
|
|
10438
|
+
"500": {
|
|
10439
|
+
"$ref": "#/components/responses/InternalError"
|
|
9790
10440
|
}
|
|
9791
10441
|
}
|
|
9792
10442
|
}
|
|
@@ -9854,21 +10504,6 @@
|
|
|
9854
10504
|
}
|
|
9855
10505
|
}
|
|
9856
10506
|
},
|
|
9857
|
-
"/v1/channels/booking/sync": {
|
|
9858
|
-
"post": {
|
|
9859
|
-
"operationId": "sync_booking",
|
|
9860
|
-
"summary": "Bulk sync to Booking.com",
|
|
9861
|
-
"description": "Trigger a full bulk sync of properties + availability + rates to Booking.com. Runs async \u2014 returns 202 with a job id; poll `/v1/sync/jobs/{id}` for status.",
|
|
9862
|
-
"tags": [
|
|
9863
|
-
"Booking.com"
|
|
9864
|
-
],
|
|
9865
|
-
"responses": {
|
|
9866
|
-
"200": {
|
|
9867
|
-
"description": "Sync started"
|
|
9868
|
-
}
|
|
9869
|
-
}
|
|
9870
|
-
}
|
|
9871
|
-
},
|
|
9872
10507
|
"/v1/channels/booking/reviews": {
|
|
9873
10508
|
"get": {
|
|
9874
10509
|
"operationId": "list_booking_reviews",
|
|
@@ -10127,81 +10762,6 @@
|
|
|
10127
10762
|
}
|
|
10128
10763
|
}
|
|
10129
10764
|
},
|
|
10130
|
-
"/v1/channels/vrbo/listings/{id}/pricing": {
|
|
10131
|
-
"get": {
|
|
10132
|
-
"operationId": "getVrboListingPricing",
|
|
10133
|
-
"summary": "Get VRBO pricing (501 \u2014 agency model)",
|
|
10134
|
-
"description": "VRBO uses the agency model \u2014 VRBO PULLS rates from `/api/webhooks/vrbo/listings-xml/rates/{listing}/{unit}` rather than accepting a push API. This endpoint is declared for symmetry with the other channel-pricing routes but currently returns **501 Not Implemented** with a pointer at the public rate URL VRBO consumes. Use `GET /v1/listings/{id}/calendar` (once wired) to inspect the underlying source-of-truth.\n\nWhen the listings-XML rate-builder is ported into this repo, this endpoint will return the parsed rates VRBO sees.",
|
|
10135
|
-
"tags": [
|
|
10136
|
-
"VRBO"
|
|
10137
|
-
],
|
|
10138
|
-
"parameters": [
|
|
10139
|
-
{
|
|
10140
|
-
"name": "id",
|
|
10141
|
-
"in": "path",
|
|
10142
|
-
"required": true,
|
|
10143
|
-
"schema": {
|
|
10144
|
-
"type": "integer"
|
|
10145
|
-
},
|
|
10146
|
-
"description": "Vanio listing ID \u2014 resolved to a VRBO listing/unit via the workspace mapping."
|
|
10147
|
-
}
|
|
10148
|
-
],
|
|
10149
|
-
"responses": {
|
|
10150
|
-
"401": {
|
|
10151
|
-
"$ref": "#/components/responses/Unauthorized"
|
|
10152
|
-
},
|
|
10153
|
-
"404": {
|
|
10154
|
-
"$ref": "#/components/responses/NotFound"
|
|
10155
|
-
},
|
|
10156
|
-
"501": {
|
|
10157
|
-
"description": "Not implemented \u2014 VRBO is agency-model. Response includes the public rate URL VRBO fetches.",
|
|
10158
|
-
"content": {
|
|
10159
|
-
"application/json": {
|
|
10160
|
-
"schema": {
|
|
10161
|
-
"$ref": "#/components/schemas/Error"
|
|
10162
|
-
}
|
|
10163
|
-
}
|
|
10164
|
-
}
|
|
10165
|
-
}
|
|
10166
|
-
}
|
|
10167
|
-
},
|
|
10168
|
-
"put": {
|
|
10169
|
-
"operationId": "updateVrboListingPricing",
|
|
10170
|
-
"summary": "Update VRBO pricing (501 \u2014 no push API exists)",
|
|
10171
|
-
"description": "VRBO has no rate-push API. To change what VRBO sees, update the underlying Vanio calendar/pricing-settings (e.g. `PUT /v1/listings/{id}/calendar` once wired) \u2014 VRBO will pick up the change on its next pull. This endpoint always returns **501** rather than fake-stubbing a successful push the SDK would silently swallow.",
|
|
10172
|
-
"tags": [
|
|
10173
|
-
"VRBO"
|
|
10174
|
-
],
|
|
10175
|
-
"parameters": [
|
|
10176
|
-
{
|
|
10177
|
-
"name": "id",
|
|
10178
|
-
"in": "path",
|
|
10179
|
-
"required": true,
|
|
10180
|
-
"schema": {
|
|
10181
|
-
"type": "integer"
|
|
10182
|
-
}
|
|
10183
|
-
}
|
|
10184
|
-
],
|
|
10185
|
-
"responses": {
|
|
10186
|
-
"401": {
|
|
10187
|
-
"$ref": "#/components/responses/Unauthorized"
|
|
10188
|
-
},
|
|
10189
|
-
"404": {
|
|
10190
|
-
"$ref": "#/components/responses/NotFound"
|
|
10191
|
-
},
|
|
10192
|
-
"501": {
|
|
10193
|
-
"description": "Not implemented \u2014 VRBO accepts no rate pushes. Update the calendar instead.",
|
|
10194
|
-
"content": {
|
|
10195
|
-
"application/json": {
|
|
10196
|
-
"schema": {
|
|
10197
|
-
"$ref": "#/components/schemas/Error"
|
|
10198
|
-
}
|
|
10199
|
-
}
|
|
10200
|
-
}
|
|
10201
|
-
}
|
|
10202
|
-
}
|
|
10203
|
-
}
|
|
10204
|
-
},
|
|
10205
10765
|
"/v1/channels/vrbo/reservations": {
|
|
10206
10766
|
"get": {
|
|
10207
10767
|
"operationId": "list_vrbo_reservations",
|
|
@@ -11084,59 +11644,7 @@
|
|
|
11084
11644
|
}
|
|
11085
11645
|
}
|
|
11086
11646
|
},
|
|
11087
|
-
"/v1/ai": {
|
|
11088
|
-
"post": {
|
|
11089
|
-
"operationId": "create_ai_operation",
|
|
11090
|
-
"summary": "AI operation",
|
|
11091
|
-
"description": "Perform an AI-powered operation.\n\nOperations:\n- `respond-to-guest` \u2014 Generate a contextual guest response\n- `classify-intent` \u2014 Classify the intent of a guest message\n- `generate-listing` \u2014 Generate optimized listing description\n- `review-response` \u2014 Generate a review response\n- `price-suggestion` \u2014 Get AI pricing suggestions",
|
|
11092
|
-
"tags": [
|
|
11093
|
-
"AI"
|
|
11094
|
-
],
|
|
11095
|
-
"requestBody": {
|
|
11096
|
-
"content": {
|
|
11097
|
-
"application/json": {
|
|
11098
|
-
"schema": {
|
|
11099
|
-
"$ref": "#/components/schemas/AIOperation"
|
|
11100
|
-
}
|
|
11101
|
-
}
|
|
11102
|
-
}
|
|
11103
|
-
},
|
|
11104
|
-
"responses": {
|
|
11105
|
-
"200": {
|
|
11106
|
-
"description": "AI response (may be streaming)",
|
|
11107
|
-
"content": {
|
|
11108
|
-
"application/json": {
|
|
11109
|
-
"schema": {
|
|
11110
|
-
"type": "object",
|
|
11111
|
-
"properties": {
|
|
11112
|
-
"result": {
|
|
11113
|
-
"type": "string"
|
|
11114
|
-
},
|
|
11115
|
-
"confidence": {
|
|
11116
|
-
"type": "number"
|
|
11117
|
-
}
|
|
11118
|
-
}
|
|
11119
|
-
}
|
|
11120
|
-
}
|
|
11121
|
-
}
|
|
11122
|
-
}
|
|
11123
|
-
}
|
|
11124
|
-
}
|
|
11125
|
-
},
|
|
11126
11647
|
"/v1/billing": {
|
|
11127
|
-
"get": {
|
|
11128
|
-
"operationId": "get_billing",
|
|
11129
|
-
"summary": "Get plan and usage",
|
|
11130
|
-
"description": "Fetch the current plan, usage counters, and billing-cycle reset date for this workspace. Use this to surface a \"you have used X / Y\" indicator in your dashboard.",
|
|
11131
|
-
"tags": [
|
|
11132
|
-
"Billing"
|
|
11133
|
-
],
|
|
11134
|
-
"responses": {
|
|
11135
|
-
"200": {
|
|
11136
|
-
"description": "Plan info and current usage"
|
|
11137
|
-
}
|
|
11138
|
-
}
|
|
11139
|
-
},
|
|
11140
11648
|
"post": {
|
|
11141
11649
|
"operationId": "create_billing_checkout",
|
|
11142
11650
|
"summary": "Create checkout session",
|
|
@@ -11379,1377 +11887,6 @@
|
|
|
11379
11887
|
}
|
|
11380
11888
|
}
|
|
11381
11889
|
},
|
|
11382
|
-
"/api/studio/projects": {
|
|
11383
|
-
"get": {
|
|
11384
|
-
"summary": "List Studio projects",
|
|
11385
|
-
"description": "Returns every Studio project owned by the authenticated account, excluding soft-deleted ones. Use this to populate a project picker or dashboard.",
|
|
11386
|
-
"operationId": "listStudioProjects",
|
|
11387
|
-
"tags": [
|
|
11388
|
-
"Studio"
|
|
11389
|
-
],
|
|
11390
|
-
"responses": {
|
|
11391
|
-
"200": {
|
|
11392
|
-
"description": "Project list",
|
|
11393
|
-
"content": {
|
|
11394
|
-
"application/json": {
|
|
11395
|
-
"schema": {
|
|
11396
|
-
"type": "object",
|
|
11397
|
-
"properties": {
|
|
11398
|
-
"data": {
|
|
11399
|
-
"type": "array",
|
|
11400
|
-
"items": {
|
|
11401
|
-
"$ref": "#/components/schemas/StudioProject"
|
|
11402
|
-
}
|
|
11403
|
-
}
|
|
11404
|
-
}
|
|
11405
|
-
}
|
|
11406
|
-
}
|
|
11407
|
-
}
|
|
11408
|
-
},
|
|
11409
|
-
"401": {
|
|
11410
|
-
"description": "Unauthorized",
|
|
11411
|
-
"content": {
|
|
11412
|
-
"application/json": {
|
|
11413
|
-
"schema": {
|
|
11414
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11415
|
-
}
|
|
11416
|
-
}
|
|
11417
|
-
}
|
|
11418
|
-
},
|
|
11419
|
-
"500": {
|
|
11420
|
-
"description": "Server error",
|
|
11421
|
-
"content": {
|
|
11422
|
-
"application/json": {
|
|
11423
|
-
"schema": {
|
|
11424
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11425
|
-
}
|
|
11426
|
-
}
|
|
11427
|
-
}
|
|
11428
|
-
}
|
|
11429
|
-
}
|
|
11430
|
-
},
|
|
11431
|
-
"post": {
|
|
11432
|
-
"summary": "Create a Studio project",
|
|
11433
|
-
"description": "Spins up a new Studio project from a name + prompt. Repull AI uses the prompt to materialize the initial template; the returned project starts in `draft` status.",
|
|
11434
|
-
"operationId": "createStudioProject",
|
|
11435
|
-
"tags": [
|
|
11436
|
-
"Studio"
|
|
11437
|
-
],
|
|
11438
|
-
"requestBody": {
|
|
11439
|
-
"required": true,
|
|
11440
|
-
"content": {
|
|
11441
|
-
"application/json": {
|
|
11442
|
-
"schema": {
|
|
11443
|
-
"type": "object",
|
|
11444
|
-
"required": [
|
|
11445
|
-
"name",
|
|
11446
|
-
"prompt"
|
|
11447
|
-
],
|
|
11448
|
-
"properties": {
|
|
11449
|
-
"name": {
|
|
11450
|
-
"type": "string",
|
|
11451
|
-
"description": "Human-readable project name. Used to derive the slug."
|
|
11452
|
-
},
|
|
11453
|
-
"prompt": {
|
|
11454
|
-
"type": "string",
|
|
11455
|
-
"description": "Initial prompt that seeds the project. Repull AI scaffolds the first generation from this."
|
|
11456
|
-
},
|
|
11457
|
-
"template_id": {
|
|
11458
|
-
"type": "string",
|
|
11459
|
-
"nullable": true,
|
|
11460
|
-
"description": "Optional template to start from (e.g. `next-saas`). Omit to generate from prompt only."
|
|
11461
|
-
}
|
|
11462
|
-
}
|
|
11463
|
-
},
|
|
11464
|
-
"examples": {
|
|
11465
|
-
"default": {
|
|
11466
|
-
"value": {
|
|
11467
|
-
"name": "Booking Pulse",
|
|
11468
|
-
"prompt": "A dashboard that surfaces booking velocity by source.",
|
|
11469
|
-
"template_id": "next-saas"
|
|
11470
|
-
}
|
|
11471
|
-
}
|
|
11472
|
-
}
|
|
11473
|
-
}
|
|
11474
|
-
}
|
|
11475
|
-
},
|
|
11476
|
-
"responses": {
|
|
11477
|
-
"201": {
|
|
11478
|
-
"description": "Project created (draft state)",
|
|
11479
|
-
"content": {
|
|
11480
|
-
"application/json": {
|
|
11481
|
-
"schema": {
|
|
11482
|
-
"type": "object",
|
|
11483
|
-
"properties": {
|
|
11484
|
-
"data": {
|
|
11485
|
-
"type": "object",
|
|
11486
|
-
"properties": {
|
|
11487
|
-
"id": {
|
|
11488
|
-
"type": "string",
|
|
11489
|
-
"format": "uuid"
|
|
11490
|
-
},
|
|
11491
|
-
"slug": {
|
|
11492
|
-
"type": "string"
|
|
11493
|
-
},
|
|
11494
|
-
"status": {
|
|
11495
|
-
"type": "string",
|
|
11496
|
-
"enum": [
|
|
11497
|
-
"draft",
|
|
11498
|
-
"building",
|
|
11499
|
-
"live",
|
|
11500
|
-
"archived"
|
|
11501
|
-
]
|
|
11502
|
-
}
|
|
11503
|
-
}
|
|
11504
|
-
}
|
|
11505
|
-
}
|
|
11506
|
-
}
|
|
11507
|
-
}
|
|
11508
|
-
}
|
|
11509
|
-
},
|
|
11510
|
-
"400": {
|
|
11511
|
-
"description": "Invalid request body",
|
|
11512
|
-
"content": {
|
|
11513
|
-
"application/json": {
|
|
11514
|
-
"schema": {
|
|
11515
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11516
|
-
}
|
|
11517
|
-
}
|
|
11518
|
-
}
|
|
11519
|
-
},
|
|
11520
|
-
"401": {
|
|
11521
|
-
"description": "Unauthorized",
|
|
11522
|
-
"content": {
|
|
11523
|
-
"application/json": {
|
|
11524
|
-
"schema": {
|
|
11525
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11526
|
-
}
|
|
11527
|
-
}
|
|
11528
|
-
}
|
|
11529
|
-
},
|
|
11530
|
-
"500": {
|
|
11531
|
-
"description": "Server error",
|
|
11532
|
-
"content": {
|
|
11533
|
-
"application/json": {
|
|
11534
|
-
"schema": {
|
|
11535
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11536
|
-
}
|
|
11537
|
-
}
|
|
11538
|
-
}
|
|
11539
|
-
}
|
|
11540
|
-
}
|
|
11541
|
-
}
|
|
11542
|
-
},
|
|
11543
|
-
"/api/studio/projects/{id}": {
|
|
11544
|
-
"get": {
|
|
11545
|
-
"summary": "Get a Studio project",
|
|
11546
|
-
"description": "Fetches a single Studio project by ID, including its current status and timestamps.",
|
|
11547
|
-
"operationId": "getStudioProject",
|
|
11548
|
-
"tags": [
|
|
11549
|
-
"Studio"
|
|
11550
|
-
],
|
|
11551
|
-
"parameters": [
|
|
11552
|
-
{
|
|
11553
|
-
"name": "id",
|
|
11554
|
-
"in": "path",
|
|
11555
|
-
"required": true,
|
|
11556
|
-
"schema": {
|
|
11557
|
-
"type": "string",
|
|
11558
|
-
"format": "uuid"
|
|
11559
|
-
},
|
|
11560
|
-
"description": "Project UUID."
|
|
11561
|
-
}
|
|
11562
|
-
],
|
|
11563
|
-
"responses": {
|
|
11564
|
-
"200": {
|
|
11565
|
-
"description": "Project",
|
|
11566
|
-
"content": {
|
|
11567
|
-
"application/json": {
|
|
11568
|
-
"schema": {
|
|
11569
|
-
"type": "object",
|
|
11570
|
-
"properties": {
|
|
11571
|
-
"data": {
|
|
11572
|
-
"$ref": "#/components/schemas/StudioProject"
|
|
11573
|
-
}
|
|
11574
|
-
}
|
|
11575
|
-
}
|
|
11576
|
-
}
|
|
11577
|
-
}
|
|
11578
|
-
},
|
|
11579
|
-
"401": {
|
|
11580
|
-
"description": "Unauthorized",
|
|
11581
|
-
"content": {
|
|
11582
|
-
"application/json": {
|
|
11583
|
-
"schema": {
|
|
11584
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11585
|
-
}
|
|
11586
|
-
}
|
|
11587
|
-
}
|
|
11588
|
-
},
|
|
11589
|
-
"404": {
|
|
11590
|
-
"description": "Project not found",
|
|
11591
|
-
"content": {
|
|
11592
|
-
"application/json": {
|
|
11593
|
-
"schema": {
|
|
11594
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11595
|
-
}
|
|
11596
|
-
}
|
|
11597
|
-
}
|
|
11598
|
-
}
|
|
11599
|
-
}
|
|
11600
|
-
},
|
|
11601
|
-
"patch": {
|
|
11602
|
-
"summary": "Update a Studio project",
|
|
11603
|
-
"description": "Updates project metadata. Only the included fields are touched; omit a field to leave it unchanged.",
|
|
11604
|
-
"operationId": "updateStudioProject",
|
|
11605
|
-
"tags": [
|
|
11606
|
-
"Studio"
|
|
11607
|
-
],
|
|
11608
|
-
"parameters": [
|
|
11609
|
-
{
|
|
11610
|
-
"name": "id",
|
|
11611
|
-
"in": "path",
|
|
11612
|
-
"required": true,
|
|
11613
|
-
"schema": {
|
|
11614
|
-
"type": "string",
|
|
11615
|
-
"format": "uuid"
|
|
11616
|
-
}
|
|
11617
|
-
}
|
|
11618
|
-
],
|
|
11619
|
-
"requestBody": {
|
|
11620
|
-
"required": true,
|
|
11621
|
-
"content": {
|
|
11622
|
-
"application/json": {
|
|
11623
|
-
"schema": {
|
|
11624
|
-
"type": "object",
|
|
11625
|
-
"properties": {
|
|
11626
|
-
"name": {
|
|
11627
|
-
"type": "string"
|
|
11628
|
-
},
|
|
11629
|
-
"status": {
|
|
11630
|
-
"type": "string",
|
|
11631
|
-
"enum": [
|
|
11632
|
-
"draft",
|
|
11633
|
-
"building",
|
|
11634
|
-
"live",
|
|
11635
|
-
"archived"
|
|
11636
|
-
]
|
|
11637
|
-
}
|
|
11638
|
-
}
|
|
11639
|
-
},
|
|
11640
|
-
"examples": {
|
|
11641
|
-
"rename": {
|
|
11642
|
-
"value": {
|
|
11643
|
-
"name": "Booking Pulse v2"
|
|
11644
|
-
}
|
|
11645
|
-
}
|
|
11646
|
-
}
|
|
11647
|
-
}
|
|
11648
|
-
}
|
|
11649
|
-
},
|
|
11650
|
-
"responses": {
|
|
11651
|
-
"200": {
|
|
11652
|
-
"description": "Updated project",
|
|
11653
|
-
"content": {
|
|
11654
|
-
"application/json": {
|
|
11655
|
-
"schema": {
|
|
11656
|
-
"type": "object",
|
|
11657
|
-
"properties": {
|
|
11658
|
-
"data": {
|
|
11659
|
-
"$ref": "#/components/schemas/StudioProject"
|
|
11660
|
-
}
|
|
11661
|
-
}
|
|
11662
|
-
}
|
|
11663
|
-
}
|
|
11664
|
-
}
|
|
11665
|
-
},
|
|
11666
|
-
"400": {
|
|
11667
|
-
"description": "Invalid request body",
|
|
11668
|
-
"content": {
|
|
11669
|
-
"application/json": {
|
|
11670
|
-
"schema": {
|
|
11671
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11672
|
-
}
|
|
11673
|
-
}
|
|
11674
|
-
}
|
|
11675
|
-
},
|
|
11676
|
-
"401": {
|
|
11677
|
-
"description": "Unauthorized",
|
|
11678
|
-
"content": {
|
|
11679
|
-
"application/json": {
|
|
11680
|
-
"schema": {
|
|
11681
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11682
|
-
}
|
|
11683
|
-
}
|
|
11684
|
-
}
|
|
11685
|
-
},
|
|
11686
|
-
"404": {
|
|
11687
|
-
"description": "Project not found",
|
|
11688
|
-
"content": {
|
|
11689
|
-
"application/json": {
|
|
11690
|
-
"schema": {
|
|
11691
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11692
|
-
}
|
|
11693
|
-
}
|
|
11694
|
-
}
|
|
11695
|
-
}
|
|
11696
|
-
}
|
|
11697
|
-
},
|
|
11698
|
-
"delete": {
|
|
11699
|
-
"summary": "Delete a Studio project",
|
|
11700
|
-
"description": "Soft-deletes a project. The project is archived and removed from the listing endpoint, but its files and deployments are retained for recovery.",
|
|
11701
|
-
"operationId": "deleteStudioProject",
|
|
11702
|
-
"tags": [
|
|
11703
|
-
"Studio"
|
|
11704
|
-
],
|
|
11705
|
-
"parameters": [
|
|
11706
|
-
{
|
|
11707
|
-
"name": "id",
|
|
11708
|
-
"in": "path",
|
|
11709
|
-
"required": true,
|
|
11710
|
-
"schema": {
|
|
11711
|
-
"type": "string",
|
|
11712
|
-
"format": "uuid"
|
|
11713
|
-
}
|
|
11714
|
-
}
|
|
11715
|
-
],
|
|
11716
|
-
"responses": {
|
|
11717
|
-
"200": {
|
|
11718
|
-
"description": "Project deleted",
|
|
11719
|
-
"content": {
|
|
11720
|
-
"application/json": {
|
|
11721
|
-
"schema": {
|
|
11722
|
-
"type": "object",
|
|
11723
|
-
"properties": {
|
|
11724
|
-
"data": {
|
|
11725
|
-
"type": "object",
|
|
11726
|
-
"properties": {
|
|
11727
|
-
"id": {
|
|
11728
|
-
"type": "string",
|
|
11729
|
-
"format": "uuid"
|
|
11730
|
-
},
|
|
11731
|
-
"deleted": {
|
|
11732
|
-
"type": "boolean"
|
|
11733
|
-
}
|
|
11734
|
-
}
|
|
11735
|
-
}
|
|
11736
|
-
}
|
|
11737
|
-
}
|
|
11738
|
-
}
|
|
11739
|
-
}
|
|
11740
|
-
},
|
|
11741
|
-
"401": {
|
|
11742
|
-
"description": "Unauthorized",
|
|
11743
|
-
"content": {
|
|
11744
|
-
"application/json": {
|
|
11745
|
-
"schema": {
|
|
11746
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11747
|
-
}
|
|
11748
|
-
}
|
|
11749
|
-
}
|
|
11750
|
-
},
|
|
11751
|
-
"404": {
|
|
11752
|
-
"description": "Project not found",
|
|
11753
|
-
"content": {
|
|
11754
|
-
"application/json": {
|
|
11755
|
-
"schema": {
|
|
11756
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11757
|
-
}
|
|
11758
|
-
}
|
|
11759
|
-
}
|
|
11760
|
-
}
|
|
11761
|
-
}
|
|
11762
|
-
}
|
|
11763
|
-
},
|
|
11764
|
-
"/api/studio/projects/{id}/files": {
|
|
11765
|
-
"get": {
|
|
11766
|
-
"summary": "List Studio project files",
|
|
11767
|
-
"description": "Returns every file in the project tree with its content, sha256, and size. Use the digests to detect drift before writing.",
|
|
11768
|
-
"operationId": "listStudioProjectFiles",
|
|
11769
|
-
"tags": [
|
|
11770
|
-
"Studio"
|
|
11771
|
-
],
|
|
11772
|
-
"parameters": [
|
|
11773
|
-
{
|
|
11774
|
-
"name": "id",
|
|
11775
|
-
"in": "path",
|
|
11776
|
-
"required": true,
|
|
11777
|
-
"schema": {
|
|
11778
|
-
"type": "string",
|
|
11779
|
-
"format": "uuid"
|
|
11780
|
-
}
|
|
11781
|
-
}
|
|
11782
|
-
],
|
|
11783
|
-
"responses": {
|
|
11784
|
-
"200": {
|
|
11785
|
-
"description": "File list",
|
|
11786
|
-
"content": {
|
|
11787
|
-
"application/json": {
|
|
11788
|
-
"schema": {
|
|
11789
|
-
"type": "object",
|
|
11790
|
-
"properties": {
|
|
11791
|
-
"data": {
|
|
11792
|
-
"type": "array",
|
|
11793
|
-
"items": {
|
|
11794
|
-
"$ref": "#/components/schemas/StudioFile"
|
|
11795
|
-
}
|
|
11796
|
-
}
|
|
11797
|
-
}
|
|
11798
|
-
}
|
|
11799
|
-
}
|
|
11800
|
-
}
|
|
11801
|
-
},
|
|
11802
|
-
"401": {
|
|
11803
|
-
"description": "Unauthorized",
|
|
11804
|
-
"content": {
|
|
11805
|
-
"application/json": {
|
|
11806
|
-
"schema": {
|
|
11807
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11808
|
-
}
|
|
11809
|
-
}
|
|
11810
|
-
}
|
|
11811
|
-
},
|
|
11812
|
-
"404": {
|
|
11813
|
-
"description": "Project not found",
|
|
11814
|
-
"content": {
|
|
11815
|
-
"application/json": {
|
|
11816
|
-
"schema": {
|
|
11817
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11818
|
-
}
|
|
11819
|
-
}
|
|
11820
|
-
}
|
|
11821
|
-
}
|
|
11822
|
-
}
|
|
11823
|
-
}
|
|
11824
|
-
},
|
|
11825
|
-
"/api/studio/projects/{id}/files/{path}": {
|
|
11826
|
-
"put": {
|
|
11827
|
-
"summary": "Upsert a Studio project file",
|
|
11828
|
-
"description": "Creates or replaces a file at the given path. Returns the new sha256 so subsequent writes can use optimistic concurrency.",
|
|
11829
|
-
"operationId": "upsertStudioProjectFile",
|
|
11830
|
-
"tags": [
|
|
11831
|
-
"Studio"
|
|
11832
|
-
],
|
|
11833
|
-
"parameters": [
|
|
11834
|
-
{
|
|
11835
|
-
"name": "id",
|
|
11836
|
-
"in": "path",
|
|
11837
|
-
"required": true,
|
|
11838
|
-
"schema": {
|
|
11839
|
-
"type": "string",
|
|
11840
|
-
"format": "uuid"
|
|
11841
|
-
}
|
|
11842
|
-
},
|
|
11843
|
-
{
|
|
11844
|
-
"name": "path",
|
|
11845
|
-
"in": "path",
|
|
11846
|
-
"required": true,
|
|
11847
|
-
"schema": {
|
|
11848
|
-
"type": "string"
|
|
11849
|
-
},
|
|
11850
|
-
"description": "URL-encoded project-relative path, e.g. `src%2Fapp%2Fpage.tsx`."
|
|
11851
|
-
}
|
|
11852
|
-
],
|
|
11853
|
-
"requestBody": {
|
|
11854
|
-
"required": true,
|
|
11855
|
-
"content": {
|
|
11856
|
-
"application/json": {
|
|
11857
|
-
"schema": {
|
|
11858
|
-
"type": "object",
|
|
11859
|
-
"required": [
|
|
11860
|
-
"content"
|
|
11861
|
-
],
|
|
11862
|
-
"properties": {
|
|
11863
|
-
"content": {
|
|
11864
|
-
"type": "string",
|
|
11865
|
-
"description": "Full UTF-8 file contents \u2014 partial updates are not supported."
|
|
11866
|
-
}
|
|
11867
|
-
}
|
|
11868
|
-
},
|
|
11869
|
-
"examples": {
|
|
11870
|
-
"default": {
|
|
11871
|
-
"value": {
|
|
11872
|
-
"content": "export default function Page() { return <div>Hello</div> }"
|
|
11873
|
-
}
|
|
11874
|
-
}
|
|
11875
|
-
}
|
|
11876
|
-
}
|
|
11877
|
-
}
|
|
11878
|
-
},
|
|
11879
|
-
"responses": {
|
|
11880
|
-
"200": {
|
|
11881
|
-
"description": "File upserted",
|
|
11882
|
-
"content": {
|
|
11883
|
-
"application/json": {
|
|
11884
|
-
"schema": {
|
|
11885
|
-
"type": "object",
|
|
11886
|
-
"properties": {
|
|
11887
|
-
"data": {
|
|
11888
|
-
"type": "object",
|
|
11889
|
-
"properties": {
|
|
11890
|
-
"sha256": {
|
|
11891
|
-
"type": "string"
|
|
11892
|
-
}
|
|
11893
|
-
}
|
|
11894
|
-
}
|
|
11895
|
-
}
|
|
11896
|
-
}
|
|
11897
|
-
}
|
|
11898
|
-
}
|
|
11899
|
-
},
|
|
11900
|
-
"400": {
|
|
11901
|
-
"description": "Invalid request body",
|
|
11902
|
-
"content": {
|
|
11903
|
-
"application/json": {
|
|
11904
|
-
"schema": {
|
|
11905
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11906
|
-
}
|
|
11907
|
-
}
|
|
11908
|
-
}
|
|
11909
|
-
},
|
|
11910
|
-
"401": {
|
|
11911
|
-
"description": "Unauthorized",
|
|
11912
|
-
"content": {
|
|
11913
|
-
"application/json": {
|
|
11914
|
-
"schema": {
|
|
11915
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11916
|
-
}
|
|
11917
|
-
}
|
|
11918
|
-
}
|
|
11919
|
-
},
|
|
11920
|
-
"404": {
|
|
11921
|
-
"description": "Project not found",
|
|
11922
|
-
"content": {
|
|
11923
|
-
"application/json": {
|
|
11924
|
-
"schema": {
|
|
11925
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11926
|
-
}
|
|
11927
|
-
}
|
|
11928
|
-
}
|
|
11929
|
-
}
|
|
11930
|
-
}
|
|
11931
|
-
},
|
|
11932
|
-
"delete": {
|
|
11933
|
-
"summary": "Delete a Studio project file",
|
|
11934
|
-
"description": "Removes a single file from the project tree. The deployment is not redeployed automatically \u2014 trigger a new deployment to apply the change.",
|
|
11935
|
-
"operationId": "deleteStudioProjectFile",
|
|
11936
|
-
"tags": [
|
|
11937
|
-
"Studio"
|
|
11938
|
-
],
|
|
11939
|
-
"parameters": [
|
|
11940
|
-
{
|
|
11941
|
-
"name": "id",
|
|
11942
|
-
"in": "path",
|
|
11943
|
-
"required": true,
|
|
11944
|
-
"schema": {
|
|
11945
|
-
"type": "string",
|
|
11946
|
-
"format": "uuid"
|
|
11947
|
-
}
|
|
11948
|
-
},
|
|
11949
|
-
{
|
|
11950
|
-
"name": "path",
|
|
11951
|
-
"in": "path",
|
|
11952
|
-
"required": true,
|
|
11953
|
-
"schema": {
|
|
11954
|
-
"type": "string"
|
|
11955
|
-
},
|
|
11956
|
-
"description": "URL-encoded project-relative path."
|
|
11957
|
-
}
|
|
11958
|
-
],
|
|
11959
|
-
"responses": {
|
|
11960
|
-
"200": {
|
|
11961
|
-
"description": "File deleted",
|
|
11962
|
-
"content": {
|
|
11963
|
-
"application/json": {
|
|
11964
|
-
"schema": {
|
|
11965
|
-
"type": "object",
|
|
11966
|
-
"properties": {
|
|
11967
|
-
"data": {
|
|
11968
|
-
"type": "object",
|
|
11969
|
-
"properties": {
|
|
11970
|
-
"path": {
|
|
11971
|
-
"type": "string"
|
|
11972
|
-
},
|
|
11973
|
-
"deleted": {
|
|
11974
|
-
"type": "boolean"
|
|
11975
|
-
}
|
|
11976
|
-
}
|
|
11977
|
-
}
|
|
11978
|
-
}
|
|
11979
|
-
}
|
|
11980
|
-
}
|
|
11981
|
-
}
|
|
11982
|
-
},
|
|
11983
|
-
"401": {
|
|
11984
|
-
"description": "Unauthorized",
|
|
11985
|
-
"content": {
|
|
11986
|
-
"application/json": {
|
|
11987
|
-
"schema": {
|
|
11988
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11989
|
-
}
|
|
11990
|
-
}
|
|
11991
|
-
}
|
|
11992
|
-
},
|
|
11993
|
-
"404": {
|
|
11994
|
-
"description": "Project or file not found",
|
|
11995
|
-
"content": {
|
|
11996
|
-
"application/json": {
|
|
11997
|
-
"schema": {
|
|
11998
|
-
"$ref": "#/components/schemas/StudioError"
|
|
11999
|
-
}
|
|
12000
|
-
}
|
|
12001
|
-
}
|
|
12002
|
-
}
|
|
12003
|
-
}
|
|
12004
|
-
}
|
|
12005
|
-
},
|
|
12006
|
-
"/api/studio/projects/{id}/generations": {
|
|
12007
|
-
"post": {
|
|
12008
|
-
"summary": "Run a Studio generation",
|
|
12009
|
-
"description": "Records a generation run scoped to a single project \u2014 Repull AI takes the prompt, generates the response, and stores it on the project timeline. Use this when you want generation history; for one-shot completions without persistence use `POST /api/studio/generate`.",
|
|
12010
|
-
"operationId": "createStudioProjectGeneration",
|
|
12011
|
-
"tags": [
|
|
12012
|
-
"Studio"
|
|
12013
|
-
],
|
|
12014
|
-
"parameters": [
|
|
12015
|
-
{
|
|
12016
|
-
"name": "id",
|
|
12017
|
-
"in": "path",
|
|
12018
|
-
"required": true,
|
|
12019
|
-
"schema": {
|
|
12020
|
-
"type": "string",
|
|
12021
|
-
"format": "uuid"
|
|
12022
|
-
}
|
|
12023
|
-
}
|
|
12024
|
-
],
|
|
12025
|
-
"requestBody": {
|
|
12026
|
-
"required": true,
|
|
12027
|
-
"content": {
|
|
12028
|
-
"application/json": {
|
|
12029
|
-
"schema": {
|
|
12030
|
-
"type": "object",
|
|
12031
|
-
"required": [
|
|
12032
|
-
"prompt"
|
|
12033
|
-
],
|
|
12034
|
-
"properties": {
|
|
12035
|
-
"prompt": {
|
|
12036
|
-
"type": "string",
|
|
12037
|
-
"description": "Prompt to send to Repull AI."
|
|
12038
|
-
}
|
|
12039
|
-
}
|
|
12040
|
-
},
|
|
12041
|
-
"examples": {
|
|
12042
|
-
"default": {
|
|
12043
|
-
"value": {
|
|
12044
|
-
"prompt": "Add a dark-mode toggle to the header."
|
|
12045
|
-
}
|
|
12046
|
-
}
|
|
12047
|
-
}
|
|
12048
|
-
}
|
|
12049
|
-
}
|
|
12050
|
-
},
|
|
12051
|
-
"responses": {
|
|
12052
|
-
"201": {
|
|
12053
|
-
"description": "Generation recorded",
|
|
12054
|
-
"content": {
|
|
12055
|
-
"application/json": {
|
|
12056
|
-
"schema": {
|
|
12057
|
-
"type": "object",
|
|
12058
|
-
"properties": {
|
|
12059
|
-
"data": {
|
|
12060
|
-
"type": "object",
|
|
12061
|
-
"properties": {
|
|
12062
|
-
"generation_id": {
|
|
12063
|
-
"type": "string",
|
|
12064
|
-
"format": "uuid"
|
|
12065
|
-
},
|
|
12066
|
-
"response": {
|
|
12067
|
-
"type": "string"
|
|
12068
|
-
},
|
|
12069
|
-
"tokens_out": {
|
|
12070
|
-
"type": "integer"
|
|
12071
|
-
}
|
|
12072
|
-
}
|
|
12073
|
-
}
|
|
12074
|
-
}
|
|
12075
|
-
}
|
|
12076
|
-
}
|
|
12077
|
-
}
|
|
12078
|
-
},
|
|
12079
|
-
"400": {
|
|
12080
|
-
"description": "Invalid request body",
|
|
12081
|
-
"content": {
|
|
12082
|
-
"application/json": {
|
|
12083
|
-
"schema": {
|
|
12084
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12085
|
-
}
|
|
12086
|
-
}
|
|
12087
|
-
}
|
|
12088
|
-
},
|
|
12089
|
-
"401": {
|
|
12090
|
-
"description": "Unauthorized",
|
|
12091
|
-
"content": {
|
|
12092
|
-
"application/json": {
|
|
12093
|
-
"schema": {
|
|
12094
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12095
|
-
}
|
|
12096
|
-
}
|
|
12097
|
-
}
|
|
12098
|
-
},
|
|
12099
|
-
"404": {
|
|
12100
|
-
"description": "Project not found",
|
|
12101
|
-
"content": {
|
|
12102
|
-
"application/json": {
|
|
12103
|
-
"schema": {
|
|
12104
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12105
|
-
}
|
|
12106
|
-
}
|
|
12107
|
-
}
|
|
12108
|
-
},
|
|
12109
|
-
"429": {
|
|
12110
|
-
"description": "Rate limit exceeded",
|
|
12111
|
-
"content": {
|
|
12112
|
-
"application/json": {
|
|
12113
|
-
"schema": {
|
|
12114
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12115
|
-
}
|
|
12116
|
-
}
|
|
12117
|
-
},
|
|
12118
|
-
"headers": {
|
|
12119
|
-
"Retry-After": {
|
|
12120
|
-
"schema": {
|
|
12121
|
-
"type": "integer"
|
|
12122
|
-
},
|
|
12123
|
-
"description": "Seconds to wait before retrying."
|
|
12124
|
-
}
|
|
12125
|
-
}
|
|
12126
|
-
}
|
|
12127
|
-
}
|
|
12128
|
-
}
|
|
12129
|
-
},
|
|
12130
|
-
"/api/studio/generate": {
|
|
12131
|
-
"post": {
|
|
12132
|
-
"summary": "Generate text with Repull AI",
|
|
12133
|
-
"description": "Sends a prompt to Repull AI and returns the completion synchronously. This is the single LLM endpoint used by the Studio UI; programmatic clients can use it to drive their own vibe-coding flows. Responses include token accounting, cost-in-micros, and cache/fallback flags. 429s include a `Retry-After` header.",
|
|
12134
|
-
"operationId": "generateStudioCompletion",
|
|
12135
|
-
"tags": [
|
|
12136
|
-
"Studio"
|
|
12137
|
-
],
|
|
12138
|
-
"requestBody": {
|
|
12139
|
-
"required": true,
|
|
12140
|
-
"content": {
|
|
12141
|
-
"application/json": {
|
|
12142
|
-
"schema": {
|
|
12143
|
-
"type": "object",
|
|
12144
|
-
"required": [
|
|
12145
|
-
"project_id",
|
|
12146
|
-
"prompt"
|
|
12147
|
-
],
|
|
12148
|
-
"properties": {
|
|
12149
|
-
"project_id": {
|
|
12150
|
-
"oneOf": [
|
|
12151
|
-
{
|
|
12152
|
-
"type": "string"
|
|
12153
|
-
},
|
|
12154
|
-
{
|
|
12155
|
-
"type": "integer"
|
|
12156
|
-
}
|
|
12157
|
-
],
|
|
12158
|
-
"description": "Project the generation belongs to (used for billing + rate limits)."
|
|
12159
|
-
},
|
|
12160
|
-
"prompt": {
|
|
12161
|
-
"type": "string",
|
|
12162
|
-
"maxLength": 32000,
|
|
12163
|
-
"description": "User prompt. Up to 32,000 characters."
|
|
12164
|
-
},
|
|
12165
|
-
"system_prompt": {
|
|
12166
|
-
"type": "string",
|
|
12167
|
-
"maxLength": 32000,
|
|
12168
|
-
"description": "Optional system prompt to steer the response."
|
|
12169
|
-
},
|
|
12170
|
-
"temperature": {
|
|
12171
|
-
"type": "number",
|
|
12172
|
-
"minimum": 0,
|
|
12173
|
-
"maximum": 2,
|
|
12174
|
-
"description": "Sampling temperature. Defaults to model preset."
|
|
12175
|
-
},
|
|
12176
|
-
"max_tokens": {
|
|
12177
|
-
"type": "integer",
|
|
12178
|
-
"minimum": 1,
|
|
12179
|
-
"maximum": 16384,
|
|
12180
|
-
"description": "Maximum completion tokens."
|
|
12181
|
-
}
|
|
12182
|
-
}
|
|
12183
|
-
},
|
|
12184
|
-
"examples": {
|
|
12185
|
-
"default": {
|
|
12186
|
-
"value": {
|
|
12187
|
-
"project_id": "a1b2c3d4-e5f6-7890-abcd-ef0123456789",
|
|
12188
|
-
"prompt": "Refactor the header to use a sticky position."
|
|
12189
|
-
}
|
|
12190
|
-
}
|
|
12191
|
-
}
|
|
12192
|
-
}
|
|
12193
|
-
}
|
|
12194
|
-
},
|
|
12195
|
-
"responses": {
|
|
12196
|
-
"200": {
|
|
12197
|
-
"description": "Generation result",
|
|
12198
|
-
"content": {
|
|
12199
|
-
"application/json": {
|
|
12200
|
-
"schema": {
|
|
12201
|
-
"type": "object",
|
|
12202
|
-
"properties": {
|
|
12203
|
-
"data": {
|
|
12204
|
-
"type": "object",
|
|
12205
|
-
"properties": {
|
|
12206
|
-
"text": {
|
|
12207
|
-
"type": "string",
|
|
12208
|
-
"description": "Generated completion text."
|
|
12209
|
-
},
|
|
12210
|
-
"generation_id": {
|
|
12211
|
-
"type": "string",
|
|
12212
|
-
"format": "uuid"
|
|
12213
|
-
},
|
|
12214
|
-
"model": {
|
|
12215
|
-
"type": "string",
|
|
12216
|
-
"description": "Model identifier that produced the response."
|
|
12217
|
-
},
|
|
12218
|
-
"tokens_in": {
|
|
12219
|
-
"type": "integer"
|
|
12220
|
-
},
|
|
12221
|
-
"tokens_out": {
|
|
12222
|
-
"type": "integer"
|
|
12223
|
-
},
|
|
12224
|
-
"latency_ms": {
|
|
12225
|
-
"type": "integer"
|
|
12226
|
-
},
|
|
12227
|
-
"cost_usd_micro": {
|
|
12228
|
-
"type": "integer",
|
|
12229
|
-
"description": "Cost in millionths of a USD."
|
|
12230
|
-
},
|
|
12231
|
-
"cached": {
|
|
12232
|
-
"type": "boolean",
|
|
12233
|
-
"description": "True if the response was served from cache."
|
|
12234
|
-
},
|
|
12235
|
-
"fallback": {
|
|
12236
|
-
"type": "boolean",
|
|
12237
|
-
"description": "True if the primary model failed and Repull AI fell back to the secondary."
|
|
12238
|
-
}
|
|
12239
|
-
}
|
|
12240
|
-
}
|
|
12241
|
-
}
|
|
12242
|
-
}
|
|
12243
|
-
}
|
|
12244
|
-
}
|
|
12245
|
-
},
|
|
12246
|
-
"400": {
|
|
12247
|
-
"description": "Invalid request body",
|
|
12248
|
-
"content": {
|
|
12249
|
-
"application/json": {
|
|
12250
|
-
"schema": {
|
|
12251
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12252
|
-
}
|
|
12253
|
-
}
|
|
12254
|
-
}
|
|
12255
|
-
},
|
|
12256
|
-
"401": {
|
|
12257
|
-
"description": "Unauthorized",
|
|
12258
|
-
"content": {
|
|
12259
|
-
"application/json": {
|
|
12260
|
-
"schema": {
|
|
12261
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12262
|
-
}
|
|
12263
|
-
}
|
|
12264
|
-
}
|
|
12265
|
-
},
|
|
12266
|
-
"429": {
|
|
12267
|
-
"description": "Rate limit exceeded",
|
|
12268
|
-
"content": {
|
|
12269
|
-
"application/json": {
|
|
12270
|
-
"schema": {
|
|
12271
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12272
|
-
}
|
|
12273
|
-
}
|
|
12274
|
-
},
|
|
12275
|
-
"headers": {
|
|
12276
|
-
"Retry-After": {
|
|
12277
|
-
"schema": {
|
|
12278
|
-
"type": "integer"
|
|
12279
|
-
},
|
|
12280
|
-
"description": "Seconds to wait before retrying."
|
|
12281
|
-
},
|
|
12282
|
-
"X-RateLimit-Limit": {
|
|
12283
|
-
"schema": {
|
|
12284
|
-
"type": "integer"
|
|
12285
|
-
}
|
|
12286
|
-
},
|
|
12287
|
-
"X-RateLimit-Remaining": {
|
|
12288
|
-
"schema": {
|
|
12289
|
-
"type": "integer"
|
|
12290
|
-
}
|
|
12291
|
-
},
|
|
12292
|
-
"X-RateLimit-Reset": {
|
|
12293
|
-
"schema": {
|
|
12294
|
-
"type": "integer"
|
|
12295
|
-
},
|
|
12296
|
-
"description": "Unix timestamp when the quota resets."
|
|
12297
|
-
}
|
|
12298
|
-
}
|
|
12299
|
-
},
|
|
12300
|
-
"500": {
|
|
12301
|
-
"description": "Server error",
|
|
12302
|
-
"content": {
|
|
12303
|
-
"application/json": {
|
|
12304
|
-
"schema": {
|
|
12305
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12306
|
-
}
|
|
12307
|
-
}
|
|
12308
|
-
}
|
|
12309
|
-
}
|
|
12310
|
-
}
|
|
12311
|
-
}
|
|
12312
|
-
},
|
|
12313
|
-
"/api/studio/deployments": {
|
|
12314
|
-
"get": {
|
|
12315
|
-
"summary": "List Studio deployments",
|
|
12316
|
-
"description": "Returns every deployment across all projects in your account, newest first. Filter by project with `project_id`.",
|
|
12317
|
-
"operationId": "listStudioDeployments",
|
|
12318
|
-
"tags": [
|
|
12319
|
-
"Studio"
|
|
12320
|
-
],
|
|
12321
|
-
"parameters": [
|
|
12322
|
-
{
|
|
12323
|
-
"name": "project_id",
|
|
12324
|
-
"in": "query",
|
|
12325
|
-
"schema": {
|
|
12326
|
-
"type": "string",
|
|
12327
|
-
"format": "uuid"
|
|
12328
|
-
},
|
|
12329
|
-
"description": "Optional \u2014 restrict the list to a single project."
|
|
12330
|
-
},
|
|
12331
|
-
{
|
|
12332
|
-
"name": "status",
|
|
12333
|
-
"in": "query",
|
|
12334
|
-
"schema": {
|
|
12335
|
-
"type": "string",
|
|
12336
|
-
"enum": [
|
|
12337
|
-
"provisioning",
|
|
12338
|
-
"building",
|
|
12339
|
-
"live",
|
|
12340
|
-
"suspended",
|
|
12341
|
-
"failed"
|
|
12342
|
-
]
|
|
12343
|
-
}
|
|
12344
|
-
},
|
|
12345
|
-
{
|
|
12346
|
-
"name": "limit",
|
|
12347
|
-
"in": "query",
|
|
12348
|
-
"schema": {
|
|
12349
|
-
"type": "integer",
|
|
12350
|
-
"default": 50
|
|
12351
|
-
}
|
|
12352
|
-
},
|
|
12353
|
-
{
|
|
12354
|
-
"name": "offset",
|
|
12355
|
-
"in": "query",
|
|
12356
|
-
"schema": {
|
|
12357
|
-
"type": "integer",
|
|
12358
|
-
"default": 0
|
|
12359
|
-
}
|
|
12360
|
-
}
|
|
12361
|
-
],
|
|
12362
|
-
"responses": {
|
|
12363
|
-
"200": {
|
|
12364
|
-
"description": "Deployment list",
|
|
12365
|
-
"content": {
|
|
12366
|
-
"application/json": {
|
|
12367
|
-
"schema": {
|
|
12368
|
-
"type": "object",
|
|
12369
|
-
"properties": {
|
|
12370
|
-
"data": {
|
|
12371
|
-
"type": "array",
|
|
12372
|
-
"items": {
|
|
12373
|
-
"$ref": "#/components/schemas/StudioDeployment"
|
|
12374
|
-
}
|
|
12375
|
-
},
|
|
12376
|
-
"pagination": {
|
|
12377
|
-
"$ref": "#/components/schemas/Pagination"
|
|
12378
|
-
}
|
|
12379
|
-
}
|
|
12380
|
-
}
|
|
12381
|
-
}
|
|
12382
|
-
}
|
|
12383
|
-
},
|
|
12384
|
-
"401": {
|
|
12385
|
-
"description": "Unauthorized",
|
|
12386
|
-
"content": {
|
|
12387
|
-
"application/json": {
|
|
12388
|
-
"schema": {
|
|
12389
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12390
|
-
}
|
|
12391
|
-
}
|
|
12392
|
-
}
|
|
12393
|
-
}
|
|
12394
|
-
}
|
|
12395
|
-
},
|
|
12396
|
-
"post": {
|
|
12397
|
-
"summary": "Trigger a Studio deployment",
|
|
12398
|
-
"description": "Kicks off a new deployment for a project \u2014 Repull provisions a Fly.io machine, writes the subdomain DNS record, and builds the project. The response returns immediately with `provisioning` status; poll `GET /api/studio/deployments/{id}` until `live`.",
|
|
12399
|
-
"operationId": "createStudioDeployment",
|
|
12400
|
-
"tags": [
|
|
12401
|
-
"Studio"
|
|
12402
|
-
],
|
|
12403
|
-
"requestBody": {
|
|
12404
|
-
"required": true,
|
|
12405
|
-
"content": {
|
|
12406
|
-
"application/json": {
|
|
12407
|
-
"schema": {
|
|
12408
|
-
"type": "object",
|
|
12409
|
-
"required": [
|
|
12410
|
-
"project_id"
|
|
12411
|
-
],
|
|
12412
|
-
"properties": {
|
|
12413
|
-
"project_id": {
|
|
12414
|
-
"type": "string",
|
|
12415
|
-
"format": "uuid",
|
|
12416
|
-
"description": "Project to deploy."
|
|
12417
|
-
}
|
|
12418
|
-
}
|
|
12419
|
-
},
|
|
12420
|
-
"examples": {
|
|
12421
|
-
"default": {
|
|
12422
|
-
"value": {
|
|
12423
|
-
"project_id": "a1b2c3d4-e5f6-7890-abcd-ef0123456789"
|
|
12424
|
-
}
|
|
12425
|
-
}
|
|
12426
|
-
}
|
|
12427
|
-
}
|
|
12428
|
-
}
|
|
12429
|
-
},
|
|
12430
|
-
"responses": {
|
|
12431
|
-
"201": {
|
|
12432
|
-
"description": "Deployment queued",
|
|
12433
|
-
"content": {
|
|
12434
|
-
"application/json": {
|
|
12435
|
-
"schema": {
|
|
12436
|
-
"type": "object",
|
|
12437
|
-
"properties": {
|
|
12438
|
-
"data": {
|
|
12439
|
-
"type": "object",
|
|
12440
|
-
"properties": {
|
|
12441
|
-
"deployment_id": {
|
|
12442
|
-
"type": "string",
|
|
12443
|
-
"format": "uuid"
|
|
12444
|
-
},
|
|
12445
|
-
"subdomain": {
|
|
12446
|
-
"type": "string"
|
|
12447
|
-
},
|
|
12448
|
-
"status": {
|
|
12449
|
-
"type": "string",
|
|
12450
|
-
"enum": [
|
|
12451
|
-
"provisioning"
|
|
12452
|
-
]
|
|
12453
|
-
}
|
|
12454
|
-
}
|
|
12455
|
-
}
|
|
12456
|
-
}
|
|
12457
|
-
}
|
|
12458
|
-
}
|
|
12459
|
-
}
|
|
12460
|
-
},
|
|
12461
|
-
"400": {
|
|
12462
|
-
"description": "Invalid request body",
|
|
12463
|
-
"content": {
|
|
12464
|
-
"application/json": {
|
|
12465
|
-
"schema": {
|
|
12466
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12467
|
-
}
|
|
12468
|
-
}
|
|
12469
|
-
}
|
|
12470
|
-
},
|
|
12471
|
-
"401": {
|
|
12472
|
-
"description": "Unauthorized",
|
|
12473
|
-
"content": {
|
|
12474
|
-
"application/json": {
|
|
12475
|
-
"schema": {
|
|
12476
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12477
|
-
}
|
|
12478
|
-
}
|
|
12479
|
-
}
|
|
12480
|
-
},
|
|
12481
|
-
"404": {
|
|
12482
|
-
"description": "Project not found",
|
|
12483
|
-
"content": {
|
|
12484
|
-
"application/json": {
|
|
12485
|
-
"schema": {
|
|
12486
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12487
|
-
}
|
|
12488
|
-
}
|
|
12489
|
-
}
|
|
12490
|
-
}
|
|
12491
|
-
}
|
|
12492
|
-
}
|
|
12493
|
-
},
|
|
12494
|
-
"/api/studio/deployments/{id}": {
|
|
12495
|
-
"get": {
|
|
12496
|
-
"summary": "Get a Studio deployment",
|
|
12497
|
-
"description": "Fetches a single deployment, including its current status and live URL. Poll this endpoint after `POST /api/studio/deployments` until `status` is `live`.",
|
|
12498
|
-
"operationId": "getStudioDeployment",
|
|
12499
|
-
"tags": [
|
|
12500
|
-
"Studio"
|
|
12501
|
-
],
|
|
12502
|
-
"parameters": [
|
|
12503
|
-
{
|
|
12504
|
-
"name": "id",
|
|
12505
|
-
"in": "path",
|
|
12506
|
-
"required": true,
|
|
12507
|
-
"schema": {
|
|
12508
|
-
"type": "string",
|
|
12509
|
-
"format": "uuid"
|
|
12510
|
-
}
|
|
12511
|
-
}
|
|
12512
|
-
],
|
|
12513
|
-
"responses": {
|
|
12514
|
-
"200": {
|
|
12515
|
-
"description": "Deployment",
|
|
12516
|
-
"content": {
|
|
12517
|
-
"application/json": {
|
|
12518
|
-
"schema": {
|
|
12519
|
-
"type": "object",
|
|
12520
|
-
"properties": {
|
|
12521
|
-
"data": {
|
|
12522
|
-
"$ref": "#/components/schemas/StudioDeployment"
|
|
12523
|
-
}
|
|
12524
|
-
}
|
|
12525
|
-
}
|
|
12526
|
-
}
|
|
12527
|
-
}
|
|
12528
|
-
},
|
|
12529
|
-
"401": {
|
|
12530
|
-
"description": "Unauthorized",
|
|
12531
|
-
"content": {
|
|
12532
|
-
"application/json": {
|
|
12533
|
-
"schema": {
|
|
12534
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12535
|
-
}
|
|
12536
|
-
}
|
|
12537
|
-
}
|
|
12538
|
-
},
|
|
12539
|
-
"404": {
|
|
12540
|
-
"description": "Deployment not found",
|
|
12541
|
-
"content": {
|
|
12542
|
-
"application/json": {
|
|
12543
|
-
"schema": {
|
|
12544
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12545
|
-
}
|
|
12546
|
-
}
|
|
12547
|
-
}
|
|
12548
|
-
}
|
|
12549
|
-
}
|
|
12550
|
-
},
|
|
12551
|
-
"delete": {
|
|
12552
|
-
"summary": "Delete a Studio deployment",
|
|
12553
|
-
"description": "Tears down a deployment \u2014 releases the Fly.io machine, removes the DNS record, and marks the deployment as deleted. The underlying project is unaffected.",
|
|
12554
|
-
"operationId": "deleteStudioDeployment",
|
|
12555
|
-
"tags": [
|
|
12556
|
-
"Studio"
|
|
12557
|
-
],
|
|
12558
|
-
"parameters": [
|
|
12559
|
-
{
|
|
12560
|
-
"name": "id",
|
|
12561
|
-
"in": "path",
|
|
12562
|
-
"required": true,
|
|
12563
|
-
"schema": {
|
|
12564
|
-
"type": "string",
|
|
12565
|
-
"format": "uuid"
|
|
12566
|
-
}
|
|
12567
|
-
}
|
|
12568
|
-
],
|
|
12569
|
-
"responses": {
|
|
12570
|
-
"200": {
|
|
12571
|
-
"description": "Deployment deleted",
|
|
12572
|
-
"content": {
|
|
12573
|
-
"application/json": {
|
|
12574
|
-
"schema": {
|
|
12575
|
-
"type": "object",
|
|
12576
|
-
"properties": {
|
|
12577
|
-
"data": {
|
|
12578
|
-
"type": "object",
|
|
12579
|
-
"properties": {
|
|
12580
|
-
"deployment_id": {
|
|
12581
|
-
"type": "string",
|
|
12582
|
-
"format": "uuid"
|
|
12583
|
-
},
|
|
12584
|
-
"deleted": {
|
|
12585
|
-
"type": "boolean"
|
|
12586
|
-
}
|
|
12587
|
-
}
|
|
12588
|
-
}
|
|
12589
|
-
}
|
|
12590
|
-
}
|
|
12591
|
-
}
|
|
12592
|
-
}
|
|
12593
|
-
},
|
|
12594
|
-
"401": {
|
|
12595
|
-
"description": "Unauthorized",
|
|
12596
|
-
"content": {
|
|
12597
|
-
"application/json": {
|
|
12598
|
-
"schema": {
|
|
12599
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12600
|
-
}
|
|
12601
|
-
}
|
|
12602
|
-
}
|
|
12603
|
-
},
|
|
12604
|
-
"404": {
|
|
12605
|
-
"description": "Deployment not found",
|
|
12606
|
-
"content": {
|
|
12607
|
-
"application/json": {
|
|
12608
|
-
"schema": {
|
|
12609
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12610
|
-
}
|
|
12611
|
-
}
|
|
12612
|
-
}
|
|
12613
|
-
}
|
|
12614
|
-
}
|
|
12615
|
-
}
|
|
12616
|
-
},
|
|
12617
|
-
"/api/studio/deployments/{id}/suspend": {
|
|
12618
|
-
"post": {
|
|
12619
|
-
"summary": "Suspend a Studio deployment",
|
|
12620
|
-
"description": "Pauses a deployment without deleting it \u2014 the Fly.io machine is stopped and the URL returns 503 until the deployment is woken. Suspended deployments do not accrue runtime charges.",
|
|
12621
|
-
"operationId": "suspendStudioDeployment",
|
|
12622
|
-
"tags": [
|
|
12623
|
-
"Studio"
|
|
12624
|
-
],
|
|
12625
|
-
"parameters": [
|
|
12626
|
-
{
|
|
12627
|
-
"name": "id",
|
|
12628
|
-
"in": "path",
|
|
12629
|
-
"required": true,
|
|
12630
|
-
"schema": {
|
|
12631
|
-
"type": "string",
|
|
12632
|
-
"format": "uuid"
|
|
12633
|
-
}
|
|
12634
|
-
}
|
|
12635
|
-
],
|
|
12636
|
-
"responses": {
|
|
12637
|
-
"200": {
|
|
12638
|
-
"description": "Deployment suspended",
|
|
12639
|
-
"content": {
|
|
12640
|
-
"application/json": {
|
|
12641
|
-
"schema": {
|
|
12642
|
-
"type": "object",
|
|
12643
|
-
"properties": {
|
|
12644
|
-
"data": {
|
|
12645
|
-
"$ref": "#/components/schemas/StudioDeployment"
|
|
12646
|
-
}
|
|
12647
|
-
}
|
|
12648
|
-
}
|
|
12649
|
-
}
|
|
12650
|
-
}
|
|
12651
|
-
},
|
|
12652
|
-
"401": {
|
|
12653
|
-
"description": "Unauthorized",
|
|
12654
|
-
"content": {
|
|
12655
|
-
"application/json": {
|
|
12656
|
-
"schema": {
|
|
12657
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12658
|
-
}
|
|
12659
|
-
}
|
|
12660
|
-
}
|
|
12661
|
-
},
|
|
12662
|
-
"404": {
|
|
12663
|
-
"description": "Deployment not found",
|
|
12664
|
-
"content": {
|
|
12665
|
-
"application/json": {
|
|
12666
|
-
"schema": {
|
|
12667
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12668
|
-
}
|
|
12669
|
-
}
|
|
12670
|
-
}
|
|
12671
|
-
},
|
|
12672
|
-
"409": {
|
|
12673
|
-
"description": "Deployment is already suspended or in a non-suspendable state",
|
|
12674
|
-
"content": {
|
|
12675
|
-
"application/json": {
|
|
12676
|
-
"schema": {
|
|
12677
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12678
|
-
}
|
|
12679
|
-
}
|
|
12680
|
-
}
|
|
12681
|
-
}
|
|
12682
|
-
}
|
|
12683
|
-
}
|
|
12684
|
-
},
|
|
12685
|
-
"/api/studio/deployments/{id}/wake": {
|
|
12686
|
-
"post": {
|
|
12687
|
-
"summary": "Wake a suspended Studio deployment",
|
|
12688
|
-
"description": "Resumes a previously suspended deployment \u2014 Repull restarts the Fly.io machine and the URL becomes reachable again once `status` returns to `live`.",
|
|
12689
|
-
"operationId": "wakeStudioDeployment",
|
|
12690
|
-
"tags": [
|
|
12691
|
-
"Studio"
|
|
12692
|
-
],
|
|
12693
|
-
"parameters": [
|
|
12694
|
-
{
|
|
12695
|
-
"name": "id",
|
|
12696
|
-
"in": "path",
|
|
12697
|
-
"required": true,
|
|
12698
|
-
"schema": {
|
|
12699
|
-
"type": "string",
|
|
12700
|
-
"format": "uuid"
|
|
12701
|
-
}
|
|
12702
|
-
}
|
|
12703
|
-
],
|
|
12704
|
-
"responses": {
|
|
12705
|
-
"200": {
|
|
12706
|
-
"description": "Deployment waking",
|
|
12707
|
-
"content": {
|
|
12708
|
-
"application/json": {
|
|
12709
|
-
"schema": {
|
|
12710
|
-
"type": "object",
|
|
12711
|
-
"properties": {
|
|
12712
|
-
"data": {
|
|
12713
|
-
"$ref": "#/components/schemas/StudioDeployment"
|
|
12714
|
-
}
|
|
12715
|
-
}
|
|
12716
|
-
}
|
|
12717
|
-
}
|
|
12718
|
-
}
|
|
12719
|
-
},
|
|
12720
|
-
"401": {
|
|
12721
|
-
"description": "Unauthorized",
|
|
12722
|
-
"content": {
|
|
12723
|
-
"application/json": {
|
|
12724
|
-
"schema": {
|
|
12725
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12726
|
-
}
|
|
12727
|
-
}
|
|
12728
|
-
}
|
|
12729
|
-
},
|
|
12730
|
-
"404": {
|
|
12731
|
-
"description": "Deployment not found",
|
|
12732
|
-
"content": {
|
|
12733
|
-
"application/json": {
|
|
12734
|
-
"schema": {
|
|
12735
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12736
|
-
}
|
|
12737
|
-
}
|
|
12738
|
-
}
|
|
12739
|
-
},
|
|
12740
|
-
"409": {
|
|
12741
|
-
"description": "Deployment is not in a suspended state",
|
|
12742
|
-
"content": {
|
|
12743
|
-
"application/json": {
|
|
12744
|
-
"schema": {
|
|
12745
|
-
"$ref": "#/components/schemas/StudioError"
|
|
12746
|
-
}
|
|
12747
|
-
}
|
|
12748
|
-
}
|
|
12749
|
-
}
|
|
12750
|
-
}
|
|
12751
|
-
}
|
|
12752
|
-
},
|
|
12753
11890
|
"/v1/kv": {
|
|
12754
11891
|
"get": {
|
|
12755
11892
|
"operationId": "list_kv",
|