Skip to main content

Dynamic Sets: Property Groups and Performance Insights

Written by Ryo

Dynamic sets are saved collections of relevant properties that meet your specified criteria. They're built inside Wheelhouse Navigator — a map-based interface that combines geographic, performance, pricing, inventory type, operator type, LOS & fees, and amenity data. Use dynamic sets for benchmarking, pricing strategy, owner comms, listing acquisition, and more.

Dynamic sets include two distinct listing types: the member listings inside the set (properties matching your criteria), and your own associated listings that you've linked for side-by-side comparison.

Important

The RM API works with both free and paid dynamic sets. Listing sets, viewing a set, its member listings and its associated listings all work for free sets. The performance endpoints (aggregated metrics, time series, distribution, changelog and the price calendar) are for paid sets only and return 404 Not Found for a free set. To upgrade a free set, use POST /sets/:set_id/upgrade — this charges your payment method.


GET /sets

List all dynamic sets, free and paid, that the authenticated user owns or has shared access to. Use the is_paid field to tell them apart. Results are ordered by most recently updated first.

curl "https://api.usewheelhouse.com/ss_api/v1/sets" \
-H "X-Integration-Api-Key: your_api_key_here"

Query parameters

  • name (string, optional) — match sets by name. * stands for any run of characters, so *Palm Springs* matches sets with that phrase anywhere in the name; a value with no * has to match the whole name. Matching ignores case

  • kind (string, optional) — match sets by their kind. Comma-separate several to match any of them, e.g. competitive,market. Sets with no kind are reported as other. An unrecognised value returns 400

  • per_page (integer, optional, default: 50) — number of sets per page (max 100)

  • page (integer, optional) — page number

  • offset (integer, optional) — number of items to skip

Response — array of dynamic set objects:

[
{
"id": 7,
"user_id": 1001,
"name": "Beachfront Comps",
"description": "Top comps near our Malibu property",
"kind": "competitive",
"currency": "USD",
"is_static": true,
"filters": {},
"boundary": [...],
"listing_counts": {
"active": 8,
"hidden": 1,
"review": 0,
"removed": 1
},
"updated_at": "2026-01-15T08:30:00Z"
}
]

Response fields

  • id — Wheelhouse's internal dynamic set ID (integer)

  • kind — the use-case label for the set. One of: competitive, market, neighborhood, marketing, acquisition, underwriting, merchandising, other

  • is_paid — true if the set is on the paid Dynamic Sets plan. Only paid sets expose the performance endpoints; free sets return 404 there

  • is_static — true if member listings are a frozen snapshot; false if the set auto-syncs based on its boundary and filters

  • listing_counts — member counts broken down by status: active, hidden, review, removed

  • boundary — geographic boundary of the set

Status codes

  • 200 — array of dynamic sets

  • 401 — API key authorization failed


GET /sets/:set_id

Get detailed information about a single dynamic set, including its definition, boundary, and member counts per status.

curl "https://api.usewheelhouse.com/ss_api/v1/sets/7" \
-H "X-Integration-Api-Key: your_api_key_here"

Path parameters

  • set_id (integer, required) — Wheelhouse internal dynamic set ID

Status codes

  • 200 — dynamic set object (same shape as list response)

  • 401 — API key authorization failed

  • 404 — not found or not accessible


GET /sets/:set_id/aggregated_metrics

Get monthly performance metrics aggregated across active member listings.

curl "https://api.usewheelhouse.com/ss_api/v1/sets/7/aggregated_metrics?currency=USD&dates[]=2026-05-01&dates[]=2026-06-01" \
-H "X-Integration-Api-Key: your_api_key_here"

Path parameters

  • set_id (integer, required) — Wheelhouse internal dynamic set ID

Query parameters

  • currency (string, optional) — ISO 4217 3-letter currency code. Defaults to the set's currency.

  • dates (string[], optional) — restrict to months starting on these dates (YYYY-MM-DD, first of month). Send more than one in brackets (?dates[]=2026-05-01&dates[]=2026-06-01); a key repeated without brackets keeps only its last value. Defaults to all available.

