Skip to main content

Listing Preferences: Read, Update & Preview Pricing Settings

Written by Ryo

Listing preferences control how Wheelhouse generates price recommendations for each property — base price, seasonality, discounts, min stay rules, and more. These are called "Settings" in the Wheelhouse app. This reference covers every endpoint for reading, updating, previewing, and copying preferences.


GET /preferences/:listing_id

Read preferences for a single listing.

curl "https://api.usewheelhouse.com/ss_api/v1/preferences/12345678?channel=airbnb" \
-H "X-Integration-Api-Key: your_api_key_here"

Parameters

  • listing_id (string, path, required) — the channel's unique listing identifier

  • channel (string, query, required) — the channel name for this listing (from GET /listings)

Key response fields

  • listing_id — Wheelhouse's internal numeric ID for this listing

  • partner_listing_id — the channel's listing ID (same as the id in GET /listings)

  • base_price — the manually set base price (if set, overrides Wheelhouse's recommendation)

  • base_price_adjustment — percentage adjustment to the Wheelhouse recommended base price (only present if base_price is not set)

  • weekly_discount / monthly_discount — discount percentage for stays ≥7 / ≥28 nights (0 = no discount). On listings that accept length-of-stay premiums (every listing whose supported_settings.long_term_discount_type is complex, and some with rules), values are signed: -10 is a 10% discount and 10 a 10% premium

  • automatic_rate_posting_enabled — whether Wheelhouse auto-pushes prices to the channel

  • last_minute_discount / seasonality_adjustment / far_future_premium / day_of_week — objects with type set to CON (conservative), REC (recommended), AGG (aggressive), or CUS (custom). For day_of_week, CUS takes your own rules, whose values are price multipliers (1.1 is 10% higher), and CUS without rules has no effect. Sent without rules, CON and AGG store the matching preset rule

  • smooth — a boolean on last_minute_discount, far_future_premium and seasonality_adjustment, shown as Smooth in the app. It defaults to false, which is stepped, and it is only used when type is CUS. When true, the adjustment eases gradually from one rule to the next instead of jumping at each rule's edge, and custom rules still apply exactly. On seasonality_adjustment, smoothing also ignores the step, start_value and end_value of monthly rules

  • currency — currency used for prices on this listing

  • fee_adjustments — the estimated fees guests pay on top of the nightly rate (shown as "Asking Rate (+Est. Fees)" in the app). An object with total_fee_percentage (fees as a percentage of the nightly rate, -100 or more; 15 means guests pay about 15% on top) and auto_update (when true, the percentage is recalculated weekly from the fees on recent reservations, replacing what was set; defaults to false). It is null when nothing is configured, otherwise both keys are present. When you update it, the object replaces the stored one as a whole, so send both keys; null clears it. It is what GET /listings/:listing_id/fee_impact_calendar reads

  • historical_anchoring_mode — how a historical anchoring percentage (Historical Protections in the app) turns the historical price into a floor for the recommendation: blended (default) or anchor_only. blended averages the historical price with the recommendation, using the percentage as the weight on the historical price: at 50%, a $1,200 historical price and a $400 recommendation give $800. anchor_only takes the percentage of the historical price alone, so at 50% the floor is $600: a $400 recommendation rises to $600 and a $700 one stays at $700. Either only ever raises a price, and from 100% up both give the same price

  • historical_anchoring_price_source — which historical price anchoring weighs in: observed (default), the listing's price as Wheelhouse saw it on the channel once the date booked; posted, the price Wheelhouse last posted for the date before it booked, so dates Wheelhouse never posted a price for are not anchored; or posted_with_fallback, the posted price where there is one and the observed price otherwise

  • supported_settings — which settings this listing's channel can act on. A setting reported false is discarded on write rather than posted to the channel, so check it before sending that setting


GET /preferences

Read preferences for multiple listings at once.

curl "https://api.usewheelhouse.com/ss_api/v1/preferences?channel=airbnb&listing_ids[]=12345678&listing_ids[]=87654321" \
-H "X-Integration-Api-Key: your_api_key_here"

Query parameters

  • channel (string, required) — the channel name for these listings

  • listing_ids (string[], optional) — listing IDs to include. Send more than one in brackets (?listing_ids[]=12345678&listing_ids[]=87654321); a key repeated without brackets keeps only its last value. If omitted, returns an empty array (not all listings)

Returns an array of preference objects, one per listing.


PUT /preferences/:listing_id

Update preferences for a single listing. Send only the fields you want to change — everything else stays unchanged.

curl --request PUT "https://api.usewheelhouse.com/ss_api/v1/preferences/12345678?channel=airbnb" \
-H "X-Integration-Api-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"base_price": 200, "monthly_discount": 10}'

Parameters

  • listing_id (string, path, required)

  • channel (string, query, required)

Important behavior

Partial updates apply at the top level only. If you send a field that holds an array of rules (e.g. minimum_price_rules_v3), the entire array is replaced — individual rules cannot be patched. Always fetch current preferences first and include every rule you want to keep.

These settings are objects, and the object you send replaces the stored one as a whole:

  • checkin_checkout — send active and both check_in_rules and check_out_rules. A request missing either array is rejected with 400. An empty check_out_rules leaves check-out unrestricted. Rule values are allow flags: 1 allows the day and 0 blocks it, and a day_of_week rule has 7 values, with index 0 = Sunday. Where rules overlap, the more specific rule type wins (a date-specific custom rule over a day_of_week rule); between rules of the same type, the later one in the array wins. auto_adjust, when true, opens extra check-in and check-out days around unavailable nights so open stretches between bookings can still be booked.

  • occupancy_pacing — {} means pacing is off, which is the default for a new listing; omit it to leave pacing unchanged. A non-empty object needs adjusted and pacing, and pacing must include a matrix with type global, otherwise the request is rejected with 400. Each column is a lead-time window in days from today, and each row is an occupancy band: a row covers occupancy above min up to and including max, and the first matching row wins. values holds one array per row with one whole percentage per column (-10 is a 10% decrease), each -100 or more. Any other shape is rejected with 400.

  • gap_night — the custom array replaces the stored one.

Example, check-in on Friday and Saturday only, check-out any day:

{
"checkin_checkout": {
"active": true,
"auto_adjust": false,
"check_in_rules": [{"type": "day_of_week", "day_of_week_values": [0, 0, 0, 0, 0, 1, 1]}],
"check_out_rules": [{"type": "day_of_week", "day_of_week_values": [1, 1, 1, 1, 1, 1, 1]}]
}
}

Write responses include a warnings array, empty when everything applied. Each entry names the setting and a reason: not_supported_by_channel (the channel has no such feature and everything sent for it was dropped), partially_supported_by_channel (only the excess was dropped), or not_supported_for_multi_unit (the setting is stored but has no effect on price because the listing has more than one unit, which is the case for gap night pricing).

Gap night pricing

The gap_night setting is "Gaps & Adjacencies" in the Pricing Engine panel. It sets the price multiplier for open nights between bookings. It only affects prices, and it is separate from the gap and adjacency rule types in the minimum stay rules, which control minimum stay for those nights.

Set type to CON, REC or AGG for a preset, or to CUS to write your own rules in custom. CUS without custom is rejected; an empty array is allowed. Each custom rule has:

  • gap (integer, required) — the rule applies to gaps of this many nights or fewer

  • day_of_week (array of integers, required) — the weekdays the rule applies to, 0 = Sunday through 6 = Saturday, each at most once

  • adjustment (number, required) — a price multiplier, greater than 0 and at most 10. 0.8 is a 20% discount

  • adjacent (string, optional) — leave it out to match open nights with an unavailable night on both sides ("In between"). left matches the first gap open nights after an unavailable night ("Only after"). right matches the last gap open nights before one ("Only before")

When several rules match a night, rules without adjacent are checked first, then left, then right. Within those, the rule with the smallest gap that still covers the gap wins, and among rules with the same gap the largest adjustment wins.

Example, 20% off on Sunday to Thursday for gaps of 2 nights or fewer:

{
"gap_night": {
"type": "CUS",
"custom": [{"gap": 2, "day_of_week": [0, 1, 2, 3, 4], "adjustment": 0.8}]
}
}

Gap night pricing does not apply to listings with more than one unit. The setting is still accepted, and the response carries a not_supported_for_multi_unit warning.

Status codes

  • 400 — a setting in the request has the wrong shape; the message names the field

  • 423 — preferences not yet initialized for this listing; retry after a brief delay

  • 409 — another request already in progress for this listing; retry after it completes


PUT /preferences/:listing_id/:setting

Update a single pricing setting to a preset level.

curl --request PUT "https://api.usewheelhouse.com/ss_api/v1/preferences/12345678/seasonality_adjustment?channel=airbnb" \
-H "X-Integration-Api-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"type": "AGG"}'

Returns 204 No Content on success.

Supported settings

  • base_price_adjustment — body: {"type": "CON" | "REC" | "AGG"}

  • day_of_week — body: {"type": "CON" | "REC" | "AGG"}

  • seasonality_adjustment — body: {"type": "CON" | "REC" | "AGG"}

  • last_minute_discount — body: {"type": "CON" | "REC" | "AGG"}

  • far_future_premium — body: {"type": "CON" | "REC" | "AGG"}

  • automatic_rate_posting — body: {"enabled": true | false}

Parameters

  • listing_id (string, path, required)

  • setting (string, path, required) — one of the settings listed above

  • channel (string, query, required)


PUT /preferences (bulk)

Update preferences across multiple listings in one request. This is a bulk update, which a user with restricted editor access to a shared listing may not make: such a listing is reported in the response with status 403, however many listings the request names. Use PUT /preferences/:listing_id for it instead.

curl --request PUT "https://api.usewheelhouse.com/ss_api/v1/preferences?channel=airbnb" \
-H "X-Integration-Api-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"listing_preferences": [
{"listing_id": "12345678", "base_price": 200},
{"listing_id": "87654321", "base_price": 180}
]
}'

