Docs
Sites API

Properties

Property cards for search and listing pages, the property page in one call, and its neighborhood, reviews and Instagram feed.

Listing properties

GET /properties — the website's enabled properties as cards, in the website's own order unless sorted. On a property website this is the one property. Tags: site, plus property:{id} and inventory:{id} per property on the page.

Parameter
qName contains
groupA group id; includes descendants. Unknown id is a 404
city, stateExact, case-insensitive. Values come from GET /facets
availableHas (true) or lacks (false) an available unit
bedsBedroom counts, comma-separated; matches a property with an enabled floor plan of that size
min_rent, max_rentBudget bounds, matched against available units
near, radiusnear=30.2672,-97.7431, radius in kilometres (default 25). A bounding box, not a great-circle distance
sortname, order
page, per_pageDefault 50, ceiling 200

The card

{
  "id": "01000000-0000-4000-8000-000000000002",
  "slug": "contract-property",
  "name": "Contract Property",
  "path": "/property/contract-property",
  "address": { "street": "100 Contract Way", "street_2": null, "city": "Austin", "county": "Travis", "state": "TX", "postal_code": "78701", "country": "US", "formatted": "100 Contract Way, Austin, TX, 78701, US" },
  "location": { "lat": 30.2672, "lng": -97.7431 },
  "timezone": "America/Chicago",
  "image": null,
  "phone": "+1 555 0100",
  "rating": { "average": 4.5, "count": 2 },
  "tags": [],
  "units_count": 1,
  "available_units_count": 1,
  "floor_plans_count": 1,
  "rent": { "min": 1500, "max": 1500, "base_min": 1500, "base_max": 1500 },
  "pricing_display": {
    "mode": "BASE_AND_TOTAL",
    "hidden_price_label": "Call for Pricing",
    "no_availability_price_label": "Call for Availability",
    "no_price_label": "Call for Pricing",
    "total_price_label": "Total Monthly Leasing Price"
  }
}
  • Counts and rent bounds come from enabled, unhidden units; rent from the available ones.
  • image is the property's own image; when it has none, an image from its first enabled image gallery (one tagged exterior if there is one, else the first). rating is the overall { average, count }. Between them a listing page needs no galleries or reviews request per property.
  • location is null when a coordinate is missing — never 0,0.
  • timezone is the property's IANA timezone. Use it for office hours, "open now" and tour times; null when the property has no address.
  • rent values are null when the property's pricing display settings hide them, or when no rent is known. Show a label from pricing_display instead: hidden_price_label when the property hides all pricing, no_availability_price_label when it hides prices with nothing available and available_units_count is 0, no_price_label otherwise. See Inventory & pricing.

Rent filters never reveal a hidden price. When min_rent or max_rent is used, a property that hides its pricing is left out of the results rather than matched silently.

One property

GET /properties/{property} — the card, the property's details, and whichever sections the page renders, in one call. Tags: property:{id}, inventory:{id}.

Parameter
includeComma-separated: amenities, announcements, buildings, content, faqs, fees, galleries, groups, media, office_hours. Unknown is a 422
content_keysWith include=content: the block keys to return, comma-separated

Always present, beyond the card:

KeyHolds
descriptionThe property's marketing description
contactphones[], emails[], socials[]
urlswebsite, resident_portal, application, tour_booking
leasingapplicant_hold_period_days, availability_window_days
pet_policydescription, restrictions
pricingThe property's pricing display settings: pricing_display_mode, hide_all_pricing, hide_price_when_no_availability, hidden_price_label, no_availability_price_label, no_price_label, tmlp_label, show_fee_breakdown, fee_breakdown_behavior (EXPANDED or COLLAPSED), pricing_disclaimer_text. The API has already applied them to every price it returns. See Inventory & pricing
hasWhich sections hold anything

has: skip what is empty

"has": { "amenities": true, "announcements": true, "buildings": true, "content": true, "faqs": true, "galleries": true, "neighborhood": true, "reviews": true, "instagram": true, "floor_plans": true, "available_units": true }

has is always filled in, whatever you include. Read it to decide which sections to render, and which sub-resources are worth a request.

Included sections

Every includable key is always in the payload, and is null when not requested, so the shape never depends on the query string.

includeReturns
amenitiesid, name, code, description, type, is_marketable, tags, images[], videos[], virtual_tours[]
announcementsThose current now: key (the identifier a template places it by), title, meta, text, disclaimer, image, links[], starts_at, ends_at
buildingsnumber, code, name, type, description, image, images[], available_units_count, tags, groups[]
contentContent blocks: key, type, media_type, title, subtitle, description, links[], images[], background_image, videos[], virtual_tours[], and items[] for multi-item blocks
faqsquestion, answer, tags, sort_order, and topic (id, title, description, sort_order, or null) — group by topic.id, order topics and questions by their sort_order
feesThe property-wide fee schedule: lines[], monthly_total, monthly_total_max, upfront_total. Empty lines and null totals when pricing is hidden
gallerieskey (the identifier a template places it by), type (image, video, panorama, virtual_tour), title, text, images[], panoramas[], videos[], virtual_tours[]
groupsThe groups the property belongs to, each with its set
mediaThe property's own media, apart from its galleries: property_images[] (the card's image is the first), images[], background_image, videos[], virtual_tours[]
office_hoursThe property's office hours settings: hours[] (day, time, both free text as entered, such as Monday - Friday and 9:00 AM - 5:00 PM), display_heading, disclaimer
curl "$RESI_DELIVERY_API_URL/properties/contract-property?include=amenities,content,faqs&content_keys=hero,highlights" \
  -H "Authorization: Bearer $RESI_DELIVERY_TOKEN" -H "X-Resi-Website: $RESI_WEBSITE_ID"

An image anywhere in the API is { id, url, thumb_url, title, caption, alt_text, tags }. tags are the image's media-library tags ([] when none), for filtering a gallery to, say, exterior or pool. panoramas[] holds images in the same shape, meant for a 360° viewer; an image can appear in both images and panoramas.

Neighborhood

GET /properties/{property}/neighborhood?limit=100 — tag property:{id}. limit is 1–500, default 100, by name; meta.places gives { total, listed }.

  • origin — the property's name, address and location, for centring a map.
  • categories[] — the account's categories: id, label, color, types, and in_use (whether any place below uses it).
  • places[] — name, address, location, category_id, category, color, rating, website, google_maps_url, place_id, tags, images[], and travel_times (drive, walk, bike, transit, in minutes, null when unknown).

Reviews

GET /properties/{property}/reviews — published reviews, newest first. Tag property:{id}.

Parameter
sourceReview sources, comma-separated (for example google_business_profile)
rating[gte]Range operators gte, lte, gt, lt
sortdate, rating
page, per_pageDefault 20, ceiling 100

Each review carries reply — { text, replied_at } for the property's published response, or null.

meta.rating always carries the property's overall { average, count }, regardless of the filters applied, so a "4.5 from 212 reviews" badge needs no second request.

Instagram

GET /properties/{property}/instagram?limit=12 — the most recent posts (limit 1–50). An empty list, not an error, when the property has no enabled Instagram connection. Each post: type, caption, hashtags[], permalink, posted_at, and media[] of { type, url, thumbnail_url }.

Last updated on

On this page