Status codes

  • 200 — aggregated metrics per period

  • 401 — API key authorization failed

  • 404 — not found, not accessible, or not a paid set


GET /sets/:set_id/listings

List member listings grouped by membership status, with trailing year performance metrics.

curl "https://api.usewheelhouse.com/ss_api/v1/sets/7/listings" \
-H "X-Integration-Api-Key: your_api_key_here"

Path parameters

  • set_id (integer, required) — Wheelhouse internal dynamic set ID

Response

{ "active": [...], "hidden": [...], "review": [...], "removed": [...] }
  • active — currently active members

  • hidden — hidden from the set view

  • review — pending review before being added

  • removed — previously removed members

Status codes

  • 200 — member listings grouped by status

  • 401 — API key authorization failed

  • 404 — not found or not accessible


GET /sets/:set_id/time_series

Get daily time-series metrics aggregated across active member listings over a date range.

curl "https://api.usewheelhouse.com/ss_api/v1/sets/7/time_series?metric[]=occupancy&metric[]=adr_w_fees&start_date=2026-01-01&end_date=2026-06-30" \
-H "X-Integration-Api-Key: your_api_key_here"

Path parameters

  • set_id (integer, required) — Wheelhouse internal dynamic set ID

Query parameters

  • metric (string[], optional) — metrics to include. Available: asking_rate_w_fees, occupancy, occupancy_adjusted, adr_w_fees, lead_time, revpar_adjusted_w_fees, revpar_w_fees, revenue_w_fees, nights_bookable. Defaults to all. Send more than one in brackets (?metric[]=occupancy&metric[]=adr_w_fees); a key repeated without brackets keeps only its last value.

  • start_date (string, optional) — YYYY-MM-DD. Defaults to today. Max 3 years past, 1 year future.

  • end_date (string, optional) — YYYY-MM-DD. Defaults to 1 year from today. Must be after start_date.

Status codes

  • 200 — time-series data

  • 204 — not enough data

  • 400 — invalid parameter value

  • 401 — API key authorization failed

  • 404 — not found, not accessible, or not a paid set


GET /sets/:set_id/distribution

Get histogram distributions for one or more metrics for a given calendar month.

curl "https://api.usewheelhouse.com/ss_api/v1/sets/7/distribution?metric[]=occupancy&metric[]=adr_w_fees&month=2026-06-01" \
-H "X-Integration-Api-Key: your_api_key_here"

Path parameters

  • set_id (integer, required) — Wheelhouse internal dynamic set ID

Query parameters

  • metric (string[], optional) — metrics to include. Available: occupancy, occupancy_adjusted, asking_rate_w_fees, adr_w_fees, lead_time, revpar_adjusted_w_fees, revpar_w_fees, length_of_stay. Defaults to all. Send more than one in brackets (?metric[]=occupancy&metric[]=adr_w_fees); a key repeated without brackets keeps only its last value.

  • month (string, optional) — the target month (YYYY-MM-DD or YYYY-MM, e.g. 2026-06-01 or 2026-06). Defaults to start of current month.

Response

Each metric key maps to an array of histogram buckets:

{
"currency": "USD",
"month": "2026-06-01",
"data": {
"occupancy": [
{ "bucket_min_incl": 0.0, "bucket_max_excl": 0.1, "probability": 0.0625, "percentile": 0.0625 }
],
"adr_w_fees": [...],
"lead_time": [...],
"length_of_stay": [...]
}
}

Metric units:

  • asking_rate_w_fees, adr_w_fees, revpar_adjusted_w_fees, revpar_w_fees — monetary, in the currency at the top level

  • occupancy, occupancy_adjusted — decimal fraction (0–1); multiply by 100 for percentage

  • lead_time — days; negative = advance booking (booked before stay date)

  • length_of_stay — nights

Status codes

  • 200 — metric distributions for the month

  • 204 — not enough data

  • 400 — invalid parameter value

  • 401 — API key authorization failed

  • 404 — not found, not accessible, or not a paid set


GET /sets/:set_id/associated_listings