Parameters

  • channel (string, query, required)

  • listing_preferences (array, body, required) — each entry must include:

    • listing_id (string, required) — the channel's listing ID

    • any preference fields to update (same fields as PUT /preferences/{listing_id})

Status codes

  • 207 — some updates succeeded, some failed; check the response body for per-listing breakdown

  • 424 — all updates failed


PUT /preferences/:listing_id/copy

Copy preferences from one listing to another. This overwrites the target listing's existing preferences.

The :listing_id in the path is the target (the listing being overwritten). The source listing is identified in the request body.

curl --request PUT "https://api.usewheelhouse.com/ss_api/v1/preferences/87654321/copy" \
-H "X-Integration-Api-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"channel": "airbnb",
"copy_preferences_from": {
"listing_id": "12345678",
"channel": "airbnb"
}
}'

Request body

  • channel (string, required) — channel name of the target listing

  • copy_preferences_from (object, required) — identifies the source listing:

  • listing_id (string, required) — the source listing's channel ID

    • channel (string, optional) — channel name of the source listing

  • copy_custom_rates (boolean, optional, default: true) — when true, also copies custom rates from the source to the target


POST /preferences/:listing_id/preview

Preview how a preference change would affect daily prices — without saving anything. See the How to preview pricing changes before applying them guide for full details and code examples.

