PostalLens SG

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.

One thing to know up front. A postal code is a delivery address, not a location. Every distance here is measured from a single resolved building point, and every response tells you how that point was obtained.

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

CategoryWhat it coversSource
bus_stopBus stop poles with road namesLTA
mrt_stationMRT and LRT stationsLTA
mrt_exitStation exitsLTA
hawkerHawker centresNEA
food_centreMarkets and food centresNEA
schoolPrimary and secondary schoolsMOE

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

StatusCodeWhat it means
400invalid_postalNot six digits
404postal_not_foundValid format, no building found
404unknown_categoryCategory 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.

Loading the source register…

Field reference

FieldTypeMeaning
postalstringSix digit Singapore postal code
lat / lonnumberWGS84 degrees — for maps and display
x_svy21 / y_svy21numberSVY21 metres (EPSG:3413) — for measuring
distance_mnumberStraight-line metres from the building point
resolved_viastringlocal (cached) or nominatim (fresh geocode)
as_ofstringISO 8601 timestamp of the dataset state used
sourcesarrayPer module: code, agency, row count, as-of date
Distances are straight-line. They are computed in SVY21, so they are exact planar metres rather than great-circle approximations — but they are not walking routes. Nothing on this portal estimates a walk time.

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 yetWhy
Map tilesBasemap tiles need a OneMap account key, which is not issued yet
Walking routesNeeds the OneMap routing API; distances are straight-line only
Live bus arrivals and weatherThese need LTA DataMall and NEA real-time keys
Scores and percentilesNot computed until the corpus is complete enough to rank against
Housing prices by postal codeThe URA transaction mirror has no block-level geography yet
Every one of ~140,000 postal codes13,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.