List the authenticated user's own listings associated with the set for comparison. For shared sets, listings you don't have access to are omitted.

curl "https://api.usewheelhouse.com/ss_api/v1/sets/7/associated_listings" \
-H "X-Integration-Api-Key: your_api_key_here"

Path parameters

  • set_id (integer, required) — Wheelhouse internal dynamic set ID

Status codes

  • 200 — array of associated listing objects

  • 401 — API key authorization failed

  • 404 — not found or not accessible


PUT /sets/:set_id/associated_listings

Associate your own listings with a dynamic set. Already-associated listings are left unchanged. Requires editor or manager access on shared sets.

curl --request PUT "https://api.usewheelhouse.com/ss_api/v1/sets/7/associated_listings" \
-H "X-Integration-Api-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{ "listing_ids": ["abc123", "def456"], "channel": "airbnb" }'

Path parameters

  • set_id (integer, required) — Wheelhouse internal dynamic set ID

Request body

  • listing_ids (string[], required) — channel listing IDs to associate. Maximum 500.

  • channel (string, conditional) — required if it cannot be derived from the API key.

Status codes

  • 200 — updated array of associated listing objects

  • 400 — invalid parameters

  • 401 — API key authorization failed

  • 403 — insufficient access or read-only API key

  • 404 — set or listing not found, or not accessible

  • 409 — concurrent request in progress; retry after it completes


DELETE /sets/:set_id/associated_listings

Remove your own listings from a dynamic set. Requires editor or manager access on shared sets.

curl --request DELETE "https://api.usewheelhouse.com/ss_api/v1/sets/7/associated_listings?listing_ids[]=abc123&listing_ids[]=def456&channel=airbnb" \
-H "X-Integration-Api-Key: your_api_key_here"

Path parameters

  • set_id (integer, required) — Wheelhouse internal dynamic set ID

Query parameters

  • listing_ids (string[], required) — channel listing IDs to remove. Maximum 500. Send more than one in brackets (?listing_ids[]=abc123&listing_ids[]=def456); a key repeated without brackets keeps only its last value.

  • channel (string, conditional) — required if it cannot be derived from the API key.

Status codes

  • 200 — updated array of associated listing objects

  • 400 — invalid parameters

  • 401 — API key authorization failed

  • 403 — insufficient access or read-only API key

  • 404 — set or listing not found, or not accessible

  • 409 — concurrent request in progress; retry after it completes


GET /sets/:set_id/changelog

Get the history of changes to a dynamic set — membership additions, removals, and edits — ordered oldest first.

curl "https://api.usewheelhouse.com/ss_api/v1/sets/7/changelog?after=2026-01-01" \
-H "X-Integration-Api-Key: your_api_key_here"

Path parameters

  • set_id (integer, required) — Wheelhouse internal dynamic set ID

Query parameters

  • after (string, optional) — only include changes on or after this date (YYYY-MM-DD)

  • before (string, optional) — only include changes before this date (YYYY-MM-DD, exclusive)

Status codes

  • 200 — array of changelog entries

  • 401 — API key authorization failed

  • 404 — not found, not accessible, or not a paid set


POST /sets

Create a free dynamic set. Add candidate listings (from GET /sets/candidates) by passing their internal listing_id values; they are added with the active status. The set is created on the free plan — upgrade it with POST /sets/:set_id/upgrade to use the performance endpoints.

curl --request POST "https://api.usewheelhouse.com/ss_api/v1/sets" \
-H "X-Integration-Api-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "Beachfront Comps",
"description": "Top comps near our Malibu property",
"listing_ids": [101, 102, 103]
}'

Request body

  • name (string, required) — name of the dynamic set

  • description (string, optional) — description of the set

  • currency (string, optional) — ISO-4217 3-letter currency code. Defaults to the currency of the most common market among the set's listings

  • listing_ids (integer[], optional) — internal listing IDs (the listing_id values from GET /sets/candidates) to add as members. Maximum 500 per request

Status codes

  • 201 — the created dynamic set

  • 400 — validation error, such as a missing name or more than 500 listing IDs

  • 401 — API key authorization failed

  • 403 — the API key is read-only

  • 404 — one or more of the listing IDs were not found


