Overview
Returns a JSON array of every unit in a building that is flagged advertised_on_website: true. Use it to power a building's listings page, a unit picker on a tour-request form, or any frontend that needs an up-to-date catalog of what's available.
- One building per request, identified by its
token. - Units that aren't advertised on the website are excluded from the response.
- Units whose price is marked private (
price_advertised: false) are still returned, but withmonthly_rent_grossandmonthly_rent_netset tonull.
Authentication
There is no API key or bearer token. Each building has its own opaque token, and you pass it as a query parameter to fetch that building's units.
- A SeeClickRent admin issues the token to you when your integration is set up.
- It's the same token you'd use with the Website Leads API — one token per building, used for both reading units and posting leads.
- Treat the token like a shared secret — anyone with it can read advertised inventory for that building.
Rate limits
- 300 requests per 5 minutes per source IP across the entire
/api/*namespace. - Excess requests get an HTTP
429 Too Many Requestswith aRetry-Afterheader (in seconds) and this body:
{
"error": {
"message": "throttled",
"human_message": "Too many requests. Please try again later."
}
}
If you're rendering a high-traffic listings page, cache the response on your end (a few minutes is usually plenty — inventory doesn't change second-to-second). Contact SeeClickRent if you need a higher limit.
Request
Headers
Accept: application/json
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
token |
string | Required | Building token issued by SeeClickRent. Identifies which building's units to return. |
Example
GET /api/v1/building_units?token=abc123def456 HTTP/1.1
Host: seeclickrent.com
Accept: application/json
Response
200 OK — success
Returns a JSON array. Each element represents one advertised unit. The array is empty ([]) if the building has no units flagged for the website.
[
{
"id": 9821,
"building_id": 412,
"floor": 2,
"unit": "2A",
"bed": 1,
"bath": 1.0,
"exposure": "South",
"status": "available",
"monthly_rent_gross": 3200.0,
"monthly_rent_net": 2933.33,
"square_feet": 675,
"weeks_free": 4,
"months_free": 1,
"lease_term": 13,
"floor_plan": {
"original": "https://seeclickrent.com/rails/active_storage/blobs/.../floor-plan.pdf",
"thumbnail": "https://seeclickrent.com/rails/active_storage/representations/.../floor-plan.png"
},
"images": [
{
"original": "https://seeclickrent.com/rails/active_storage/blobs/.../living-room.jpg",
"thumbnail": "https://seeclickrent.com/rails/active_storage/representations/.../living-room.jpg"
}
],
"price_advertised": true,
"date_available": "2026-06-01",
"created_at": "2026-04-12T18:22:13.000Z",
"updated_at": "2026-05-02T10:14:55.000Z"
}
]
Field reference
Every object in the response array contains the following keys:
| Field | Type | Description |
|---|---|---|
id |
integer | SeeClickRent unit ID. Stable across requests; safe to persist as a foreign key on your side. |
building_id |
integer | SeeClickRent building ID. The same value for every unit in the response. |
floor |
integer | null | Floor number the unit is on. |
unit |
string | Unit label, e.g. "2A", "PHB". |
bed |
integer | Number of bedrooms. 0 represents a studio. |
bath |
number | Number of bathrooms. May be a half-step value, e.g. 1.5. |
exposure |
string | null | Window exposure, e.g. "North", "South/East". |
status |
string | Current leasing status of the unit (e.g. "available", "applied", "leased"). |
monthly_rent_gross |
number | null | Advertised monthly rent before concessions. null when price_advertised is false. |
monthly_rent_net |
number | null | Effective monthly rent after spreading concessions across the lease term. null when price_advertised is false. |
square_feet |
integer | string | Square footage when the building advertises it; otherwise the literal string "N/A". |
weeks_free |
integer | null | Number of free weeks offered as a concession. |
months_free |
number | null | The same concession expressed in months (derived from weeks_free). |
lease_term |
integer | null | Lease term in months that the concession is calculated against. |
floor_plan |
object | null | Floor plan attachment. See Images and floor plans. |
images |
array of objects | Unit photos in upload order. Empty array if the unit has no images. |
price_advertised |
boolean | Whether the building advertises this unit's price publicly. When false, the rent fields are blanked out (see above). |
date_available |
string (date) | null | Move-in date in YYYY-MM-DD format. |
created_at |
string (ISO 8601 datetime) | When the unit record was created in SeeClickRent. |
updated_at |
string (ISO 8601 datetime) | When the unit record was last modified. Useful for cache invalidation on your side. |
Images and floor plans
Both floor_plan and each entry in images use the same shape:
{
"original": "https://seeclickrent.com/rails/active_storage/blobs/.../photo.jpg",
"thumbnail": "https://seeclickrent.com/rails/active_storage/representations/.../photo.jpg"
}
originalis the full-resolution upload.thumbnailis a 400x400 contained variant, generated lazily on first request — the first hit may be slightly slower while it's processed; subsequent hits are served from cache.thumbnailmay benullfor non-image attachments (e.g. PDF floor plans without a renderable preview).floor_planitself isnullif no floor plan has been uploaded.- URLs are signed and long-lived but not guaranteed to be permanent — always re-fetch from this endpoint rather than caching URLs forever.
Code samples
curl -G https://seeclickrent.com/api/v1/building_units \
-H "Accept: application/json" \
--data-urlencode "token=abc123def456"
const token = "abc123def456";
const url = `https://seeclickrent.com/api/v1/building_units?token=${encodeURIComponent(token)}`;
const response = await fetch(url, {
method: "GET",
headers: { "Accept": "application/json" },
});
if (response.ok) {
const units = await response.json();
console.log(`Loaded ${units.length} units`);
} else {
console.error("Failed to load units:", response.status);
}
import requests
resp = requests.get(
"https://seeclickrent.com/api/v1/building_units",
params={"token": "abc123def456"},
headers={"Accept": "application/json"},
timeout=10,
)
if resp.status_code == 200:
units = resp.json()
print(f"Loaded {len(units)} units")
elif resp.status_code == 429:
retry_after = int(resp.headers.get("Retry-After", "60"))
print(f"Throttled, retry in {retry_after}s")
else:
print(f"Failed: {resp.status_code} {resp.text}")
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Empty array [] returned for a building you know has units |
None of the units are flagged advertised_on_website: true in SeeClickRent. |
Have your leasing team check the website-advertising flag on each unit. |
monthly_rent_gross and monthly_rent_net are null |
The unit is intentionally not advertising its price (price_advertised: false). |
If pricing should be public, flip the price-advertised toggle on the unit in SeeClickRent. |
| First load of a thumbnail is slow | Active Storage variants are generated lazily on first request. | Pre-warm by hitting the thumbnail URLs once after upload, or accept the one-time delay. |
square_feet comes back as the string "N/A" instead of a number |
The building chose not to advertise square footage for this unit. | Render "N/A" verbatim, or treat any non-numeric value as missing. |
429 Too Many Requests |
Hit the 300-per-5-minute IP throttle. | Honor the Retry-After header. Cache responses for a few minutes; contact SeeClickRent for a higher limit. |
5xx errors |
Transient server-side issue. | Retry with exponential backoff. The endpoint is read-only, so retries are safe. |
Support
For tokens, building setup, or rate-limit increases, reach out to your SeeClickRent point of contact or contact us.