Skip to main content

Dynamic Sets

Dynamic sets are user-curated sets of comparison listings used to track competitive performance. Use these endpoints to build a set from scratch (search for candidate listings near a location, create a set from them, and upgrade it to paid), list a user's sets, inspect a set's definition and member listings, retrieve aggregated performance metrics, manage which of the user's own listings the set is associated with, and fetch a set's change history, time-series metrics, and metric distributions.

GET /sets returns both free and paid sets; the is_paid field on each set indicates which. Everything involved in building a set works on a free one — creating it, adding and removing its member listings, reviewing them, and managing which of your own listings it is associated with. What the paid plan buys is the set-level analytics computed across the set, including its price calendar. A paid-only endpoint returns 404 Not Found for a free set, which is indistinguishable from a set that does not exist, so check is_paid before calling one.

EndpointFree setsPaid sets
GET /sets
POST /sets✅ (creates a free set)
GET /sets/candidates✅ (no set required)
GET /sets/{set_id}
POST /sets/{set_id}/upgrade✅ (this is what upgrades it)
POST /sets/{set_id}/share
GET /sets/{set_id}/listings
PUT /sets/{set_id}/listings
DELETE /sets/{set_id}/listings
GET /sets/{set_id}/associated_listings
PUT /sets/{set_id}/associated_listings
DELETE /sets/{set_id}/associated_listings
GET /sets/{set_id}/aggregated_metrics❌ 404
GET /sets/{set_id}/price_calendar❌ 404✅ (up to 25 members)
GET /sets/{set_id}/time_series❌ 404
GET /sets/{set_id}/distribution❌ 404
GET /sets/{set_id}/changelog❌ 404

Upgrade a free set with POST /sets/{set_id}/upgrade, which purchases the paid plan and charges the billable user. Sets the user owns as well as sets shared with the user are included throughout; modifying a shared set requires editor or manager access to it.

📄️Add member listings to a dynamic set.

Adds the given listings to the set as members — the comparison listings the set is built from. Identify them by the internal `listing_id` values returned by `GET /sets/candidates`; only listings that are 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`. Requires editor or manager access to the set when the set is shared. **Works for free and paid sets.** This is an upsert: a listing already in the set keeps its single membership and takes the requested `status`, so repeating an identical call leaves the set in the same state.

📄️Remove member listings from a dynamic set.

Removes the given listings from the set's membership. 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`. Requires editor or manager access to the set when the set is shared. **Works for free and paid sets.** Note that on a filter-based (non-static) set, membership is derived from the set's own filters, so removed members may be restored by the next sync — the same behaviour as the Wheelhouse app.

📄️Share a dynamic set with other users.

Grants specified access levels to other users for this dynamic set. Only the set's owner or a manager-level collaborator may share the set. Access levels are: **R** (viewer, read-only), **E** (restricted editor), **F** (editor, can modify set and associated listings), **M** (manager, can share and upgrade the set), and **N** (disabled, revokes access). Sharing with a user who already has access updates their level to the newly specified one. Returns the updated dynamic set. **Works for free and paid sets.**