GET /sets/candidates

Search market listings to choose from when building a dynamic set, with their trailing-year performance metrics. Provide either lat, long and radius (radius in meters) or one or more market_ids. Results are ordered nearest-first, each with a distance_meters value, and are paginated. Pass the returned listing_id values to POST /sets to add them as members. This endpoint isn't tied to a set, so no set plan applies.

curl "https://api.usewheelhouse.com/ss_api/v1/sets/candidates?lat=34.03&long=-118.69&radius=3000&min_bedrooms=2" \
-H "X-Integration-Api-Key: your_api_key_here"

Query parameters

  • lat, long (number) and radius (integer, meters) — search center and radius. Send all three together

  • market_ids (integer[]) — restrict candidates to these markets. Provide this or lat/long/radius. Send more than one in brackets (?market_ids[]=12&market_ids[]=34); a key repeated without brackets keeps only its last value

  • min_bedrooms, max_bedrooms (integer) and min_bathrooms, max_bathrooms (number)

  • room_types (string[]) — normalized room types. Send more than one in brackets (?room_types[]=apartment&room_types[]=house)

  • min_bookable_nights_0_365 (integer) — minimum bookable nights over the next 365 days

  • min_open_occupancy_0_365 (number, 0–1) — minimum forward-looking adjusted occupancy

  • min_open_occupancy_365_0 (number, 0–1) — minimum trailing-year adjusted occupancy. Defaults to 0.35

  • min_bookable_nights_365_0 (integer) — minimum trailing-year bookable nights. Defaults to 127

  • per_page (integer) and page (integer) — pagination

Status codes

  • 200 — array of candidate listings, nearest first

  • 400 — neither lat/long/radius nor market_ids were provided, or lat/long/radius were not sent together

  • 401 — API key authorization failed


POST /sets/:set_id/upgrade

This charges your payment method

Upgrading creates a real paid subscription. There is no sandbox or test mode.

Upgrade a free dynamic set to the paid Dynamic Sets plan, so its performance endpoints (aggregated metrics, time series, distribution, changelog and the price calendar) become available. Only the set's owner or a manager-level collaborator can upgrade a set; editors cannot. The billable user must have a valid payment method on file. Returns the upgraded set.

curl --request POST "https://api.usewheelhouse.com/ss_api/v1/sets/7/upgrade" \
-H "X-Integration-Api-Key: your_api_key_here"

Path parameters

  • set_id (integer, required) — Wheelhouse internal dynamic set ID

Status codes

  • 200 — the upgraded (now paid) dynamic set

  • 401 — API key authorization failed

  • 402 — no valid payment method on file, or the charge failed

  • 403 — the API key is read-only, or the user is not the set's owner or a manager

  • 404 — dynamic set not found or not accessible

  • 409 — the dynamic set is already on a paid plan


POST /sets/:set_id/share

Share a dynamic set with other users by granting them an access level. Only the set's owner or a manager-level collaborator can share a set. Sharing with a user who already has access updates their level. Returns the updated set. Works for free and paid sets.

curl --request POST "https://api.usewheelhouse.com/ss_api/v1/sets/7/share" \
-H "X-Integration-Api-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"access": { "F": [2001, 2002], "R": [2003] }
}'

Path parameters

  • set_id (integer, required) — Wheelhouse internal dynamic set ID

Request body

  • access (object, required) — user IDs to grant each access level, keyed by level code:

  • R — viewer, read-only

  • E — restricted editor

  • F — editor; can modify the set and its associated listings

  • M — manager; can also share and upgrade the set

  • N — disabled; revokes access

Status codes

  • 200 — the dynamic set with updated sharing settings

  • 400 — invalid access levels or user IDs

  • 401 — API key authorization failed

  • 403 — the API key is read-only, or the user is not the set's owner or a manager

  • 404 — dynamic set not found or not accessible


PUT /sets/:set_id/listings

