{ "openapi": "3.1.0", "info": { "title": "Uplisting API", "version": "2026-10-02", "description": "Uplisting public API. Two auth methods: legacy API key (HTTP Basic, Base64-encoded key; generate at https://app.uplisting.io/connect/api) and V3 OAuth 2.0 authorization code with PKCE via https://auth.airdna.co. V3 endpoints have no version prefix; V2 endpoints use /v2/ and need the X-Uplisting-Client-Id header. Responses follow JSON:API. Rate limits: 5 req/s and 100 req/min per IP, 15 req/min per property (429 when exceeded). Developer resources: https://uplisting.io/developer", "contact": { "name": "Uplisting partner team", "url": "https://docs.google.com/forms/d/e/1FAIpQLScU_dEV5KWM57YsjzUwbBxl9jnawt7GjP3HmTPWRz41CZz5Qg/viewform" } }, "externalDocs": { "description": "Uplisting developer resources", "url": "https://uplisting.io/developer" }, "servers": [ { "url": "https://connect.uplisting.io" } ], "components": { "securitySchemes": { "legacyApiKey": { "type": "http", "scheme": "basic", "description": "Authorization: Basic . Used for V1/V2 endpoints and webhooks." }, "oauth": { "type": "oauth2", "description": "V3 OAuth. Authorization code with PKCE (S256). Include offline_access for a refresh token.", "flows": { "authorizationCode": { "authorizationUrl": "https://auth.airdna.co/oauth2/authorize", "tokenUrl": "https://auth.airdna.co/oauth2/token", "refreshUrl": "https://auth.airdna.co/oauth2/token", "scopes": { "offline_access": "Issue a refresh token (must be in the first authorise request)", "properties:read": "Read properties and search availability", "properties:write": "Update property fees and discounts", "calendar:read": "Read calendar, rates and restrictions", "calendar:write": "Update calendar", "bookings:read": "Read bookings", "bookings:create": "Create bookings and get quotes", "bookings:update": "Update and cancel bookings, approve or decline booking requests", "reviews:read": "Read reviews", "custom_booking_attributes:read": "List custom booking attribute definitions", "custom_booking_attributes:write": "Create custom booking attribute definitions", "messaging:read": "Read message threads", "messaging:write": "Send messages" } } } } } }, "tags": [ { "name": "Webhook notifications" }, { "name": "v2" }, { "name": "Properties" }, { "name": "Calendar" }, { "name": "Bookings" }, { "name": "Custom booking attributes" }, { "name": "Reviews" }, { "name": "Messaging" }, { "name": "Utility" }, { "name": "Legacy API key" } ], "paths": { "/hooks": { "post": { "summary": "Webhook - Registering Hooks", "tags": [ "Webhook notifications" ], "operationId": "legacy_POST_hooks", "security": [ { "legacyApiKey": [] } ], "responses": { "201": { "description": "Webhook - Registering Hooks", "content": { "application/json": { "example": { "id": 1269 } } } }, "401": { "description": "Unrecognised API key or token" }, "429": { "description": "Rate limit exceeded" } }, "description": "Legacy API key. To receive push notifications when things change in Uplisting, register a webhook against an event. We will `POST` a JSON payload to your `target_url` whenever that event fires.\n\nRegister a hook with `POST https://connect.uplisting.io/hooks` and a body of `{ \"target_url\": \u2026, \"event\": \u2026 }`. The response contains an `id` and a `secret`: **store the secret**, you need it to verify signatures (see below).\n\n**Available events**\n**Bookings**\n\n- `booking_created`: a new booking is imported from a channel or created in Uplisting.\n \n- `booking_updated`: any change to a booking (including price changes and moves).\n \n- `booking_removed`: a booking is cancelled or deleted.\n \n- `booking_cancelled`: a booking is cancelled.\n \n- `booking_request_approved`: a pending booking request is approved.\n \n- `booking_request_declined`: a pending booking request is declined.\n \n\n**Properties**\n\n- `property_created` \u00b7 `property_updated` \u00b7 `property_removed`\n \n\n**Calendar & pricing**\n\n- `prices_changed`: nightly prices or base rates changed.\n \n- `restrictions_changed`: min-length-of-stay / closed-for-arrival / closed-for-departure changed.\n \n- `availability_changed`: availability changed for a date range.\n \n\n**Messaging**\n\n- `message_created`: an inbound or outbound guest message.\n \n\n**Payments**\n\n- `payment_status_changed`: a payment's status changed.\n \n- `payment_refunded`: a payment was refunded.\n \n\n**Reviews**\n\n- `review_created`: a new review was created.\n \n\n**Delivery, envelope & signature verification**\nEach delivery is a `POST` with `Content-Type: application/json` and these headers:\n\n- `X-Uplisting-Timestamp`: Unix time (seconds) when the request was signed.\n \n- `X-Uplisting-Signature`: an HMAC-SHA256 hex digest.\n \n\nThe signature is computed as:\n\n```\nX-Uplisting-Signature = HMAC_SHA256(secret, \".\")\n\n ```\n\nTo verify, recompute the HMAC over the `X-Uplisting-Timestamp` value, a full stop and the raw request body exactly as received, using that hook's `secret`, and compare digests in constant time. The timestamp lets you reject stale/replayed requests.\n\nEvery payload body is **flat**: the event's fields are at the top level, plus two envelope fields added to every event:\n\n- `timestamp`: ISO 8601 string.\n \n- `event_id`: a unique UUID for the delivery (use it to de-duplicate).\n \n\n> Note: the body does **not** contain an `event` field: you know which event fired from the `target_url` you registered for it. \n \n\nA hook is disabled automatically if 5 events in a row fail terminally (all retries used, or a permanent error) with no successful delivery in between.\n\n**Webhook Retries**\nWe `POST` each event to your endpoint and expect a **`2xx`** **response within 5 seconds**. Anything else (a non-`2xx` status, a timeout, or a connection error) is treated as a **failed delivery** and retried.\n\n**Retry schedule**\n\n- Failed deliveries are retried on a **growing backoff**, up to **21 attempts** spanning roughly **8.4 days**.\n \n- Delays start at \\~30 seconds and lengthen with each attempt (a few minutes after the first handful of tries, hours by the end of the window).\n \n- After the final attempt, the event is abandoned.\n \n\n**What is and isn't retried**\n\n| Response at your endpoint | Retried? |\n| --- | --- |\n| `2xx` | Success: no retry |\n| `408 Request Timeout`, `429 Too Many Requests` | Yes |\n| Other `4xx` (`400`, `401`, `403`, `404`, `410`, `422`, \u2026) | No: treated as permanent |\n| `3xx` / `5xx` | Yes |\n| Timeout or connection/TLS/DNS error | Yes |\n\nMost `4xx` client errors are considered permanent (we assume the request will keep failing) so they are **not** retried.\n\n**Deduplication**\n\nEvery retry re-sends the **same** **`event_id`**. Because retries mean your endpoint may receive the same event more than once, **deduplicate on** **`event_id`** and treat delivery as at-least-once.\n\n**Automatic disabling**\n\nIf **5 events fail terminally in a row** (each either exhausting all retries or hitting a permanent error) **with no successful delivery in between**, the subscription is automatically disabled. A single successful delivery resets the counter, so this reflects a sustained outage rather than occasional failures.\n\n**Booking payload**\n`booking_created` and `booking_updated` deliver the full booking payload:\n\n``` json\n{\n \"id\": 1,\n \"slug\": \"abc123\",\n \"guest_name\": \"Jon Snow\",\n \"preferred_guest_name\": \"King of the North\",\n \"guest_email\": \"jon.snow@example.com\",\n \"guest_phone\": \"+441234567890\",\n \"channel\": \"airbnb_official\",\n \"source\": null,\n \"note\": \"Bringing the dragon\",\n \"direct\": false,\n \"automated_messages_enabled\": true,\n \"automated_reviews_enabled\": false,\n \"arrival_time\": \"15:00:00\",\n \"booked_at\": \"2026-07-01T11:19:59Z\",\n \"check_in\": \"2026-07-05\",\n \"check_out\": \"2026-07-08\",\n \"departure_time\": \"11:00:00\",\n \"lock_code\": \"1234\",\n \"manually_moved\": false,\n \"number_of_nights\": 3,\n \"property_name\": \"Mi Casa\",\n \"property_id\": 2,\n \"currency\": \"GBP\",\n \"multi_unit_name\": null,\n \"multi_unit_id\": null,\n \"external_reservation_id\": \"ABC2DEF3YZ\",\n \"number_of_guests\": 3,\n \"cleaning_fee\": 40.0,\n \"extra_guest_charges\": 0.0,\n \"extra_charges\": 0.0,\n \"discounts\": 0.0,\n \"booking_taxes\": 0.0,\n \"commission\": 14.0,\n \"commission_vat\": 0.0,\n \"other_charges\": null,\n \"total_payout\": 388.0,\n \"cancellation_fee\": 0.0,\n \"gross_revenue\": 402.45,\n \"accomodation_total\": 362.45,\n \"accommodation_total\": 362.45,\n \"accommodation_with_commission\": 376.45,\n \"guest_price\": 402.45,\n \"average_price_per_night\": 120.82,\n \"subtotal\": 402.45,\n \"host_edited\": false,\n \"owner_payout\": 340.0,\n \"payment_processing_fee\": 12.45,\n \"net_revenue\": 390.0,\n \"balance\": 0.0,\n \"accommodation_management_fee\": 20.0,\n \"cleaning_management_fee\": 4.0,\n \"total_management_fee\": 48.0,\n \"status\": \"confirmed\",\n \"booking_tax_items\": [\n {\n \"name\": \"City tax\",\n \"amount\": 5.0\n }\n ],\n \"booking_discounts\": [\n {\n \"name\": \"Weekly\",\n \"type\": \"weekly\",\n \"amount\": 10.0\n }\n ],\n \"booking_promotions\": [],\n \"booking_upsells\": [\n {\n \"name\": \"Early check-in\",\n \"type\": \"upsell\",\n \"amount\": 15.0\n }\n ],\n \"booking_adjustments\": [],\n \"booking_fees\": [\n {\n \"name\": \"Cleaning fee\",\n \"type\": \"cleaning_fee\",\n \"amount\": 40.0\n }\n ],\n \"booking_charges\": [],\n \"booking_channel_fees\": [\n {\n \"name\": \"Airbnb host fee\",\n \"type\": \"channel_fee\",\n \"amount\": 14.0\n }\n ],\n \"booking_cancellation_details\": [],\n \"booking_payments\": [\n {\n \"id\": 900,\n \"amount\": 402.45,\n \"currency\": \"GBP\",\n \"status\": \"paid\",\n \"due_at\": \"2026-07-05T00:00:00Z\"\n }\n ],\n \"booking_refunds\": [],\n \"security_deposit\": {\n \"id\": 12,\n \"status\": \"authorized\",\n \"amount\": 200.0,\n \"charged_at\": null,\n \"expires_at\": \"2026-07-09T00:00:00Z\"\n },\n \"timestamp\": \"2026-07-01T11:20:00Z\",\n \"event_id\": \"0f9c2e2a-2b7a-4a1e-9c3d-1b2c3d4e5f60\"\n}\n\n ```\n\nFor `booking_updated` triggered by a status change, the payload additionally includes `previous_status` and `new_status`.\n\nFor `booking_removed`, the payload is a reduced set of the base attributes plus a `reason`:\n\n``` json\n{\n \"id\": 163760,\n \"slug\": \"def456\",\n \"guest_name\": \"Jon Snow\",\n \"channel\": \"uplisting\",\n \"direct\": false,\n \"automated_messages_enabled\": true,\n \"automated_reviews_enabled\": false,\n \"arrival_time\": \"15:00:00\",\n \"booked_at\": \"2026-07-01T12:51:01Z\",\n \"check_in\": \"2026-07-02\",\n \"check_out\": \"2026-07-03\",\n \"departure_time\": \"11:00:00\",\n \"lock_code\": \"1234\",\n \"manually_moved\": false,\n \"number_of_nights\": 1,\n \"property_name\": \"Mi Casa\",\n \"property_id\": 2,\n \"currency\": \"USD\",\n \"number_of_guests\": 2,\n \"reason\": \"cancelled\",\n \"timestamp\": \"2026-07-01T12:52:00Z\",\n \"event_id\": \"1a2b3c4d-5e6f-7081-9203-a4b5c6d7e8f9\"\n}\n\n ```\n\n**Property payload**\n`property_created` / `property_updated` / `property_removed`:\n\n``` json\n{\n \"id\": 12345,\n \"name\": \"Beach House\",\n \"nickname\": \"Mi Casa\",\n \"time_zone\": \"Europe/London\",\n \"timestamp\": \"2026-07-01T12:30:45Z\",\n \"event_id\": \"\\u2026\"\n}\n\n ```\n\n**Message payload**\n`message_created`:\n\n``` json\n{\n \"id\": 789,\n \"channel\": \"airbnb\",\n \"direction\": \"inbound\",\n \"context\": \"conversation\",\n \"body\": \"Hi, what time is check-in?\",\n \"status\": \"received\",\n \"failure_reason\": null,\n \"sender_reference_id\": null,\n \"occasion_type\": \"booking\",\n \"occasion_id\": 1,\n \"property_id\": 2,\n \"property_name\": \"Mi Casa\",\n \"created_at\": \"2026-07-01T12:30:00Z\",\n \"timestamp\": \"2026-07-01T12:30:45Z\",\n \"event_id\": \"\\u2026\"\n}\n\n ```\n\n**Review payload**\n`review_created`:\n\n``` json\n{\n \"id\": 456,\n \"airbnb_review_id\": \"987654\",\n \"channel\": \"airbnb\",\n \"reviewer_role\": \"guest\",\n \"overall_rating\": 5,\n \"review_text\": \"Great stay!\",\n \"review_date\": \"2026-07-01T00:00:00Z\",\n \"booking_id\": 1,\n \"property_id\": 2,\n \"property_name\": \"Mi Casa\",\n \"timestamp\": \"2026-07-01T12:30:45Z\",\n \"event_id\": \"\\u2026\"\n}\n\n ```\n\n**Payment payload**\n`payment_status_changed`:\n\n``` json\n{\n \"id\": 999,\n \"amount\": 1500.5,\n \"currency\": \"USD\",\n \"status\": \"paid\",\n \"previous_status\": \"pending\",\n \"due_at\": \"2026-07-05T00:00:00Z\",\n \"booking_id\": 1,\n \"property_id\": 2,\n \"property_name\": \"Mi Casa\",\n \"timestamp\": \"2026-07-01T12:30:45Z\",\n \"event_id\": \"\\u2026\"\n}\n\n ```\n\n`payment_refunded`:\n\n``` json\n{\n \"payment_id\": 999,\n \"booking_id\": 1,\n \"property_id\": 2,\n \"property_name\": \"Mi Casa\",\n \"amount_refunded\": 500.25,\n \"total_refunded\": 500.25,\n \"payment_amount\": 1500.5,\n \"currency\": \"USD\",\n \"refunded_at\": \"2026-07-01T12:30:45Z\",\n \"timestamp\": \"2026-07-01T12:30:45Z\",\n \"event_id\": \"\\u2026\"\n}\n\n ```\n\n**Rate, restriction & availability payloads**\n`prices_changed` / `restrictions_changed`:\n\n``` json\n{\n \"property_id\": 12345,\n \"property_name\": \"Mi Casa\",\n \"rate_type\": \"price\",\n \"start_date\": \"2026-08-01\",\n \"end_date\": \"2026-08-31\",\n \"timestamp\": \"2026-07-01T12:30:45Z\",\n \"event_id\": \"\\u2026\"\n}\n\n ```\n\n`rate_type` is one of `price`/`base_rate` (for `prices_changed`) or `mlos`/`closed_for_arrival`/`closed_for_departure` (for `restrictions_changed`).\n\n`availability_changed`:\n\n``` json\n{\n \"property_id\": 12345,\n \"property_name\": \"Mi Casa\",\n \"start_date\": \"2026-08-01\",\n \"end_date\": \"2026-08-31\",\n \"timestamp\": \"2026-07-01T12:30:45Z\",\n \"event_id\": \"\\u2026\"\n}\n\n ```", "requestBody": { "content": { "application/json": { "schema": { "type": "object" }, "example": { "target_url": "https://example.com/uplisting/booking-created", "event": "booking_created" } } } } }, "get": { "summary": "Webhooks", "tags": [ "Webhook notifications" ], "operationId": "legacy_GET_hooks", "security": [ { "legacyApiKey": [] } ], "responses": { "200": { "description": "Hooks Index", "content": { "application/json": { "example": { "data": [ { "id": "305", "type": "webhooks", "attributes": { "target_url": "https://example.com/hook/booking_created_2", "event": "booking_created", "created_at": "2020-12-16T11:35:58Z", "updated_at": "2020-12-16T11:35:58Z" } }, { "id": "319", "type": "webhooks", "attributes": { "target_url": "https://example.com/hook/booking_created_4", "event": "booking_created", "created_at": "2020-12-16T14:40:12Z", "updated_at": "2020-12-16T14:40:12Z" } } ] } } } }, "401": { "description": "Unrecognised API key or token" }, "429": { "description": "Rate limit exceeded" } }, "description": "Legacy API key. Retrieving details of registered webhooks\n\nTo retrieve the details for all webhooks registered for a user, you should send a GET request to the endpoint above.\n\nThe payload will be a list of webhooks for the partner account in JSON API format. \n\nFor more info on JSON API format, visit https://jsonapi.org." } }, "/hooks/{id}": { "delete": { "summary": "Webhook - Removing hooks", "tags": [ "Webhook notifications" ], "operationId": "legacy_DELETE_hooks_id", "security": [ { "legacyApiKey": [] } ], "responses": { "200": { "description": "Webhook - Removing hooks", "content": { "application/json": { "example": { "status": "destroyed" } } } }, "401": { "description": "Unrecognised API key or token" }, "429": { "description": "Rate limit exceeded" } }, "description": "Legacy API key. If you wish to remove a hook (e.g. unsubscribe from further events) then send `DELETE` to `https://connect.uplisting.io/hooks/:id` where id is the ID you got back when first registering the hook.", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ] } }, "/hooks/{id}/rotate_secret": { "post": { "summary": "Webhook - Rotate secret", "tags": [ "Webhook notifications" ], "operationId": "legacy_POST_hooks_id_rotate_secret", "security": [ { "legacyApiKey": [] } ], "responses": { "201": { "description": "Success" }, "401": { "description": "Unrecognised API key or token" }, "429": { "description": "Rate limit exceeded" } }, "description": "Legacy API key. Rotate the signing secret for a registered webhook. `POST` to `https://connect.uplisting.io/hooks/:id/rotate_secret` where `:id` is the hook id.\n\nReturns the hook id and its **new** secret:\n\n```json\n{\n \"id\": 123,\n \"secret\": \"\"\n}\n```\n\nUpdate your signature-verification code to use the new secret immediately.", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ] } }, "/v2/custom_booking_attributes": { "get": { "summary": "Custom booking attributes", "tags": [ "v2" ], "operationId": "legacy_GET_v2_custom_booking_attributes", "security": [ { "legacyApiKey": [] } ], "responses": { "200": { "description": "Custom booking attributes", "content": { "application/json": { "example": { "data": [ { "id": "1", "type": "custom_booking_attributes", "attributes": { "name": "lock_code", "description": "A customisable lock code", "created_at": "2022-05-30T14:31:23Z", "updated_at": "2022-05-30T14:31:23Z" } } ] } } } }, "401": { "description": "Unrecognised API key or token" }, "429": { "description": "Rate limit exceeded" } }, "description": "Legacy API key. **Listing booking attributes that can be changed**\n\nThere are only certain attributes that can be changed on any specific booking and those are listed under this endpoint.\n\nThe use case here is to retrieve the list of attributes for a specific account using a host's API key. These can then be mapped to attributes on a partner's side and used with the `PATCH /v2/bookings/:id` endpoint to make changes to the booking.\n\nThese values are then used in Uplisting in automated messaging by replacing special tags used in messaging templates.\n\nNOTE: This endpoint requires a partner client ID in the header under the `X-Uplisting-Client-ID` header. If you don't have a partner client ID, request one with the API access request form: https://docs.google.com/forms/d/e/1FAIpQLScU_dEV5KWM57YsjzUwbBxl9jnawt7GjP3HmTPWRz41CZz5Qg/viewform", "parameters": [ { "name": "X-Uplisting-Client-Id", "in": "header", "required": true, "schema": { "type": "string" }, "description": "Your partner client ID (V2 endpoints)." } ] }, "post": { "summary": "Create custom booking attributes", "tags": [ "v2" ], "operationId": "legacy_POST_v2_custom_booking_attributes", "security": [ { "legacyApiKey": [] } ], "responses": { "201": { "description": "Success" }, "401": { "description": "Unrecognised API key or token" }, "429": { "description": "Rate limit exceeded" } }, "description": "Legacy API key. **Description**\nCreates a new custom booking attribute that can be used to store additional metadata for bookings.\n\nEach attribute is tied to the partner API client that created it and must follow specific naming conventions.\n\n**Constraints**\n- **Maximum:** 15 custom booking attributes per partner per account.\n \n- **Namespace Enforcement:** \n Attribute names must be namespaced (e.g., `partnername_attribute_name`).\n \n- **Naming Convention:** \n Only underscore-style (`snake_case`) names are allowed.\n \n\n**Note:** Partner clients must have their `custom_booking_attribute_prefix` set before they can create custom booking attributes. (Please contact our Partner team on\u00a0[partner@uplisting.io](mailto:partner@uplisting.io) to have that configured)\n\nValues are accepted with an HTTP 201 response.\n\nNOTE: This endpoint requires a partner client ID in the header under the `X-Uplisting-Client-ID` header. If you don't have a partner client ID, request one with the API access request form: https://docs.google.com/forms/d/e/1FAIpQLScU_dEV5KWM57YsjzUwbBxl9jnawt7GjP3HmTPWRz41CZz5Qg/viewform", "parameters": [ { "name": "X-Uplisting-Client-Id", "in": "header", "required": true, "schema": { "type": "string" }, "description": "Your partner client ID (V2 endpoints)." } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object" }, "example": { "data": { "attributes": { "name": "partner_custom_attribute_name", "description": "Describe the custom attribute here" } } } } } } } }, "/v2/bookings/{id}": { "patch": { "summary": "Update booking attributes", "tags": [ "v2" ], "operationId": "legacy_PATCH_v2_bookings_id", "security": [ { "legacyApiKey": [] } ], "responses": { "200": { "description": "Success" }, "401": { "description": "Unrecognised API key or token" }, "429": { "description": "Rate limit exceeded" } }, "description": "Legacy API key. Any attribute listed in the custom booking attributes endpoint can be updated via this endpoint and values set against a specific booking.\n\nAttribute values can be anything that is represented by a string, e.g.\n\n``` json\n{\n \"data\": {\n \"attributes\": {\n \"lock_code\": 1234567\n }\n }\n}\n\n ```\n\nThese attributes can then be used by the host in automated message tags.\n\nValues are accepted with an HTTP 201 response.\n\nNOTE: This endpoint requires a partner client ID in the header under the `X-Uplisting-Client-ID` header. If you don't have a partner client ID, request one with the API access request form: https://docs.google.com/forms/d/e/1FAIpQLScU_dEV5KWM57YsjzUwbBxl9jnawt7GjP3HmTPWRz41CZz5Qg/viewform", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "X-Uplisting-Client-Id", "in": "header", "required": true, "schema": { "type": "string" }, "description": "Your partner client ID (V2 endpoints)." } ] } }, "/v2/bookings": { "post": { "summary": "Create booking", "tags": [ "v2" ], "operationId": "legacy_POST_v2_bookings", "security": [ { "legacyApiKey": [] } ], "responses": { "201": { "description": "Create booking", "content": { "application/json": { "example": { "data": { "id": "165003", "type": "bookings", "attributes": { "check_in": "2022-06-30", "check_out": "2022-07-06", "guest_name": "Jon Snow", "guest_email": "jon@example.com", "guest_phone": "+001122334455", "number_of_guests": 3 }, "relationships": { "property": { "data": { "id": "11780", "type": "properties" } } } } } } } }, "401": { "description": "Unrecognised API key or token" }, "429": { "description": "Rate limit exceeded" } }, "description": "Legacy API key. Endpoint allows creating confirmed bookings and accepts the following attributes:\n\n* `check_in` - required, date in ISO8601 format.\n* `check_out` - required, date in ISO8601 format, date must be after `check_in` date.\n* `property ID` - required.\n \n\nOptional attributes:\n\n* `guest_name` - optional, guest name shown on the booking calendar and used for automated messaging.\n* `guest_email` - optional, a valid email is required for any scheduled messages to be delivered to the guest.\n* `guest_phone` - optional.\n* `number_of_guests` - optional, used for price calculation.\n \n\nNOTE: This endpoint requires a partner client ID in the header under the `X-Uplisting-Client-ID` header. If you don't have a partner client ID, request one with the API access request form: https://docs.google.com/forms/d/e/1FAIpQLScU_dEV5KWM57YsjzUwbBxl9jnawt7GjP3HmTPWRz41CZz5Qg/viewform", "parameters": [ { "name": "X-Uplisting-Client-Id", "in": "header", "required": true, "schema": { "type": "string" }, "description": "Your partner client ID (V2 endpoints)." } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object" }, "example": { "data": { "attributes": { "check_in": "2022-06-30", "check_out": "2022-07-06", "guest_name": "Jon Snow", "guest_email": "jon@example.com", "guest_phone": "+001122334455", "number_of_guests": 3 }, "relationships": { "property": { "data": { "type": "properties", "id": "11780" } } } } } } } } } }, "/properties": { "get": { "summary": "List properties", "tags": [ "Properties" ], "operationId": "oauth_GET_properties", "security": [ { "oauth": [ "properties:read" ] }, { "legacyApiKey": [] } ], "responses": { "200": { "description": "List properties \u2014 200 OK", "content": { "application/json": { "example": { "data": [ { "id": "1024", "type": "properties", "attributes": { "name": "Riverside Loft", "nickname": "Riverside", "currency": "GBP", "time_zone": "Europe/London", "check_in_time": "15:00", "check_out_time": "11:00", "type": "apartment", "maximum_capacity": 4, "bedrooms": 2, "beds": 3, "bathrooms": 1, "bed_types": [ "double", "single" ], "description": "A bright riverside loft with skyline views, moments from the city centre.", "created_at": "2025-03-12T09:24:31Z", "uplisting_domain": "https://riverside.uplisting.io", "property_slug": "riverside-loft" }, "relationships": { "address": { "data": { "type": "addresses", "id": "3201" } }, "photos": { "data": [ { "type": "photos", "id": "58011" }, { "type": "photos", "id": "58012" } ] }, "amenities": { "data": [ { "type": "amenities", "id": "7" }, { "type": "amenities", "id": "42" } ] }, "channels": { "data": [ { "type": "channels", "id": "airbnb_982371" }, { "type": "channels", "id": "booking_com_774512" }, { "type": "channels", "id": "vrbo_55123480" }, { "type": "channels", "id": "direct_riverside-loft" } ] } } } ], "included": [ { "id": "3201", "type": "addresses", "attributes": { "street": "12 Wharf Road", "suite": "Flat 4", "city": "London", "state": "England", "zip_code": "N1 7GR", "country": "GB", "latitude": 51.531, "longitude": -0.0912 } }, { "id": "58011", "type": "photos", "attributes": { "order": 0, "url": "https://d1234uplisting.cloudfront.net/photos/58011.jpg" } }, { "id": "7", "type": "amenities", "attributes": { "name": "Wifi", "group": "Internet & Office" } }, { "id": "airbnb_982371", "type": "channels", "attributes": { "channel": "airbnb", "external_id": "982371", "listing_url": "https://www.airbnb.com/rooms/982371" } }, { "id": "booking_com_774512", "type": "channels", "attributes": { "channel": "booking_com", "external_id": "774512", "listing_url": "https://www.booking.com/hotel/gb/riverside-loft-london.html" } }, { "id": "vrbo_55123480", "type": "channels", "attributes": { "channel": "vrbo", "external_id": "55123480", "listing_url": "https://www.vrbo.com/en-gb/p9284471?dateless=true" } }, { "id": "direct_riverside-loft", "type": "channels", "attributes": { "channel": "direct", "external_id": "riverside-loft", "listing_url": "https://riverside.uplisting.io/london/riverside-loft/riverside-loft" } } ], "meta": { "cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNS0wNS0wMVQxNDoxMDowMFoiLCJpZCI6MTAyNX0=", "has_more": true, "total_count": 2 } } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `properties:read`\n\nList all properties on the account (cursor-paginated, JSON:API).\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `include` | query | string (CSV) | No | Comma-separated relationships to embed. Allowed: `address`, `amenities`, `channel_commissions`, `channels`, `discounts`, `fees`, `multi_units`, `photos`, `policy`, `protect_security_deposit_setting`, `suitability`, `taxes`. Unknown values are ignored. |\n| `limit` | query | integer | No | Page size for cursor pagination. |\n| `cursor` | query | string | No | Opaque cursor from the previous page's `meta`. |\n\n---\nLegacy API key (Properties): **Retrieving details for all properties**\n\nTo retrieve the details for all properties on an Uplisting account, you should send a GET request to the endpoint above.\n\nThe payload will be a list of properties for the partner account in JSON API format. It will also include the property address, photos, multi-units, fees, taxes, discounts, suitabilities and amenities in the included data.\n\n**For a full example of the JSON response, see the property endpoint. This endpoint will return an array of properties with the same format as a single property**\n\nFor more info on JSON API format, visit [https://jsonapi.org](https://jsonapi.org).\n\n**Relationships**\nProperties have relationships which include address, photos, multi-units, fees, taxes, discounts, suitabilities, policies, channel commissions and amenities types. Each individual relationship references the relevant resource in the included section of the API response, per the JSON API format.\n\n**Addresses**\nOur example property's address relationship is provided as follows:\n\n```\n\"address\": {\n \"data\": {\n \"id\": \"15111\",\n \"type\": \"addresses\"\n }\n}\n\n ```\n\nAnd the included data has the relevant address.\n\n```\n{\n \"id\": \"15111\",\n \"type\": \"addresses\",\n \"attributes\": {\n \"street\": \"3503 B Street\",\n \"suite\": null,\n \"city\": \"Philadelphia\",\n \"state\": \"PA\",\n \"zip_code\": \"19134\",\n \"country\": \"United States\",\n \"latitude\": 40.003384,\n \"longitude\": -75.123993\n }\n},\n\n ```\n\n(Trimmed. The full text is in the Postman collection.)", "parameters": [ { "name": "include", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma-separated relationships to embed. Allowed: `address`, `amenities`, `channel_commissions`, `channels`, `discounts`, `fees`, `multi_units`, `photos`, `policy`, `protect_security_deposit_setting`, `suitability`, `taxes`. Unknown values are ignored." }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer" }, "description": "Page size for cursor pagination." }, { "name": "cursor", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Opaque cursor from the previous page's `meta`." } ] } }, "/properties/{id}": { "get": { "summary": "Get property", "tags": [ "Properties" ], "operationId": "oauth_GET_properties_id", "security": [ { "oauth": [ "properties:read" ] }, { "legacyApiKey": [] } ], "responses": { "200": { "description": "Get property \u2014 200 OK", "content": { "application/json": { "example": { "data": { "id": "1024", "type": "properties", "attributes": { "name": "Riverside Loft", "nickname": "Riverside", "currency": "GBP", "time_zone": "Europe/London", "check_in_time": "15:00", "check_out_time": "11:00", "type": "apartment", "maximum_capacity": 4, "bedrooms": 2, "beds": 3, "bathrooms": 1, "bed_types": [ "double", "single" ], "description": "A bright riverside loft with skyline views, moments from the city centre.", "created_at": "2025-03-12T09:24:31Z", "uplisting_domain": "https://riverside.uplisting.io", "property_slug": "riverside-loft" }, "relationships": { "address": { "data": { "type": "addresses", "id": "3201" } }, "photos": { "data": [ { "type": "photos", "id": "58011" } ] }, "amenities": { "data": [ { "type": "amenities", "id": "42" } ] } } }, "included": [ { "id": "3201", "type": "addresses", "attributes": { "street": "12 Wharf Road", "suite": "Flat 4", "city": "London", "state": "England", "zip_code": "N1 7GR", "country": "GB", "latitude": 51.531, "longitude": -0.0912 } }, { "id": "42", "type": "amenities", "attributes": { "name": "Tennis", "group": "Outdoor Features" } } ] } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `properties:read`\n\nFetch a single property by ID.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `id` | path | integer | Yes | Property ID. |\n| `include` | query | string (CSV) | No | Comma-separated relationships to embed. Allowed: `address`, `amenities`, `channel_commissions`, `channels`, `discounts`, `fees`, `multi_units`, `photos`, `policy`, `protect_security_deposit_setting`, `suitability`, `taxes`. Unknown values are ignored. |\n\n---\nLegacy API key (Property): **Retrieving details for a single property**\n\nTo retrieve the details for a property on an Uplisting account, you should send a GET request to the endpoint above.\n\nThe payload will be a single property for the partner account in JSON API format. It will also include the property's address, photos, multi-unit, fees, taxes, suitabilities, channel commissions and amenities in the included data.\n\nFor more info on JSON API format, visit [https://jsonapi.org](https://jsonapi.org).\n\n**Relationships**\nProperties have relationships which include address, photos, multi-unit, fees, taxes, suitabilities and amenities types. Each individual relationship references the relevant resource in the included section of the API response, per the JSON API format.\n\nFor a full breakdown, review the documentation for the `GET /properties` endpoint", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Property ID." }, { "name": "include", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma-separated relationships to embed. Allowed: `address`, `amenities`, `channel_commissions`, `channels`, `discounts`, `fees`, `multi_units`, `photos`, `policy`, `protect_security_deposit_setting`, `suitability`, `taxes`. Unknown values are ignored." } ] } }, "/availability": { "get": { "summary": "Search availability", "tags": [ "Properties" ], "operationId": "oauth_GET_availability", "security": [ { "oauth": [ "properties:read" ] }, { "legacyApiKey": [] } ], "responses": { "200": { "description": "Search availability \u2014 200 OK", "content": { "application/json": { "example": { "data": [ { "id": "1024", "type": "properties", "attributes": { "name": "Riverside Loft", "nickname": "Riverside", "currency": "GBP", "time_zone": "Europe/London", "check_in_time": "15:00", "check_out_time": "11:00", "type": "apartment", "maximum_capacity": 4, "bedrooms": 2, "beds": 3, "bathrooms": 1, "bed_types": [ "double", "single" ], "description": "A bright riverside loft with skyline views, moments from the city centre.", "created_at": "2025-03-12T09:24:31Z", "uplisting_domain": "https://riverside.uplisting.io", "property_slug": "riverside-loft" }, "relationships": { "address": { "data": { "type": "addresses", "id": "3201" } }, "photos": { "data": [ { "type": "photos", "id": "58011" } ] }, "amenities": { "data": [ { "type": "amenities", "id": "7" } ] } } } ], "included": [ { "id": "3201", "type": "addresses", "attributes": { "street": "12 Wharf Road", "suite": "Flat 4", "city": "London", "state": "England", "zip_code": "N1 7GR", "country": "GB", "latitude": 51.531, "longitude": -0.0912 } }, { "id": "58011", "type": "photos", "attributes": { "order": 0, "url": "https://d1234uplisting.cloudfront.net/photos/58011.jpg" } }, { "id": "7", "type": "amenities", "attributes": { "name": "Wifi", "group": "Internet & Office" } } ] } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `properties:read`\n\nSearch available properties by date range, guest count, price and city.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `check_in` | query | date (YYYY-MM-DD) | No | Cannot be earlier than yesterday. |\n| `check_out` | query | date (YYYY-MM-DD) | No | Must be after `check_in`. |\n| `number_of_guests` | query | integer | No | |\n| `min_price` | query | integer | No | Minimum nightly price; must be less than `max_price`. |\n| `max_price` | query | integer | No | Maximum nightly price; must be greater than `min_price`. |\n| `city` | query | string | No | |\n\n---\nLegacy API key (Availability): **Retrieving availability for properties**\n\nTo retrieve the availability of properties on an Uplisting account, you should send a GET request to the endpoint above.\n\nThe payload will be a list of properties that meet the search criteria entered in the query string, in JSON API format. It will also include the property addresses, photos and amenities in the included data. (for a fuller explanation, see the properties endpoint)\n\n**Search criteria**\n\nYou can choose to search by any, or all, of these criteria via the query string on the request.\n\n1. `check_in` - the date of check in.\n2. `check_out` - the date of check out (note this is the _morning_ of check out)\n3. `number_of_guests` - the number of guests for the booking\n4. `max_price` - the maximum price allowed for the booking\n5. `min_price` - the minimum price expected for a booking\n6. `city` - scope the properties by a specific city location", "parameters": [ { "name": "check_in", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Cannot be earlier than yesterday." }, { "name": "check_out", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Must be after `check_in`." }, { "name": "number_of_guests", "in": "query", "required": false, "schema": { "type": "integer" } }, { "name": "min_price", "in": "query", "required": false, "schema": { "type": "integer" }, "description": "Minimum nightly price; must be less than `max_price`." }, { "name": "max_price", "in": "query", "required": false, "schema": { "type": "integer" }, "description": "Maximum nightly price; must be greater than `min_price`." }, { "name": "city", "in": "query", "required": false, "schema": { "type": "string" } } ] } }, "/property_fees/{property_id}": { "patch": { "summary": "Update property fees", "tags": [ "Properties" ], "operationId": "oauth_PATCH_property_fees_property_id", "security": [ { "oauth": [ "properties:write" ] } ], "responses": { "200": { "description": "Update property fees \u2014 200 OK", "content": { "application/json": { "example": { "data": [ { "id": "501-cleaning_fee", "type": "property_fees", "attributes": { "name": "Cleaning fee", "label": "cleaning_fee", "enabled": null, "guests_included": null, "amount": 45.0 } }, { "id": "501-extra_guest_charge", "type": "property_fees", "attributes": { "name": "Extra guest charge", "label": "extra_guest_charge", "enabled": true, "guests_included": 3, "amount": 12.0 } } ] } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `properties:write`\n\nBulk-update property fees. The `id` is the composite resource id returned on the property.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `property_id` | path | integer | Yes | Property ID. |\n| `data` | body | array of objects | Yes | JSON:API resource array. |\n| `data[].type` | body | string | Yes | Fee type. Allowed: `cleaning_fee`, `extra_guest_charge`. |\n| `data[].id` | body | string | Yes | Composite fee resource id. |\n| `data[].attributes.amount` | body | decimal | No | |\n| `data[].attributes.enabled` | body | boolean | No | |\n| `data[].attributes.guests_included` | body | integer | No | |", "parameters": [ { "name": "property_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Property ID." } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object" }, "example": { "data": [ { "type": "property_fees", "id": "123-cleaning_fee", "attributes": { "amount": 45.0, "enabled": true, "guests_included": 2 } }, { "type": "property_fees", "id": "123-extra_guest_charge", "attributes": { "amount": 20.0, "enabled": true, "guests_included": 1 } } ] } } } } } }, "/property_discounts/{property_id}": { "patch": { "summary": "Update property discounts", "tags": [ "Properties" ], "operationId": "oauth_PATCH_property_discounts_property_id", "security": [ { "oauth": [ "properties:write" ] } ], "responses": { "200": { "description": "Update property discounts \u2014 200 OK", "content": { "application/json": { "example": { "data": [ { "id": "501-weekly", "type": "property_discounts", "attributes": { "name": "Weekly discount", "label": "weekly", "type": null, "days": 7, "amount": 15.0 } }, { "id": "501-monthly", "type": "property_discounts", "attributes": { "name": "Monthly discount", "label": "monthly", "type": null, "days": 28, "amount": 25.0 } } ] } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `properties:write`\n\nBulk-update property length-of-stay discounts.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `property_id` | path | integer | Yes | Property ID. |\n| `data` | body | array of objects | Yes | JSON:API resource array. |\n| `data[].type` | body | string | Yes | Discount type. Allowed: `weekly`, `monthly`. |\n| `data[].id` | body | string | Yes | Composite discount resource id. |\n| `data[].attributes.amount` | body | decimal | Yes | |", "parameters": [ { "name": "property_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Property ID." } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object" }, "example": { "data": [ { "type": "property_discounts", "id": "123-weekly", "attributes": { "amount": 10.0 } }, { "type": "property_discounts", "id": "123-monthly", "attributes": { "amount": 25.0 } } ] } } } } } }, "/calendar/{property_id}": { "get": { "summary": "Get calendar", "tags": [ "Calendar" ], "operationId": "oauth_GET_calendar_property_id", "security": [ { "oauth": [ "calendar:read" ] }, { "legacyApiKey": [] } ], "responses": { "200": { "description": "Get calendar \u2014 200 OK", "content": { "application/json": { "example": { "data": { "id": "1024", "type": "calendars", "attributes": { "from": "2026-06-15", "to": "2026-06-17" }, "relationships": { "days": { "data": [ { "type": "calendar_days", "id": "2026-06-15" }, { "type": "calendar_days", "id": "2026-06-16" } ] } } }, "included": [ { "id": "2026-06-15", "type": "calendar_days", "attributes": { "date": "2026-06-15", "available": true, "available_count": 1, "day_rate": 100.0, "minimum_length_of_stay": 1, "maximum_available_nights": 365, "closed_for_arrival": false, "closed_for_departure": false } }, { "id": "2026-06-16", "type": "calendar_days", "attributes": { "date": "2026-06-16", "available": false, "available_count": 0, "day_rate": 100.0, "minimum_length_of_stay": 2, "maximum_available_nights": 0, "closed_for_arrival": false, "closed_for_departure": false } } ] } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `calendar:read`\n\nGet per-day availability and rates for a property.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `property_id` | path | integer | Yes | Property ID. |\n| `from` | query | date (YYYY-MM-DD) | No | Range start. Defaults to today. |\n| `to` | query | date (YYYY-MM-DD) | No | Range end. Defaults to `from` + 1 year; clamped to at most 730 days after `from`. |\n\n---\nLegacy API key (Calendar): To retrieve the calendar for a property, you should GET to the above endpoint.\n\nThe response is limited to 12 months at one time.\n\n**Date range options**\n\n- Specify neither `from` or `to` and get a year from today \n `https://connect.uplisting.io/calendar/:listing_id`\n \n- Specify a `from` only to get 12 months worth of data from that point \n `https://connect.uplisting.io/calendar/:listing_id?from=2020-02-01`\n \n- Specify `from` and `to` and get up up to 12 months worth of data within that date range\n \n- `https://connect.uplisting.io/calendar/:listing_id?from=2020-02-01&to=2021-12-01`\n \n\n**Response**\nIncluded in the response is the price, and restrictions such as availability, minimum length of stay and closed for arrival, e.g:\n\n```\n\"available\": true,\n\"available_count\": 1,\n\"date\": \"2020-12-10\",\n\"day_rate\": 150,\n\"minimum_length_of_stay\": 5,\n\"maximum_available_nights\": 15,\n\"closed_for_arrival\": false,\n\"closed_for_departure\": false\n\n ```\n\n`available`: this is a simple true/false as to whether the property is available on the date listed.\n\n`available_count`: this indicates how many properties are available on that date. It will be 1 unless a property has multi-units attached to it. For multi-units, it indicates how many units are available on that date.\n\n`date`: the day the details are for\n\n`day_rate`: the price (in the property's currency)\n\n`minimum_length_of_stay`: The minimum length for any booking that starts on this date.\n\n(Trimmed. The full text is in the Postman collection.)", "parameters": [ { "name": "property_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Property ID." }, { "name": "from", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Range start. Defaults to today." }, { "name": "to", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Range end. Defaults to `from` + 1 year; clamped to at most 730 days after `from`." } ] }, "patch": { "summary": "Update calendar", "tags": [ "Calendar" ], "operationId": "oauth_PATCH_calendar_property_id", "security": [ { "oauth": [ "calendar:write" ] } ], "responses": { "202": { "description": "Update calendar \u2014 202 Accepted", "content": { "application/json": { "example": { "request_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301" } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `calendar:write`\n\nBulk-update availability and rates. Each `calendar_days` entry uses either a single `date` **or** a `from`/`to` range. Returns **202 Accepted** with a `request_id`.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n| --- | --- | --- | --- | --- |\n| `property_id` | path | integer | Yes | Property ID. |\n| `data.type` | body | string | No | If present, must equal `\"calendars\"`. |\n| `data.attributes.notification_url` | body | string (URL) | No | Must be HTTPS. Receives async completion notification. |\n| `data.attributes.calendar_days` | body | array | Yes | Max 1095 entries. |\n| `calendar_days[].date` | body | date (YYYY-MM-DD) | No | Single day; mutually exclusive with `from`/`to`. |\n| `calendar_days[].from` | body | date (YYYY-MM-DD) | No | Range start; use with `to`. |\n| `calendar_days[].to` | body | date (YYYY-MM-DD) | No | Range end; use with `from`. |\n| `calendar_days[].available` | body | boolean | No | |\n| `calendar_days[].description` | body | string | No | Only valid together with `available: false`. Max 255 characters. Shown on the calendar for the blocked day(s), replacing the default \"Marked unavailable via API\" label. |\n| `calendar_days[].day_rate` | body | decimal | No | Must be greater than 0. |\n| `calendar_days[].minimum_length_of_stay` | body | integer | No | Must be greater than 0. |\n| `calendar_days[].closed_for_arrival` | body | boolean | No | |\n| `calendar_days[].closed_for_departure` | body | boolean | No | |", "parameters": [ { "name": "property_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Property ID." } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object" }, "example": { "data": { "type": "calendars", "attributes": { "notification_url": "https://example.com/calendar-webhook", "calendar_days": [ { "date": "2026-08-01", "available": true, "day_rate": 150.0, "minimum_length_of_stay": 2, "closed_for_arrival": false, "closed_for_departure": false }, { "from": "2026-08-02", "to": "2026-08-07", "available": true, "day_rate": 175.0 } ] } } } } } } }, "post": { "summary": "Update calendar", "tags": [ "Legacy API key" ], "operationId": "legacy_POST_calendar_property_id", "security": [ { "legacyApiKey": [] } ], "responses": { "202": { "description": "Update calendar", "content": { "application/json": { "example": { "request_id": "6a20706e-cd4e-4fe2-a40a-caae48b474a5" } } } }, "401": { "description": "Unrecognised API key or token" }, "429": { "description": "Rate limit exceeded" } }, "description": "Legacy API key. Uplisting provides calendar-based endpoints for updating rates, availability and minimum length of stay for a specific date range. Any updates made via the API are broadcast to all channels the property is connected to on Uplisting.\n\n**Notification**\n\nThis POST results in an asynchronous response to the server listed at the notification_url with a payload indicating success/failure of the changes requested and including that request ID so the response can be matched to the initial POST.\n\nThe notification URL is not required. If no URL is provided, no notifications will be sent.\n\nWe recommend using ngrok ([https://ngrok.com](https://ngrok.com)) to create a publicly accessible URL that tunnels back to your development server for testing purposes. They have a free tier that will enable you to test the Uplisting API.\n\n**Delay**\n\nThe changes received in the payload to this POST call are not applied immediately to the property. Instead, the payload is scheduled for processing by Uplisting and will be applied to the property asynchronously. The payload contains a notification_url that is used to provide a response to the partner indicating success or failure of the relevant updates.\n\nThis delay is typically less than 1 minute.\n\n**Note**\n\n- If the property ID is not part of the account specified by the API key, the notification URL will not receive a response.\n \n- If the payload is considered invalid, the response will be `400 Bad Request` with human readable errors indicating why the payload is considered invalid.\n \n- The date the rate, availability, MLOS update can either be a single day, specified as `date` or as a date range using `from` and `to`. Note that the night of the to date is always excluded, as it\u2019s considered the morning only. So, to include a range _including_ all nights from `2020-12-01` to the night of `2020-12-10`, the to should be set to `2020-12-11`.\n \n- All attributes can be set for up to 3 years in advance. **Any dates before \u201ctoday\u201d in UTC will be ignored**.\n \n- Availability is specified either as `true` if the property can be booked or `false` if the property is not available to be booked. The availability specified here is for the night of the date specified, or as above to the night before the `to` date.\n \n- The rate for the date, or date range, is specified in the currency of the property that is set on Uplisting. It should be a \u201ccommission-free\u201d rate as appropriate markup will be applied to this rate when syncing prices to connected channels.\n \n- `available`, `minimum_length_of_stay`, `day_rate`, `closed_for_arrival,` and `closed_for_departure` are all optional attributes, meaning you can set a rate and/or availability and/or minimum length of stay and/or closed for arrival and departure restrictions.\n \n- Any other attributes added to the payload will be ignored.\n \n\n**Notification URL response**\n\nThe notification URL is specified by the partner and can have any valid format. It must be an HTTPS endpoint.\n\nA Base64 encoded partner API key will be included in the `HTTP_AUTHORIZATION` header to confirm that the response is from Uplisting.\n\nThe response will be a list of the correctly applied rate and/or availability and/or MLOS as listed below:\n\n`{ \"request_id\": \"fe845d4e-9fa2-4f85-b6ee-680d7f97803e\" \"calendar\": { \"days\": [ { \"available\": true, \"day_rate\": 66, \"date\": \"2019-12-20\", \"minimum_length_of_stay\":1, \"closed_for_arrival\": false, \"closed_for_departure\": true }, { \"available\": false, \"from\": \"2019-12-31\", \"to\": \"2020-01-31\" } ] } }`", "parameters": [ { "name": "property_id", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object" }, "example": { "notification_url": "https://yourdomain.eu.ngrok.io/notification", "calendar": { "days": [ { "available": true, "date": "2020-12-13", "day_rate": 170.0, "minimum_length_of_stay": 2, "closed_for_arrival": false, "closed_for_departure": true }, { "available": false, "from": "2021-01-01", "to": "2021-02-01" } ] } } } } } } }, "/bookings": { "get": { "summary": "List bookings", "tags": [ "Bookings" ], "operationId": "oauth_GET_bookings", "security": [ { "oauth": [ "bookings:read" ] } ], "responses": { "200": { "description": "List bookings \u2014 200 OK", "content": { "application/json": { "example": { "data": [ { "id": "48210", "type": "bookings", "attributes": { "slug": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "preferred_guest_name": "King of the North", "guest_email": "jon.snow@example.com", "guest_phone": "+44797978889991", "channel": "airbnb_official", "source": "airbnb_official", "note": null, "direct": false, "automated_messages_enabled": true, "automated_reviews_enabled": true, "guest_name": "Jon Snow", "arrival_time": "14:00:00", "departure_time": "08:00:00", "booked_at": "2026-06-10T09:24:11Z", "cancelled_dt": null, "check_in": "2026-07-01", "check_out": "2026-07-05", "lock_code": null, "manually_moved": false, "number_of_nights": 4, "property_name": "Seaside Apartment", "property_id": 3391, "multi_unit_name": null, "multi_unit_id": null, "external_reservation_id": "HMABCDEFGH", "stripe_customer_id": null, "currency": "GBP", "number_of_guests": 2, "accommodation_total": 480.0, "accommodation_with_commission": 480.0, "cleaning_fee": 45.0, "extra_guest_charges": 0, "extra_charges": 0, "discounts": 0, "booking_taxes": 0, "commission": 72.0, "commission_vat": 0, "other_charges": 0, "total_payout": 453.0, "cancellation_fee": 0, "gross_revenue": 525.0, "accommodation_management_fee": 0, "cleaning_management_fee": 0, "total_management_fee": 0, "owner_payout": 453.0, "payment_processing_fee": 0, "net_revenue": 453.0, "balance": 0, "guest_price": 525.0, "average_price_per_night": 120.0, "subtotal": 525.0, "host_edited": false, "status": "confirmed" } } ], "meta": { "cursor": null, "has_more": false, "total_count": 1 } } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `bookings:read`\n\nList bookings for a property (cursor-paginated). Returns base booking attributes; to retrieve a booking's financial breakdown, use **Get booking** with `include`.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `property_id` | query | integer | Yes | Property whose bookings to list. |\n| `from` | query | date (YYYY-MM-DD) | No | Range start. Defaults to today. |\n| `to` | query | date (YYYY-MM-DD) | No | Range end. Defaults to `from` + 1 year. |\n| `limit` | query | integer | No | Page size for cursor pagination. |\n| `cursor` | query | string | No | Opaque cursor from the previous page's `meta`. |", "parameters": [ { "name": "property_id", "in": "query", "required": true, "schema": { "type": "integer" }, "description": "Property whose bookings to list." }, { "name": "from", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Range start. Defaults to today." }, { "name": "to", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Range end. Defaults to `from` + 1 year." }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer" }, "description": "Page size for cursor pagination." }, { "name": "cursor", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Opaque cursor from the previous page's `meta`." } ] }, "post": { "summary": "Create booking", "tags": [ "Bookings" ], "operationId": "oauth_POST_bookings", "security": [ { "oauth": [ "bookings:create" ] } ], "responses": { "201": { "description": "Create booking \u2014 201 Created", "content": { "application/json": { "example": { "data": { "id": "48211", "type": "bookings", "attributes": { "slug": "f9e8d7c6-b5a4-4938-8271-6f5e4d3c2b1a", "preferred_guest_name": null, "guest_email": "jon.snow@example.com", "guest_phone": "+441234567890", "channel": "uplisting", "source": "uplisting", "note": null, "direct": false, "automated_messages_enabled": true, "automated_reviews_enabled": true, "guest_name": "Jon Snow", "arrival_time": "", "departure_time": "", "booked_at": "2026-06-01T00:00:00Z", "cancelled_dt": null, "check_in": "2026-08-01", "check_out": "2026-08-05", "lock_code": null, "manually_moved": false, "number_of_nights": 4, "property_name": "Seaside Apartment", "property_id": 3391, "multi_unit_name": null, "multi_unit_id": null, "external_reservation_id": null, "stripe_customer_id": null, "currency": "GBP", "number_of_guests": 2, "accommodation_total": 480.0, "accommodation_with_commission": 480.0, "cleaning_fee": 45.0, "extra_guest_charges": 0, "extra_charges": 0, "discounts": 0, "booking_taxes": 0, "commission": 0, "commission_vat": 0, "other_charges": 0, "total_payout": 525.0, "cancellation_fee": 0, "gross_revenue": 525.0, "accommodation_management_fee": 0, "cleaning_management_fee": 0, "total_management_fee": 0, "owner_payout": 525.0, "payment_processing_fee": 0, "net_revenue": 525.0, "balance": 0, "guest_price": 525.0, "average_price_per_night": 120.0, "subtotal": 525.0, "host_edited": false, "status": "confirmed" } } } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `bookings:create`\n\nCreate a booking on a property (JSON:API). Returns **201**.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n| --- | --- | --- | --- | --- |\n| `data.attributes.check_in` | body | date (YYYY-MM-DD) | Yes | |\n| `data.attributes.check_out` | body | date (YYYY-MM-DD) | Yes | |\n| `data.attributes.arrival_time` | body | string (HH:MM) | No | Optionally `HH:MM:SS`, 24-hour. Defaults to the property's check-in time if omitted. |\n| `data.attributes.departure_time` | body | string (HH:MM) | No | Optionally `HH:MM:SS`, 24-hour. Defaults to the property's check-out time if omitted. |\n| `data.attributes.guest_name` | body | string | No | |\n| `data.attributes.guest_phone` | body | string | No | |\n| `data.attributes.guest_email` | body | string | No | |\n| `data.attributes.number_of_guests` | body | integer | No | |\n| `data.attributes.status` | body | string | No | Allowed: `pending`, `confirmed`. Defaults to `pending`. |\n| `data.relationships.property.data.id` | body | integer | Yes | Target property ID. |", "requestBody": { "content": { "application/json": { "schema": { "type": "object" }, "example": { "data": { "attributes": { "check_in": "2026-08-01", "check_out": "2026-08-05", "guest_name": "Jon Snow", "guest_email": "jon.snow@example.com", "guest_phone": "+441234567890", "number_of_guests": 2, "status": "confirmed" }, "relationships": { "property": { "data": { "id": 123 } } } } } } } } } }, "/bookings/{id}": { "get": { "summary": "Get booking", "tags": [ "Bookings" ], "operationId": "oauth_GET_bookings_id", "security": [ { "oauth": [ "bookings:read" ] }, { "legacyApiKey": [] } ], "responses": { "200": { "description": "Get booking \u2014 200 OK", "content": { "application/json": { "example": { "data": { "id": "48210", "type": "bookings", "attributes": { "slug": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "preferred_guest_name": null, "guest_email": "jon.snow@example.com", "guest_phone": "+44797978889991", "channel": "airbnb_official", "source": "airbnb_official", "note": null, "direct": false, "automated_messages_enabled": true, "automated_reviews_enabled": true, "guest_name": "Jon Snow", "arrival_time": "14:00:00", "departure_time": "08:00:00", "booked_at": "2026-06-10T09:24:11Z", "cancelled_dt": null, "check_in": "2026-07-01", "check_out": "2026-07-05", "lock_code": null, "manually_moved": false, "number_of_nights": 4, "property_name": "Seaside Apartment", "property_id": 3391, "multi_unit_name": null, "multi_unit_id": null, "external_reservation_id": "HMABCDEFGH", "stripe_customer_id": "cus_Qabc123XYZ", "currency": "GBP", "number_of_guests": 2, "accommodation_total": 480.0, "accommodation_with_commission": 480.0, "cleaning_fee": 45.0, "extra_guest_charges": 0, "extra_charges": 0, "discounts": 0, "booking_taxes": 24.0, "commission": 72.0, "commission_vat": 0, "other_charges": 0, "total_payout": 453.0, "cancellation_fee": 0, "gross_revenue": 549.0, "accommodation_management_fee": 0, "cleaning_management_fee": 0, "total_management_fee": 0, "owner_payout": 453.0, "payment_processing_fee": 0, "net_revenue": 453.0, "balance": 0, "guest_price": 549.0, "average_price_per_night": 120.0, "subtotal": 525.0, "host_edited": false, "status": "confirmed" }, "relationships": { "booking_tax_items": { "data": [ { "id": "48210-tax-0", "type": "booking_tax_items" } ] }, "booking_discounts": { "data": [] }, "booking_promotions": { "data": [] }, "booking_upsells": { "data": [ { "id": "48210-upsell-771", "type": "booking_upsells" } ] }, "booking_adjustments": { "data": [ { "id": "48210-adjustment-902", "type": "booking_adjustments" } ] }, "booking_fees": { "data": [ { "id": "48210-fee-0", "type": "booking_fees" } ] }, "booking_charges": { "data": [ { "id": "48210-charge-0", "type": "booking_charges" } ] }, "booking_channel_fees": { "data": [ { "id": "48210-channel-fee-0", "type": "booking_channel_fees" } ] }, "booking_cancellation_details": { "data": [] }, "booking_payments": { "data": [ { "id": "15501", "type": "booking_payments" } ] }, "booking_refunds": { "data": [ { "id": "6602", "type": "booking_refunds" } ] }, "security_deposit": { "data": { "id": "3301", "type": "security_deposits" } } } }, "included": [ { "id": "48210-tax-0", "type": "booking_tax_items", "attributes": { "name": "VAT", "amount": 24.0 } }, { "id": "48210-upsell-771", "type": "booking_upsells", "attributes": { "name": "Early check-in", "type": "upsell", "amount": 30.0 } }, { "id": "48210-adjustment-902", "type": "booking_adjustments", "attributes": { "type": "credit", "note": "Compensation for late check-in", "amount": 25.0 } }, { "id": "48210-fee-0", "type": "booking_fees", "attributes": { "name": "Cleaning fee", "type": "cleaning", "amount": 45.0 } }, { "id": "48210-charge-0", "type": "booking_charges", "attributes": { "name": "Accommodation", "type": "accommodation", "amount": 480.0 } }, { "id": "48210-channel-fee-0", "type": "booking_channel_fees", "attributes": { "name": "Host service fee", "type": "channel_host_fee", "amount": 72.0 } }, { "id": "15501", "type": "booking_payments", "attributes": { "currency": "GBP", "status": "charged", "amount": 200.0, "due_at": "2026-06-30T10:00:00Z" } }, { "id": "6602", "type": "booking_refunds", "attributes": { "amount": 50.0 } }, { "id": "3301", "type": "security_deposits", "attributes": { "status": "authorized", "amount": 250.0, "charged_at": null, "expires_at": "2026-07-06T11:00:00Z" } } ] } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `bookings:read`\n\nFetch a single booking.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `id` | path | integer | Yes | Booking ID. |\n| `include` | query | string (CSV) | No | Comma-separated financial relationships to embed. Allowed: `booking_tax_items`, `booking_discounts`, `booking_promotions`, `booking_upsells`, `booking_adjustments`, `booking_fees`, `booking_charges`, `booking_channel_fees`, `booking_cancellation_details`, `booking_payments`, `booking_refunds`, `security_deposit`. Unknown values are ignored. |\n\n---\nLegacy API key (Bookings): To retrieve the bookings for a property, you should GET the above endpoint.\n\nThe response is limited to a maximum of 50 bookings at a time but is paginated so more bookings can be retrieved, as required.\n\n**Date range options**\n\n- Specify neither `from` or `to` and get a year from today (UTC based) \n `https://connect.uplisting.io/bookings/:listing_id`\n- Specify a `from` only to get 12 months worth of data from that point \n `https://connect.uplisting.io/bookings/:listing_id?from=2020-02-01`\n- Specify `from` and `to` and get paginated bookings within that date range\n- `https://connect.uplisting.io/bookings/:listing_id?from=2020-02-01&to=2021-12-01`\n \n\n**Pagination options**\n\n- Specify `page=X` to get a 0-based page of results.\n- Specify `per_page=X` to retrieve less than the default of 50 in each page\n- There's `meta` information included in the response that tells you `total` bookings and `total_pages` so you can paginate through as required.\n \n\n**Booking statuses** \nBookings can have the following statuses.\n\n(Trimmed. The full text is in the Postman collection.)", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Booking ID." }, { "name": "include", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma-separated financial relationships to embed. Allowed: `booking_tax_items`, `booking_discounts`, `booking_promotions`, `booking_upsells`, `booking_adjustments`, `booking_fees`, `booking_charges`, `booking_channel_fees`, `booking_cancellation_details`, `booking_payments`, `booking_refunds`, `security_deposit`. Unknown values are ignored." }, { "name": "from", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Legacy API key only. " }, { "name": "to", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Legacy API key only. " } ] }, "patch": { "summary": "Update booking", "tags": [ "Bookings" ], "operationId": "oauth_PATCH_bookings_id", "security": [ { "oauth": [ "bookings:update" ] } ], "responses": { "200": { "description": "Update booking \u2014 200 OK", "content": { "application/json": { "example": { "data": { "id": "48210", "type": "bookings", "attributes": { "slug": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "preferred_guest_name": null, "guest_email": "jon@example.com", "guest_phone": "+447900000000", "channel": "uplisting", "source": "uplisting", "note": "Updated note", "direct": false, "automated_messages_enabled": true, "automated_reviews_enabled": true, "guest_name": "Jon Snow", "arrival_time": "", "departure_time": "", "booked_at": "2026-06-10T09:24:11Z", "cancelled_dt": null, "check_in": "2026-07-01", "check_out": "2026-07-05", "lock_code": null, "manually_moved": false, "number_of_nights": 4, "property_name": "Seaside Apartment", "property_id": 3391, "multi_unit_name": null, "multi_unit_id": null, "external_reservation_id": null, "stripe_customer_id": null, "currency": "GBP", "number_of_guests": 3, "accommodation_total": 480.0, "accommodation_with_commission": 480.0, "cleaning_fee": 45.0, "extra_guest_charges": 0, "extra_charges": 0, "discounts": 0, "booking_taxes": 0, "commission": 0, "commission_vat": 0, "other_charges": 0, "total_payout": 525.0, "cancellation_fee": 0, "gross_revenue": 525.0, "accommodation_management_fee": 0, "cleaning_management_fee": 0, "total_management_fee": 0, "owner_payout": 525.0, "payment_processing_fee": 0, "net_revenue": 525.0, "balance": 0, "guest_price": 525.0, "average_price_per_night": 120.0, "subtotal": 525.0, "host_edited": false, "status": "confirmed" } } } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `bookings:update`\n\nUpdate an existing booking's attributes (JSON:API). Editable fields include `check_in`, `check_out`, `guest_name`, `guest_email`, `guest_phone`, `number_of_guests`, `status`, `note`, `arrival_time`, `departure_time`. New dates must be available, times must match `HH:MM` (optionally `HH:MM:SS`, 24-hour), and status transitions must be valid.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n| --- | --- | --- | --- | --- |\n| `id` | path | integer | Yes | Booking ID. |\n| `data.attributes` | body | object | Yes | Non-empty hash of fields to update. |", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Booking ID." } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object" }, "example": { "data": { "attributes": { "number_of_guests": 3, "note": "Late arrival", "status": "confirmed" } } } } } } } }, "/bookings/{id}/cancellation": { "post": { "summary": "Cancel booking", "tags": [ "Bookings" ], "operationId": "oauth_POST_bookings_id_cancellation", "security": [ { "oauth": [ "bookings:update" ] } ], "responses": { "200": { "description": "Cancel booking \u2014 200 OK", "content": { "application/json": { "example": { "data": { "id": "48210", "type": "bookings", "attributes": { "slug": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "preferred_guest_name": null, "guest_email": "jon@example.com", "guest_phone": null, "channel": "uplisting", "source": "uplisting", "note": null, "direct": false, "automated_messages_enabled": true, "automated_reviews_enabled": true, "guest_name": "Jon Snow", "arrival_time": "", "departure_time": "", "booked_at": "2026-06-10T09:24:11Z", "cancelled_dt": "2026-06-15T12:00:00Z", "check_in": "2026-07-01", "check_out": "2026-07-05", "lock_code": null, "manually_moved": false, "number_of_nights": 4, "property_name": "Seaside Apartment", "property_id": 3391, "multi_unit_name": null, "multi_unit_id": null, "external_reservation_id": null, "stripe_customer_id": null, "currency": "GBP", "number_of_guests": 2, "accommodation_total": 480.0, "accommodation_with_commission": 480.0, "cleaning_fee": 45.0, "extra_guest_charges": 0, "extra_charges": 0, "discounts": 0, "booking_taxes": 0, "commission": 0, "commission_vat": 0, "other_charges": 0, "total_payout": 0, "cancellation_fee": 0, "gross_revenue": 525.0, "accommodation_management_fee": 0, "cleaning_management_fee": 0, "total_management_fee": 0, "owner_payout": 0, "payment_processing_fee": 0, "net_revenue": 0, "balance": 0, "guest_price": 525.0, "average_price_per_night": 120.0, "subtotal": 525.0, "host_edited": false, "status": "cancelled" } } } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `bookings:update`\n\nCancel a booking. No request body.\n\nNote: Cancelling a booking does not automatically issue a refund to the guest. It only changes the booking's status to cancelled. Any refund must be handled separately.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n| --- | --- | --- | --- | --- |\n| `id` | path | integer | Yes | Booking ID. |", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Booking ID." } ] } }, "/quotes": { "get": { "summary": "Get quote", "tags": [ "Bookings" ], "operationId": "oauth_GET_quotes", "security": [ { "oauth": [ "bookings:create" ] } ], "responses": { "200": { "description": "Get quote \u2014 200 OK", "content": { "application/json": { "example": { "data": { "id": "5f3a1c9e-2b7d-4e6a-9f8c-1d0e2b3a4c5d", "type": "quotes", "attributes": { "property_id": 3391, "check_in": "2026-08-01", "check_out": "2026-08-06", "number_of_nights": 5, "number_of_guests": 2, "currency": "GBP", "has_promotions": false, "promotion_code_invalid": false, "security_deposit": { "amount": 0.0, "waiver_amount": 0.0 }, "nightly_rates": [ { "date": "2026-08-01", "amount": 120.0 }, { "date": "2026-08-02", "amount": 120.0 }, { "date": "2026-08-03", "amount": 120.0 }, { "date": "2026-08-04", "amount": 120.0 }, { "date": "2026-08-05", "amount": 120.0 } ], "average_price_per_night": 120.0, "cleaning_fee": 45.0, "extra_guest_charge": 0, "accommodation_total": 600.0, "total": 645.0 }, "relationships": { "booking_tax_items": { "data": [] }, "booking_fees": { "data": [ { "id": "5f3a1c9e-2b7d-4e6a-9f8c-1d0e2b3a4c5d-fee-0", "type": "booking_fees" } ] }, "booking_charges": { "data": [ { "id": "5f3a1c9e-2b7d-4e6a-9f8c-1d0e2b3a4c5d-charge-0", "type": "booking_charges" } ] }, "booking_discounts": { "data": [] }, "booking_promotions": { "data": [] } } } } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `bookings:create`\n\nGenerate a price quote for a prospective stay.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `property_id` | query | integer | Yes | |\n| `check_in` | query | date (YYYY-MM-DD) | Yes | |\n| `check_out` | query | date (YYYY-MM-DD) | Yes | |\n| `number_of_guests` | query | integer | Yes | Must be greater than 0. |\n| `promotion_code` | query | string | No | Optional promotion code to apply. |", "parameters": [ { "name": "property_id", "in": "query", "required": true, "schema": { "type": "integer" } }, { "name": "check_in", "in": "query", "required": true, "schema": { "type": "string" } }, { "name": "check_out", "in": "query", "required": true, "schema": { "type": "string" } }, { "name": "number_of_guests", "in": "query", "required": true, "schema": { "type": "integer" }, "description": "Must be greater than 0." }, { "name": "promotion_code", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Optional promotion code to apply." } ] } }, "/booking_requests/{id}": { "patch": { "summary": "Approve/decline booking request", "tags": [ "Bookings" ], "operationId": "oauth_PATCH_booking_requests_id", "security": [ { "oauth": [ "bookings:update" ] } ], "responses": { "200": { "description": "Approve/decline booking request \u2014 200 OK", "content": { "application/json": { "example": { "data": { "id": "7742", "type": "booking_requests", "attributes": { "channel": "uplisting", "status": "approved", "slug": "c1d2e3f4-a5b6-4778-89ab-cdef01234567", "guest_name": "Jon Snow", "guest_email": "jon@example.com", "guest_phone": null, "number_of_guests": 2, "rejection_reason": null, "rejection_message": null, "check_in": "2026-07-01", "check_out": "2026-07-05", "number_of_nights": 4, "property_id": 3391, "multi_unit_id": 812, "booking_id": 48212, "created_at": "2026-06-12T08:15:00Z", "expires_at": "2026-06-13T08:15:00Z", "external_reservation_id": null } } } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `bookings:update`\n\nApprove or decline a pending booking request.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `id` | path | integer | Yes | Booking request ID. |\n| `data.attributes.status` | body | string | Yes | Allowed: `approved`, `rejected`. |\n| `data.attributes.reason` | body | string | No | Optional decline reason. |\n| `data.attributes.message` | body | string | No | Optional message to the guest. |", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Booking request ID." } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object" }, "example": { "data": { "attributes": { "status": "approved", "reason": null, "message": "See you soon!" } } } } } } } }, "/custom_booking_attributes": { "get": { "summary": "List custom booking attributes", "tags": [ "Custom booking attributes" ], "operationId": "oauth_GET_custom_booking_attributes", "security": [ { "oauth": [ "custom_booking_attributes:read" ] } ], "responses": { "200": { "description": "List custom booking attributes \u2014 200 OK", "content": { "application/json": { "example": { "data": [ { "id": "3001", "type": "custom_booking_attributes", "attributes": { "name": "acme_lock_code", "description": "Lock code", "created_at": "2026-06-15T12:00:00Z", "updated_at": "2026-06-15T12:00:00Z" } }, { "id": "3002", "type": "custom_booking_attributes", "attributes": { "name": "acme_client_status", "description": "Client status", "created_at": "2026-06-15T12:00:00Z", "updated_at": "2026-06-15T12:00:00Z" } } ], "meta": { "cursor": null, "has_more": false, "total_count": 2 } } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `custom_booking_attributes:read`\n\nList the custom booking attributes defined for your partner integration. No parameters." }, "post": { "summary": "Create custom booking attribute", "tags": [ "Custom booking attributes" ], "operationId": "oauth_POST_custom_booking_attributes", "security": [ { "oauth": [ "custom_booking_attributes:write" ] } ], "responses": { "201": { "description": "Create custom booking attribute \u2014 201 Created", "content": { "application/json": { "example": { "data": { "id": "3003", "type": "custom_booking_attributes", "attributes": { "name": "acme_channel_ref", "description": "Partner channel reference", "created_at": "2026-06-15T12:00:00Z", "updated_at": "2026-06-15T12:00:00Z" } } } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `custom_booking_attributes:write`\n\nCreate a custom booking attribute. Returns **201**.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `data.attributes.name` | body | string | Yes | snake_case; must start with your partner prefix. Max 15 attributes per account. |\n| `data.attributes.description` | body | string | Yes | |", "requestBody": { "content": { "application/json": { "schema": { "type": "object" }, "example": { "data": { "attributes": { "name": "acme_channel_ref", "description": "Partner channel reference" } } } } } } } }, "/reviews/{property_id}": { "get": { "summary": "List reviews", "tags": [ "Reviews" ], "operationId": "oauth_GET_reviews_property_id", "security": [ { "oauth": [ "reviews:read" ] } ], "responses": { "200": { "description": "List reviews \u2014 200 OK", "content": { "application/json": { "example": { "data": [ { "id": "90", "type": "reviews", "attributes": { "confirmation_code": "HMABCDEFGH", "reviewer_name": "Jane Guest", "reviewer_id": 555, "reviewer_role": "guest", "property_id": 501, "airbnb_listing_id": 111, "overall_rating": 4, "category_ratings": [ { "rating": 5, "category": "cleanliness", "review_category_tags": [] }, { "rating": 4, "category": "accuracy", "review_category_tags": [] }, { "rating": 3, "category": "checkin", "review_category_tags": [] } ], "airbnb_review_id": 90, "review_text": "Wonderful stay, would book again.", "review_date": "2026-06-15T12:00:00Z" } } ], "meta": { "cursor": null, "has_more": false, "total_count": 1 } } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `reviews:read`\n\nList reviews for a property (cursor-paginated).\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `property_id` | path | integer | Yes | Property ID. |\n| `limit` | query | integer | No | Page size for cursor pagination. |\n| `cursor` | query | string | No | Opaque cursor from the previous page's `meta`. |", "parameters": [ { "name": "property_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Property ID." }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer" }, "description": "Page size for cursor pagination." }, { "name": "cursor", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Opaque cursor from the previous page's `meta`." } ] } }, "/threads": { "get": { "summary": "List threads", "tags": [ "Messaging" ], "operationId": "oauth_GET_threads", "security": [ { "oauth": [ "messaging:read" ] } ], "responses": { "200": { "description": "List threads \u2014 200 OK", "content": { "application/json": { "example": { "data": [ { "id": "7003", "type": "threads", "attributes": { "channel": "sms", "unread": true, "content": "Hello there", "last_message_at": "2026-06-14T09:00:00Z" }, "relationships": { "booking": { "data": null }, "booking_request": { "data": null }, "enquiry": { "data": { "type": "enquiries", "id": "8003" } }, "property": { "data": { "type": "properties", "id": "501" } } } }, { "id": "7001", "type": "threads", "attributes": { "channel": "airbnb", "unread": true, "content": "What time is check-in?", "last_message_at": "2026-06-10T09:00:00Z" }, "relationships": { "booking": { "data": { "type": "bookings", "id": "8001" } }, "booking_request": { "data": null }, "enquiry": { "data": null }, "property": { "data": { "type": "properties", "id": "501" } } } } ], "meta": { "cursor": null, "has_more": false, "total_count": 2, "unread_count": 2 } } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `messaging:read`\n\nList message threads (cursor-paginated). All filters are optional. The `channel` field is one of: `sms`, `email`, `airbnb`, `booking_dot_com`, `home_away`.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `booking_id` | query | integer | No | Filter by booking. |\n| `booking_request_id` | query | integer | No | Filter by booking request. |\n| `enquiry_id` | query | integer | No | Filter by enquiry. |\n| `property_id` | query | integer | No | Filter by property. |\n| `guest_id` | query | integer | No | Filter by guest. |\n| `limit` | query | integer | No | Page size for cursor pagination. |\n| `cursor` | query | string | No | Opaque cursor from the previous page's `meta`. |", "parameters": [ { "name": "booking_id", "in": "query", "required": false, "schema": { "type": "integer" }, "description": "Filter by booking." }, { "name": "booking_request_id", "in": "query", "required": false, "schema": { "type": "integer" }, "description": "Filter by booking request." }, { "name": "enquiry_id", "in": "query", "required": false, "schema": { "type": "integer" }, "description": "Filter by enquiry." }, { "name": "property_id", "in": "query", "required": false, "schema": { "type": "integer" }, "description": "Filter by property." }, { "name": "guest_id", "in": "query", "required": false, "schema": { "type": "integer" }, "description": "Filter by guest." }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer" }, "description": "Page size for cursor pagination." }, { "name": "cursor", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Opaque cursor from the previous page's `meta`." } ] } }, "/threads/{id}/messages": { "get": { "summary": "Get thread messages", "tags": [ "Messaging" ], "operationId": "oauth_GET_threads_id_messages", "security": [ { "oauth": [ "messaging:read" ] } ], "responses": { "200": { "description": "Get thread messages \u2014 200 OK", "content": { "application/json": { "example": { "data": [ { "id": "9003", "type": "messages", "attributes": { "body": "Check-in is from 3pm.", "channel": "airbnb", "direction": "outbound", "sender_reference_id": "+447700900123", "status": "delivered", "failure_reason": null, "translated_body": null, "language": "en", "timestamp": "2026-06-13T10:00:00Z" } }, { "id": "9001", "type": "messages", "attributes": { "body": "What time is check-in?", "channel": "airbnb", "direction": "inbound", "sender_reference_id": null, "status": null, "failure_reason": null, "translated_body": null, "language": null, "timestamp": "2026-06-13T08:00:00Z" } } ], "meta": { "cursor": null, "has_more": false, "total_count": 2 } } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `messaging:read`\n\nList messages in a thread (cursor-paginated). The `channel` field is one of: `sms`, `email`, `airbnb`, `booking_dot_com`, `home_away`.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `id` | path | integer | Yes | Thread ID. |\n| `limit` | query | integer | No | Page size for cursor pagination. |\n| `cursor` | query | string | No | Opaque cursor from the previous page's `meta`. |", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Thread ID." }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer" }, "description": "Page size for cursor pagination." }, { "name": "cursor", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Opaque cursor from the previous page's `meta`." } ] }, "post": { "summary": "Send message", "tags": [ "Messaging" ], "operationId": "oauth_POST_threads_id_messages", "security": [ { "oauth": [ "messaging:write" ] } ], "responses": { "201": { "description": "Send message \u2014 201 Created", "content": { "application/json": { "example": { "data": { "id": "4242", "type": "messages", "attributes": { "body": "Hi! Your check-in details are\u2026", "channel": "airbnb", "direction": "outbound", "sender_reference_id": null, "status": "sent", "failure_reason": null, "translated_body": null, "language": null, "timestamp": "2026-06-15T12:00:00Z" } } } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. **Required scope:** `messaging:write`\n\nSend a message on a thread. Returns **201**.\n\n**Parameters**\n\n| Name | In | Type | Required | Notes |\n|---|---|---|---|---|\n| `id` | path | integer | Yes | Thread ID. |\n| `data.type` | body | string | No | If present, must equal `\"messages\"`. |\n| `data.attributes.channel` | body | string | Yes | Allowed: `sms`, `email`, `airbnb`, `booking_dot_com`, `home_away`. Must be enabled for the thread. |\n| `data.attributes.body` | body | string | Yes | Message text. SMS is length-limited. |", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Thread ID." } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object" }, "example": { "data": { "type": "messages", "attributes": { "channel": "airbnb", "body": "Hi! Your check-in details are\u2026" } } } } } } } }, "/ping": { "get": { "summary": "Ping (verify token)", "tags": [ "Utility" ], "operationId": "oauth_GET_ping", "security": [ { "oauth": [] } ], "responses": { "200": { "description": "Ping (verify token) \u2014 200 OK", "content": { "application/json": { "example": { "status": "pong", "user": "Jane Host", "email": "jane.host@example.com", "account_id": 1001 } } } }, "401": { "description": "Unrecognised API key or token" }, "403": { "description": "FORBIDDEN: missing scope or permission" }, "429": { "description": "Rate limit exceeded" } }, "description": "V3 OAuth. Authentication-only health check. Returns your user name, email and account id: use it to confirm `` is valid. No parameters.\n\n```json\n{\n \"status\": \"pong\",\n \"user\": \"Jane Doe\",\n \"email\": \"jane@example.com\",\n \"account_id\": 42\n}\n```" } }, "/users/me": { "get": { "summary": "Verify API key", "tags": [ "Legacy API key" ], "operationId": "legacy_GET_users_me", "security": [ { "legacyApiKey": [] } ], "responses": { "200": { "description": "Verify API key", "content": { "application/json": { "example": { "name": "Uplisting", "uid": "example-user-uid" } } } }, "401": { "description": "Unrecognised API key or token" }, "429": { "description": "Rate limit exceeded" } }, "description": "Legacy API key. Initially, you need to verify that your API key is correct and that you are using the correct authentication header. \nTo do so, `GET` the following URL: [https://connect.uplisting.io/users/me](https://connect.uplisting.io/users/me) with an authorisation header that is your **API key encoded with Base64** with application/json content-type.\n\nFor example, in Ruby, these are the headers you need to pass.\n\n```\nHash[\"HTTP_AUTHORIZATION\" => \"Basic #{Base64.strict_encode64(api_key)}\", \"CONTENT_TYPE\" => \"application/json\"]\n\n ```\n\nIf successful, you should get back the name of your account and a unique ID for the user.\n\n```\n{\n \"name\": \"Uplisting\",\n \"uid\": \"example-user-uid\"\n}\n\n ```\n\nThis proves that you have the correct authorisation header, which should be used for all future communication.\n\nIf you receive an error that states \"Your API key does not appear to be valid\" please first check you have Base64 encoded the key. Otherwise check the key still exists at Connect > API. If it still fails, report it to partner@uplisting.io as an API issue, with your account email." } } } }