curl --request POST "https://api.usewheelhouse.com/ss_api/v1/preferences/12345678/preview?channel=airbnb" \
-H "X-Integration-Api-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"base_price": 200}'

Returns the same format as GET /listings/{listing_id}/price_recommendations, with global_min_stay and automatic_rate_posting_enabled omitted. Nothing is saved. A setting with the wrong shape returns 400, and the message names the field.


GET /preferences/:listing_id/long_term_discounts

Get the long-term discount settings for a listing (weekly and monthly discounts).

curl "https://api.usewheelhouse.com/ss_api/v1/preferences/12345678/long_term_discounts?channel=airbnb" \
-H "X-Integration-Api-Key: your_api_key_here"

Response fields

  • weekly_discount — discount percentage for stays ≥7 nights (integer, nullable)

  • monthly_discount — discount percentage for stays ≥28 nights (integer, nullable)

These are the same values as weekly_discount and monthly_discount in GET /preferences/{listing_id}.


GET /preferences/:listing_id/changelog

Get a log of recent preference changes for a listing — useful for auditing who changed what and when.

curl "https://api.usewheelhouse.com/ss_api/v1/preferences/12345678/changelog?channel=airbnb" \
-H "X-Integration-Api-Key: your_api_key_here"

Query parameters

  • channel (string, required)

  • start_date (string, optional) — start of the date range (YYYY-MM-DD); defaults to 30 days ago, clamped to 90 days max

  • end_date (string, optional) — end of the date range (YYYY-MM-DD); defaults to tomorrow

Response

Returns an events array. Each event includes:

  • time — when the change occurred (ISO 8601)

  • source — who triggered it: "Wheelhouse" (system), "User" / "User <name>", "API" / "API <name>", "Customer Support", "Wheelhouse team" / "Wheelhouse team <name>". Reservation imports show the name of the person who ran them, including past imports; imports from before the name was recorded still show just "Wheelhouse team". Fixed rate changes made through the RM API or admin tools show where the change came from instead of always showing "User"; older entries still show "User". Preference and custom rate copies made through the RM API show as "API <name>"

  • event — type of event: "Prices posted", "Calendar synced", "Settings changed", "Custom rates", "Reservations imported"

  • status — "success", "warning" (partial success: for example some prices posted, but the channel rejected some dates; msg says what to fix) or "error"

  • msg — human-readable description of the change

Related

How to read and update pricing preferences

How to preview pricing changes before applying them

Did this answer your question?