Intermediate
15 min
Python
JavaScript
Postman

Advanced Filtering and Sorting

Master compound filters, amenity queries, performance-metric filters, multi-field sorting, and pagination to find exactly the listings you need.
Filter Operator Reference
OperatorDescriptionExample

eq

Equals

"bedrooms": {"eq": 3}

gt

Greater than

"rating_overall": {"gt": 4.0}

gte

Greater than or equal

"bedrooms": {"gte": 2}

lt

Less than

"ttm_occupancy": {"lt": 0.5}

lte

Less than or equal

"num_reviews": {"lte": 10}

range

Between min and max (inclusive)

"ttm_revenue": {"range": [30000, 100000]}

any

Has at least one of (lists only)

"amenities": {"any": ["pool", "hot_tub"]}

all

Has every one of (lists only)

"amenities": {"all": ["wifi", "kitchen"]}

none

Has none of (lists only)

"amenities": {"none": ["shared_room"]}

1

Basic Operators

The filter object in POST /listings/search/market supports six comparison operators: eq (equals), gt/gte (greater than), lt/lte (less than), and range([min, max]). These work on all numeric fields.

Python

import requests

# Basic filter operators: eq, gt, gte, lt, lte, range
response = requests.post(
    "https://api.airroi.com/listings/search/market",
    headers={
        "X-API-KEY": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "market": {
            "country": "us",
            "region": "florida",
            "locality": "miami",
        },
        "filter": {
            "bedrooms": {"gte": 2},
            "rating_overall": {"gte": 4.5},
            "ttm_revenue": {"range": [30000, 100000]},
        },
        "pagination": {"page_size": 10, "offset": 0},
        "currency": "usd",
    },
)

listings = response.json().get("results", [])
for listing in listings:
    print(f"{listing['listing_id']}: "
          f"{listing['bedrooms']}BR, "
          f"${listing['revenue']:,.0f}/yr, "
          f"Rating: {listing['rating_overall']}")

2

List Operators for Amenities

Amenities use three list operators: any (has at least one), all (has every one), and none (has none of). Common amenity codes include: wifi, kitchen, pool, hot_tub, air_conditioning, washer, dryer, parking, gym, beach_access, ocean_view, fireplace, ev_charger.

Python

# List operators for amenities: any, all, none

# Find listings with pool OR hot tub
response = requests.post(
    "https://api.airroi.com/listings/search/market",
    headers={
        "X-API-KEY": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "market": {
            "country": "us",
            "region": "tennessee",
            "locality": "nashville",
        },
        "filter": {
            "amenities": {"any": ["pool", "hot_tub"]},
        },
        "pagination": {"page_size": 10, "offset": 0},
        "currency": "usd",
    },
)

# Find listings with ALL of these amenities
response_all = requests.post(
    "https://api.airroi.com/listings/search/market",
    headers={
        "X-API-KEY": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "market": {
            "country": "us",
            "region": "tennessee",
            "locality": "nashville",
        },
        "filter": {
            "amenities": {
                "all": ["wifi", "kitchen", "washer", "dryer"]
            },
        },
        "pagination": {"page_size": 10, "offset": 0},
        "currency": "usd",
    },
)

# Exclude shared rooms
response_none = requests.post(
    "https://api.airroi.com/listings/search/market",
    headers={
        "X-API-KEY": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "market": {
            "country": "us",
            "region": "tennessee",
            "locality": "nashville",
        },
        "filter": {
            "amenities": {"none": ["shared_room"]},
        },
        "pagination": {"page_size": 10, "offset": 0},
        "currency": "usd",
    },
)

3

Compound Multi-Field Filters

Combine multiple filter conditions in a single request. All conditions use AND logic — every condition must be satisfied. This example finds superhosts with a pool or hot tub, 3+ bedrooms, rating above 4.5, and annual revenue over $50K.

Python

# Compound multi-field filter: combine multiple conditions
# Find superhosts with pool/hot tub, 3+ bedrooms,
# rating > 4.5, revenue > $50K

response = requests.post(
    "https://api.airroi.com/listings/search/market",
    headers={
        "X-API-KEY": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "market": {
            "country": "us",
            "region": "florida",
            "locality": "orlando",
        },
        "filter": {
            "superhost": {"eq": True},
            "bedrooms": {"gte": 3},
            "rating_overall": {"gte": 4.5},
            "ttm_revenue": {"gte": 50000},
            "amenities": {"any": ["pool", "hot_tub"]},
        },
        "sort": {
            "ttm_revenue": "desc",
        },
        "pagination": {"page_size": 10, "offset": 0},
        "currency": "usd",
    },
)

listings = response.json().get("results", [])
print(f"Found {len(listings)} matching listings")
for listing in listings:
    print(
        f"  {listing['listing_id']}: "
        f"{listing['bedrooms']}BR, "
        f"${listing['revenue']:,.0f}/yr, "
        f"Rating: {listing['rating_overall']}, "
        f"Superhost: {listing.get('superhost', False)}"
    )

4

Multi-Level Sorting

The sort object accepts multiple fields. The first field is the primary sort, and subsequent fields break ties. Use "asc" or "desc" for each field.

Python

# Multi-level sorting
# First sort by revenue (desc), then break ties by rating