Add member listings to a dynamic set — the comparison listings the set is built from. Identify them by the internal listing_id values returned by GET /sets/candidates; only eligible comparison candidates can be added. Returns the set's member listings after the change, in the same shape as GET /sets/:set_id/listings. Works for free and paid sets, and needs editor or manager access when the set is shared.

This is an upsert: a listing already in the set keeps its single membership and takes the requested status. If you leave status out, a member that is currently hidden, review or removed moves back to active, so pass the status explicitly when re-sending a list.

curl --request PUT "https://api.usewheelhouse.com/ss_api/v1/sets/7/listings" \
-H "X-Integration-Api-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"listing_ids": [101, 102],
"status": "active"
}'

Path parameters

  • set_id (integer, required) — Wheelhouse internal dynamic set ID

Request body

  • listing_ids (integer[], required) — internal listing IDs to add, the listing_id values from GET /sets/candidates (not channel listing IDs). At most 500 per request

  • status (string, optional, default: active) — one of active, hidden, review, removed

Status codes

  • 200 — the set's member listings after the change, grouped by status

  • 400 — more than 500 listing IDs were sent

  • 401 — API key authorization failed

  • 403 — the set is shared with you without editor or manager access, or the API key is read-only

  • 404 — set not found or not accessible, or one or more listing IDs are not eligible as members

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


DELETE /sets/:set_id/listings

Remove member listings from a dynamic set. Identify them by their internal listing_id. Returns the set's member listings after the change, in the same shape as GET /sets/:set_id/listings. Works for free and paid sets, and needs editor or manager access when the set is shared.

On a filter-based (non-static) set, membership comes from the set's own filters, so removed members may be restored by the next sync — the same as in the Wheelhouse app.

curl --request DELETE "https://api.usewheelhouse.com/ss_api/v1/sets/7/listings" \
-H "X-Integration-Api-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{ "listing_ids": [101, 102] }'

Path parameters

  • set_id (integer, required) — Wheelhouse internal dynamic set ID

Request body

  • listing_ids (integer[], required) — internal listing IDs to remove. IDs that are not members are ignored. At most 500 per request

Status codes

  • 200 — the set's member listings after the change, grouped by status

  • 400 — more than 500 listing IDs were sent

  • 401 — API key authorization failed

  • 403 — the set is shared with you without editor or manager access, or the API key is read-only

  • 404 — dynamic set not found or not accessible

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


GET /sets/:set_id/price_calendar

Get a night-by-night price calendar for each active member listing of a set — the API equivalent of the set calendar in the Wheelhouse app. Each listing carries its own array of nights, with prices converted to one currency so comps priced differently can be compared.

Only available for small sets: a set with more than 25 member listings returns 422. Every membership counts toward that limit, whatever its status. Paid sets only — a free set returns 404; upgrade it first.

The shape follows GET /listings/:listing_id/price_calendar, with two differences because a comparison listing isn't one of your own: there is no is_booked flag and no reservation_id. See booking_probability_percent on each night for what replaces them.

curl "https://api.usewheelhouse.com/ss_api/v1/sets/7/price_calendar?start_date=2026-11-01&end_date=2026-11-30&currency=USD" \
-H "X-Integration-Api-Key: your_api_key_here"

Path parameters

  • set_id (integer, required) — Wheelhouse internal dynamic set ID

Query parameters

  • start_date (string, optional) — first stay date, YYYY-MM-DD. Defaults to today

  • end_date (string, optional) — last stay date, YYYY-MM-DD. Defaults to 545 days out, the maximum calendar horizon. The range may not exceed 3 years

  • currency (string, optional) — ISO-4217 3-letter currency code to convert prices to. Defaults to the set's own currency

Status codes

  • 200 — one calendar per active member listing

  • 400 — the date range exceeds 3 years, ends before it starts, or the currency is not supported

  • 401 — API key authorization failed

  • 404 — dynamic set not found, not accessible, or not a paid set

  • 422 — the set has more than 25 member listings

Related

  • Segments: Portfolio Groups and Filters

  • Market Reports & Neighborhood Data: Market-level insights

  • How to organize and filter listings (tags, segments, dynamic sets)

Did this answer your question?