Endpoints
The developer API is read-only and versioned under /v1. Two endpoints:
| Method & path | Returns |
|---|---|
GET /v1/listings | Your active listings, paginated |
GET /v1/listings/{id} | A single active listing by id |
All requests require the Authorization: Bearer <key> header — see Authentication.
Base URL
The base URL is per-country, and your API key's country prefix tells you which one to use. The apex host serves Singapore; every other country has its own regional host.
| Country (key prefix) | Base URL |
|---|---|
Singapore (sg_) | https://api.commercialunits.com |
Malaysia (my_) | https://api.my.commercialunits.com |
United Kingdom (uk_) | https://api.uk.commercialunits.com |
India (in_) | https://api.in.commercialunits.com |
United States (us_) | https://api.us.commercialunits.com |
Canada (ca_) | https://api.ca.commercialunits.com |
Australia (au_) | https://api.au.commercialunits.com |
New Zealand (nz_) | https://api.nz.commercialunits.com |
The general pattern is https://api.<cc>.commercialunits.com, where <cc> is the lowercase country code — with Singapore served by the apex api.commercialunits.com.
Use the base URL that matches your key's prefix. A key only works against its own country's host; sending a
sg_live_…key toapi.my.commercialunits.comwill be rejected.
The rest of this page uses Singapore (api.commercialunits.com) in examples.
GET /v1/listings
Returns a paginated array of your active listings, newest first (featured listings first within that ordering).
Query parameters
| Param | Type | Default | Notes |
|---|---|---|---|
page | integer | 1 | 1-based page number |
per_page | integer | 20 | 1–100; values above 100 are clamped to 100 |
Request
curl "https://api.commercialunits.com/v1/listings?page=1&per_page=20" \
-H "Authorization: Bearer sg_live_3f9aK2pLqWzXyR7vT1mN8cD4"
Response 200 OK
{
"items": [
{
"id": "8b1f3c2a-4d5e-4f6a-9b0c-1d2e3f4a5b6c",
"building_id": "a1b2c3d4-e5f6-4071-8293-a4b5c6d7e8f9",
"org_id": "0f1e2d3c-4b5a-4690-8172-635445362718",
"title": "Corner retail unit, ground floor — Suntec City",
"size_sqft": 1450.0,
"usage_types": ["Retail", "Shop"],
"price": 9.50,
"currency": "SGD",
"is_takeover": false,
"is_featured": true,
"status": "active",
"expiry_date": "2026-12-31T00:00:00Z",
"available_from": "2026-08-01T00:00:00Z",
"min_lease_tenure": "24 months",
"view_count": 312,
"inquiry_count": 18,
"building_name": "Suntec City",
"street_address": "3 Temasek Boulevard",
"images": [
"https://commercialunits.com/images/listings/8b1f3c2a/cover.jpg",
"https://commercialunits.com/images/listings/8b1f3c2a/02.jpg"
],
"cover_image_index": 0,
"url": "https://commercialunits.com/sg/listings/8b1f3c2a-4d5e-4f6a-9b0c-1d2e3f4a5b6c",
"created_at": "2026-06-10T04:22:11Z"
}
],
"page": 1,
"per_page": 20,
"total": 1,
"pages": 1
}
Envelope fields
| Field | Type | Meaning |
|---|---|---|
items | array | The listings on this page (schema below) |
page | integer | Current page number |
per_page | integer | Page size that was applied |
total | integer | Total active listings for your org in this country |
pages | integer | Total number of pages at this per_page |
To page through everything, request page=1, 2, … until page == pages.
GET /v1/listings/{id}
Returns a single listing by its id. The id is the UUID from the items[].id field of the list endpoint.
Request
curl "https://api.commercialunits.com/v1/listings/8b1f3c2a-4d5e-4f6a-9b0c-1d2e3f4a5b6c" \
-H "Authorization: Bearer sg_live_3f9aK2pLqWzXyR7vT1mN8cD4"
Response 200 OK
The bare listing object (the same schema as one element of items[]):
{
"id": "8b1f3c2a-4d5e-4f6a-9b0c-1d2e3f4a5b6c",
"building_id": "a1b2c3d4-e5f6-4071-8293-a4b5c6d7e8f9",
"title": "Corner retail unit, ground floor — Suntec City",
"size_sqft": 1450.0,
"usage_types": ["Retail", "Shop"],
"price": 9.50,
"currency": "SGD",
"status": "active",
"building_name": "Suntec City",
"street_address": "3 Temasek Boulevard",
"images": ["https://commercialunits.com/images/listings/8b1f3c2a/cover.jpg"],
"cover_image_index": 0,
"url": "https://commercialunits.com/sg/listings/8b1f3c2a-4d5e-4f6a-9b0c-1d2e3f4a5b6c",
"created_at": "2026-06-10T04:22:11Z"
}
If the id doesn't exist, isn't active, or isn't owned by your organisation, you get 404 Not Found (the API does not distinguish "not yours" from "doesn't exist", by design).
Listing schema
Every listing object (in items[] and from GET /v1/listings/{id}) has these fields:
| Field | Type | Nullable | Description |
|---|---|---|---|
id | string (UUID) | no | Stable unique id for the listing |
building_id | string (UUID) | no | The building this unit is in |
org_id | string (UUID) | yes | Your organisation id (null for individual-landlord listings) |
title | string | yes | Listing headline |
size_sqft | number | yes | Floor area in square feet |
usage_types | string[] | no | Commercial usage tags, e.g. ["F&B","Cafe"] (main type + sub-type) |
price | number | yes | Asking rent, per the listing's pricing basis (typically PSF/month) |
currency | string | no | ISO currency code for price (e.g. SGD, MYR, GBP) |
is_takeover | boolean | no | Whether this is a lease-takeover / assignment |
is_featured | boolean | no | Whether you've promoted this listing |
status | string | no | Always "active" for listings returned here |
expiry_date | string (ISO 8601) | yes | When the listing expires |
available_from | string (ISO 8601) | yes | When the space becomes available |
min_lease_tenure | string | yes | Minimum lease term, e.g. "24 months" |
view_count | integer | no | Total views on Commercial Units |
inquiry_count | integer | no | Total inquiries received |
building_name | string | yes | Building/complex name, e.g. "Suntec City" |
street_address | string | yes | Street address of the building |
images | string[] | no | Public image URLs (see below). Empty array if none |
cover_image_index | integer | no | Index into images of the cover/hero photo |
url | string | no | Canonical public listing page on commercialunits.com |
created_at | string (ISO 8601) | no | When the listing was created |
Usage types
usage_types reflects Commercial Units' hierarchical commercial taxonomy — a main type and, where set, a sub-type:
- Office → Shared Office
- F&B → Pub, Cafe, Restaurant, Cloud Kitchen
- Industrial → Food Factory, Warehouse
- Retail → Kiosk, Shop, Anchor
- Clinic
Images
images is an array of fully-qualified, public image URLs served from the Commercial Units CDN (https://commercialunits.com/images/...). They are watermarked and ready to display:
- To show a photo: drop the URL straight into
<img src="…">. No API key, no CORS, no auth needed — these are public CDN assets. cover_image_indextells you which entry is the hero/cover image (images[cover_image_index]).
See CORS & Embedding for the difference between embedding an image (no CORS) and fetching the JSON in a browser (needs CORS).
Notes & stability
- New fields may be added to a listing object over time; treat unknown fields as optional and ignore them.
- Dates are ISO 8601 in UTC (trailing
Z). nullmeans "not set";images: []means "no photos", not "omitted".- Money is split into a numeric
priceand an ISOcurrencyso you can format it for your audience.