Field manual
How to use it
Six ways in, in the order you will probably need them. Every example on this page runs against this server, so you can press the button and see the real response rather than a mock-up.
01 — Start here
What this is
A public, no-login window onto one spatial database of Singapore open data. You give it six digits; it gives you the places around them. The same JSON feeds the pages, so anything you can see on screen you can fetch.
There is no key, no account and no rate limit you will hit by hand. If you are
building something, start at /v1/resolve and work
forward. If you are just curious, put a postal code in the box on the
front page and watch the rings populate.
02 — Resolve a postal code
Turn six digits into a point
GET /v1/resolve?postal=238859 returns the address and
the geometry for that code. Two coordinate systems come back: WGS84
latitude and longitude for display, and SVY21 X and Y in metres for anything
you want to measure.
curl "https://data.scaleupcrm.com/v1/resolve?postal=238859"
How the lookup works
The local address table answers first, in well under a millisecond. It already holds more than 13,000 Singapore addresses with their WGS84 and SVY21 coordinates, seeded from HDB geodata and topped up by the geocoder as new codes are seen. If the code has never been seen, it goes to the OpenStreetMap geocoder, and the result is written back to the table. That is why the second lookup of a code is always faster than the first.
Add ?refresh=true to force a fresh geocode and
overwrite what is cached.
03 — Ask what is nearby
Radius queries
This is the workhorse. GET /v1/nearby takes a postal
code, a radius in metres and optionally a category, and returns the points
inside it sorted by true distance.
curl "https://data.scaleupcrm.com/v1/nearby?postal=238859&radius=800&category=bus_stop"
Categories
| Category | What it covers | Source |
|---|---|---|
| bus_stop | Bus stop poles with road names | LTA |
| mrt_station | MRT and LRT stations | LTA |
| mrt_exit | Station exits | LTA |
| hawker | Hawker centres | NEA |
| food_centre | Markets and food centres | NEA |
| school | Primary and secondary schools | MOE |
Counts only
If you only need the number, /v1/rings is cheaper:
it returns the count of every category at 400 m, 800 m, 1 km and 2 km in one
round trip. This is what the ring instrument on the front page draws.
curl "https://data.scaleupcrm.com/v1/rings?postal=238859"
04 — Read the full report
One call, the whole picture
GET /v1/report/238859 assembles everything at once:
the resolved location, the counts per ring, the nearest transport, schools,
hawker centres and food centres, and the registered businesses at that postal
code, with the source and as-of date on every block.
curl "https://data.scaleupcrm.com/v1/report/238859"
The same thing renders as a page at /p/238859 — that URL is stable and shareable.
Errors
| Status | Code | What it means |
|---|---|---|
| 400 | invalid_postal | Not six digits |
| 404 | postal_not_found | Valid format, no building found |
| 404 | unknown_category | Category name not in the list above |
05 — Call it from your code
Plain JSON over HTTP
Every response is UTF-8 JSON. Distances are metres, prices would be SGD, timestamps are ISO 8601 with an offset.
Python
import requests
BASE = "https://data.scaleupcrm.com"
r = requests.get(f"{BASE}/v1/nearby",
params={"postal": "238859", "radius": 800, "category": "bus_stop"},
timeout=10)
r.raise_for_status()
for stop in r.json()["categories"][0]["items"]:
print(f'{stop["distance_m"]:>7.1f} m {stop["label"]} — {stop["detail"]}')
JavaScript
const res = await fetch(
"https://data.scaleupcrm.com/v1/rings?postal=238859"
);
const { rings, counts } = await res.json();
console.log(counts.bus_stop, "bus stops within 2 km");
From a spreadsheet
=IMPORTDATA("https://data.scaleupcrm.com/v1/resolve?postal=238859")
works in Excel and Google Sheets, for a one-off check. For a list of codes, loop
over the sheet and call /v1/rings per row.
Interactive reference
The machine-readable schema is at /v1/openapi.json, and the browsable version is at /v1/docs.
06 — The data on this server
What is loaded, and how fresh it is
The source register is live. It lists every dataset, the agency that publishes it, the row count and the date of the last successful load.
Field reference
| Field | Type | Meaning |
|---|---|---|
| postal | string | Six digit Singapore postal code |
| lat / lon | number | WGS84 degrees — for maps and display |
| x_svy21 / y_svy21 | number | SVY21 metres (EPSG:3413) — for measuring |
| distance_m | number | Straight-line metres from the building point |
| resolved_via | string | local (cached) or nominatim (fresh geocode) |
| as_of | string | ISO 8601 timestamp of the dataset state used |
| sources | array | Per module: code, agency, row count, as-of date |
07 — Attribution and licence
Credit the agency, not us
The data on this server is published by Singapore government agencies under the Singapore Open Data Licence v1.0, and address data comes from OpenStreetMap contributors under the ODbL 1.0. If you use it, say so, using this wording:
Contains information from {dataset name} accessed on {date} from data.gov.sg
which is made available under the terms of the Singapore Open Data Licence version 1.0.
Each response carries its own sources array with the
agency, the dataset code and the as-of date, so you can generate that line
per module rather than per page.
08 — What is not here yet
Honest limits
This is the live public surface of a working pipeline, not the finished product. These parts are not here, and the API will not pretend otherwise:
| Not yet | Why |
|---|---|
| Map tiles | Basemap tiles need a OneMap account key, which is not issued yet |
| Walking routes | Needs the OneMap routing API; distances are straight-line only |
| Live bus arrivals and weather | These need LTA DataMall and NEA real-time keys |
| Scores and percentiles | Not computed until the corpus is complete enough to rank against |
| Housing prices by postal code | The URA transaction mirror has no block-level geography yet |
| Every one of ~140,000 postal codes | 13,000+ addresses are cached; the full sweep is queued and fills in on demand |
Everything above is a pipeline stage, not a redesign. When a key lands, the table it feeds is already in place.