response = requests.post(
    "https://api.airroi.com/listings/search/market",
    headers={
        "X-API-KEY": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "market": {
            "country": "us",
            "region": "texas",
            "locality": "austin",
        },
        "sort": {
            "ttm_revenue": "desc",
            "rating_overall": "desc",
        },
        "pagination": {"page_size": 10, "offset": 0},
        "currency": "usd",
    },
)

# Other sort strategies:

# By occupancy (highest first)
# "sort": {"ttm_occupancy": "desc"}

# By review count (most reviewed first)
# "sort": {"num_reviews": "desc"}

# By ADR (lowest first — find budget listings)
# "sort": {"ttm_avg_rate": "asc"}

# By revenue ascending (find underperformers)
# "sort": {"ttm_revenue": "asc"}

5

Performance Metric Filters

Filter on trailing-twelve-month (TTM) and last-90-day (L90D) performance metrics. Find high-performing listings or identify underperformers for competitive analysis.

Python

# Filter on performance metrics: TTM and L90D

# High performers: 70%+ occupancy, $10K+ in last 90 days
response = requests.post(
    "https://api.airroi.com/listings/search/market",
    headers={
        "X-API-KEY": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "market": {
            "country": "us",
            "region": "colorado",
            "locality": "denver",
        },
        "filter": {
            "ttm_occupancy": {"gte": 0.7},
            "l90d_revenue": {"gte": 10000},
            "ttm_avg_rate": {"range": [100, 300]},
        },
        "sort": {"ttm_revenue": "desc"},
        "pagination": {"page_size": 10, "offset": 0},
        "currency": "usd",
    },
)

high_performers = response.json().get("results", [])
print(f"High performers: {len(high_performers)}")

# Underperformers: below 50% occupancy, low revenue
response_low = requests.post(
    "https://api.airroi.com/listings/search/market",
    headers={
        "X-API-KEY": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "market": {
            "country": "us",
            "region": "colorado",
            "locality": "denver",
        },
        "filter": {
            "ttm_occupancy": {"lt": 0.5},
            "ttm_revenue": {"lt": 20000},
        },
        "sort": {"ttm_occupancy": "asc"},
        "pagination": {"page_size": 10, "offset": 0},
        "currency": "usd",
    },
)

underperformers = response_low.json().get("results", [])
print(f"Underperformers: {len(underperformers)}")

6

Pagination

The API returns up to 10 listings per request. Use page_size (1-10) and offset to page through all results. Increment offset by page_size each iteration until the results array is empty.

Python

# Pagination: page through all results
# page_size: 1-10 per request
# offset: cursor position (0, 10, 20, ...)

import requests

API_KEY = "YOUR_API_KEY"
HEADERS = {
    "X-API-KEY": API_KEY,
    "Content-Type": "application/json",
}

def fetch_all_listings(market, filters=None):
    """Paginate through all listings matching filters."""
    all_listings = []
    offset = 0
    page_size = 10

    while True:
        body = {
            "market": market,
            "pagination": {
                "page_size": page_size,
                "offset": offset,
            },
            "currency": "usd",
        }
        if filters:
            body["filter"] = filters

        response = requests.post(
            "https://api.airroi.com/listings/search/market",
            headers=HEADERS,
            json=body,
        )
        data = response.json()
        results = data.get("results", [])

        if not results:
            break  # No more results

        all_listings.extend(results)
        print(f"Fetched {len(all_listings)} listings so far...")

        offset += page_size

    return all_listings

# Usage
market = {
    "country": "us",
    "region": "california",
    "locality": "san diego",
}
filters = {
    "bedrooms": {"gte": 2},
    "ttm_revenue": {"gte": 30000},
}

listings = fetch_all_listings(market, filters)
print(f"Total: {len(listings)} listings")

Continue Learning

Keep exploring the AirROI API with these related tutorials.

Frequently Asked Questions

The maximum page_size is 10 listings per request. To retrieve more listings, use pagination by incrementing the offset parameter by the page_size value (0, 10, 20, 30, etc.) until the results array is empty.

Filterable fields include: bedrooms, baths, guests, amenities, superhost, instant_book, rating_overall, num_reviews, ttm_revenue, ttm_occupancy, ttm_avg_rate, l90d_revenue, l90d_occupancy, professional_management, room_type, and listing_type. Numeric fields support eq, gt, gte, lt, lte, and range operators. List fields like amenities support any, all, and none operators.

Yes. Add multiple fields to the filter object and they are combined with AND logic. For example, you can filter for listings with 3+ bedrooms AND rating > 4.5 AND revenue > $50K AND amenities including a pool — all in a single request.

Yes. Add multiple fields to the sort object. The first field is the primary sort, and subsequent fields break ties. For example, {"ttm_revenue": "desc", "rating_overall": "desc"} sorts by revenue first, then by rating for listings with the same revenue.

Common amenity codes include: wifi, kitchen, pool, hot_tub, air_conditioning, washer, dryer, parking, gym, beach_access, ocean_view, fireplace, and ev_charger. Use the any operator to match listings with at least one amenity, all to require every listed amenity, or none to exclude listings with specific amenities.

TTM (Trailing Twelve Months) metrics cover the last 12 months of performance data. L90D (Last 90 Days) metrics cover the most recent 90 days. These are rolling windows that update as new data becomes available, providing both long-term and recent performance views.

Ready to Build?

Get your API key and start querying with advanced filters in minutes.
made with