Open Landmarks

Open Landmarks / Documentation

API reference

Discover landmarks by location and download their models, metadata and editable sources.

Base URLhttps://open-landmarks.benmaps.fr

No API key required. All resources support GET, HEAD and cross-origin reads. Resolve returned paths against the base URL.

Resolve the global approved or preview channel, then request tiles from its catalogue. Fetch model files only when needed.

Get a release

GET/api/v1/{channel}.json

Resolves a channel to its current release. Save the returned catalogue path to pin that release.

Path parameters channel — latest for approved models, or preview to include drafts.

200 OK · application/json
A release pointer. A channel with nothing published returns 200 with release: null, catalogue: null and count: 0 — treat that as "not yet released" rather than an empty release. The current submissions have 24 approved models and 88 models in preview.

FieldTypeDescription
schemaVersionintegerResponse schema version.
channelstringapproved for latest.json; preview for preview.json.
releasestring | nullImmutable release ID, or null when nothing is published.
countintegerNumber of models in this release.
cataloguestring | nullPath to the pinned catalogue, or null when nothing is published.
Response example
{
  "schemaVersion": 1,
  "channel": "preview",
  "release": "preview-7bd48fe030ad21eb2280",
  "count": 88,
  "catalogue": "/api/v1/releases/preview-7bd48fe030ad21eb2280/catalogue.json"
}

Cache: 60 seconds · revalidate. Open example ↗

Get a catalogue

GET/api/v1/releases/{release}/catalogue.json

Returns spatial index information and links to the full dataset.

Path parameters release — exact release ID returned by a pointer.

200 OK · application/json
A catalogue for the requested release.

FieldTypeDescription
schemaVersion / release / channel / countinteger / stringSchema version, release ID, channel and model count, as in the release pointer.
statusstringapproved-only or includes-unreviewed-drafts.
assetBasestringOrigin-relative asset root.
boundsnumber[4]Dataset extent: [west, south, east, north], WGS84 degrees.
maxHeightMnumberMaximum model height in metres; useful for padding discovery.
minZoomnumberLowest member display zoom; resolve metadata once, then defer index requests below this zoom.
index.zoomintegerFixed index zoom; currently 12.
index.templatestringTile path template with {x} and {y} placeholders.
index.occupiedstring[]Available cells, each formatted as "x/y".
assetsstringPath to all model metadata in this release.
sourceDatabasestringPath to the complete spatial source database.
attribution / dataLicensestringDataset credit and spatial data license.
Response example
{
  "schemaVersion": 1,
  "release": "preview-7bd48fe030ad21eb2280",
  "channel": "preview",
  "count": 88,
  "status": "includes-unreviewed-drafts",
  "assetBase": "/",
  "materialLibrary": {
    "schemaVersion": 1,
    "sha256": "7afc40cf0b82b7c3c054f287817be2a37e52192aa734f187f8b20ee3277187dd",
    "url": "/materials/7afc40cf0b82b7c3c054f287817be2a37e52192aa734f187f8b20ee3277187dd.json"
  },
  "bounds": [
    -122.4809672,
    37.7724394,
    2.3985133,
    51.5147302
  ],
  "maxHeightM": 330,
  "minZoom": 13,
  "attribution": "Open Landmarks; © OpenStreetMap contributors",
  "dataLicense": "ODbL-1.0",
  "index": {
    "zoom": 12,
    "template": "/api/v1/releases/preview-7bd48fe030ad21eb2280/index/12/{x}/{y}.json",
    "occupied": [
      "2046/1362",
      "2047/1361",
      "2073/1408",
      "2073/1409",
      "2074/1408",
      "2074/1409",
      "2075/1408",
      "2075/1409",
      "654/1582",
      "654/1583",
      "655/1582",
      "655/1583"
    ]
  },
  "assets": "/api/v1/releases/preview-7bd48fe030ad21eb2280/assets.json",
  "sourceDatabase": "/api/v1/releases/preview-7bd48fe030ad21eb2280/spatial-database.json"
}

Cache: 1 year · immutable. Open example ↗

Get a tile

GET/api/v1/releases/{release}/index/12/{x}/{y}.json

Returns metadata for whole models whose ground bounding boxes intersect an XYZ cell.

Path parameters release — exact release ID returned by a pointer. x, y — integer Web Mercator tile coordinates at zoom 12 (0–4095). Use cells listed in index.occupied.

200 OK · application/json
A tile containing model entries. Unoccupied cells return 404. Entries contain placement, download and attribution fields; full provenance is available at each entry’s metadata path.

FieldTypeDescription
schemaVersionintegerResponse schema version.
releasestringPinned release ID.
assetsobject[]Model entries; see metadata fields below.
Response example · selected fields
{
  "schemaVersion": 1,
  "release": "preview-7bd48fe030ad21eb2280",
  "assets": [
    {
      "id": "elizabeth-tower",
      "revision": "a753f2b89a4c25178256c3de24e6c84cd436d600d63ea7ccc69377133f7cdbd9",
      "anchor": [
        -0.12457352696457669,
        51.500700465991045
      ],
      "minZoom": 15,
      "detailZoom": 17,
      "metadata": "/assets/elizabeth-tower/b910cdfc2a7e4a309b85071fd272c7905a1cc83173051e62b00518ff68bc6c3a/asset.json",
      "lods": {
        "low": {
          "url": "/models/elizabeth-tower/073f09850da39f08fa5bb4b5b7a4036360ddaba0e46fc1dab4aab9994ca2d674/low.glb",
          "bytes": 205680,
          "sha256": "073f09850da39f08fa5bb4b5b7a4036360ddaba0e46fc1dab4aab9994ca2d674",
          "triangles": 4746,
          "gzip": {
            "url": "/models/elizabeth-tower/073f09850da39f08fa5bb4b5b7a4036360ddaba0e46fc1dab4aab9994ca2d674/low.glb.gz",
            "bytes": 67219,
            "sha256": "58286788e3e4a02b685f243d05ededfbe92f5f848bf084f586b8709e53dec9b3",
            "encoding": "gzip-file"
          }
        },
        "detail": {
          "url": "/models/elizabeth-tower/cfc00bc16755d9dd8a989f1751ecb62deeec44f44c98a21a50db111bc462aaf3/detail.glb",
          "bytes": 1431068,
          "sha256": "cfc00bc16755d9dd8a989f1751ecb62deeec44f44c98a21a50db111bc462aaf3",
          "triangles": 33510,
          "gzip": {
            "url": "/models/elizabeth-tower/cfc00bc16755d9dd8a989f1751ecb62deeec44f44c98a21a50db111bc462aaf3/detail.glb.gz",
            "bytes": 419553,
            "sha256": "762e8028e28ea129d7596262cc53a6c7ddae8e9f4813c20c6d57484bd4a7401d",
            "encoding": "gzip-file"
          }
        }
      }
    },
    {
      "id": "london-eye",
      "revision": "630cc43535a4d4086917c767925405d11b8682f94f285367139c9f1404d8fe81",
      "anchor": [
        -0.1196765,
        51.503341600000006
      ],
      "minZoom": 15,
      "detailZoom": 17,
      "metadata": "/assets/london-eye/9e762d5406a3f1e1e7c97c6ee5ab28481713f9b2951af8a6bee17eb4f771a3c0/asset.json",
      "lods": {
        "low": {
          "url": "/models/london-eye/720e9fee1ab7dd29cbe465c156ccd22efe2e680890cdb498c5b30b7dc6dc2404/low.glb",
          "bytes": 141076,
          "sha256": "720e9fee1ab7dd29cbe465c156ccd22efe2e680890cdb498c5b30b7dc6dc2404",
          "triangles": 6678,
          "gzip": {
            "url": "/models/london-eye/720e9fee1ab7dd29cbe465c156ccd22efe2e680890cdb498c5b30b7dc6dc2404/low.glb.gz",
            "bytes": 81211,
            "sha256": "939f5fc94525d2b8f8d71ef8f69afe35c0c7ea7063446863a23aa1b958db89f9",
            "encoding": "gzip-file"
          }
        },
        "detail": {
          "url": "/models/london-eye/83267b7584aec63b539b7bd96f76996b26a2d4fc50fd041008b4920de4eeb2b9/detail.glb",
          "bytes": 706164,
          "sha256": "83267b7584aec63b539b7bd96f76996b26a2d4fc50fd041008b4920de4eeb2b9",
          "triangles": 37558,
          "gzip": {
            "url": "/models/london-eye/83267b7584aec63b539b7bd96f76996b26a2d4fc50fd041008b4920de4eeb2b9/detail.glb.gz",
            "bytes": 392625,
            "sha256": "05f6af90ed0e350f41a79885c983d95cf24dcf8ac7e951c42fc7bb0cb7c4f26d",
            "encoding": "gzip-file"
          }
        }
      }
    },
    {
      "id": "nelsons-column",
      "revision": "ce345a78e44bbe4c688c01b140fe765c1d0e604c15bbb2c138e0a0077292c1d4",
      "anchor": [
        -0.12792960922045085,
        51.50775729907043
      ],
      "minZoom": 15,
      "detailZoom": 17,
      "metadata": "/assets/nelsons-column/f45c9f422ea032d38e915dff659cc70a0b0d3277e5c4d214aaf9f97bdeddfca5/asset.json",
      "lods": {
        "low": {
          "url": "/models/nelsons-column/71d2cb95a98738c192b138b9ef668d55e443a249ee9d06d37f539cf8bedccdee/low.glb",
          "bytes": 64600,
          "sha256": "71d2cb95a98738c192b138b9ef668d55e443a249ee9d06d37f539cf8bedccdee",
          "triangles": 2848,
          "gzip": {
            "url": "/models/nelsons-column/71d2cb95a98738c192b138b9ef668d55e443a249ee9d06d37f539cf8bedccdee/low.glb.gz",
            "bytes": 31435,
            "sha256": "90bd9c0bd1447ef4ae5ae4b80a9a59cb4cdd2f0fcb19f8e7b6e5280954d06f93",
            "encoding": "gzip-file"
          }
        },
        "detail": {
          "url": "/models/nelsons-column/a2a1138a7e3b3f5434f423d1d5d0f9daed64c5ecc8fcf365651a9c7c41713a08/detail.glb",
          "bytes": 293112,
          "sha256": "a2a1138a7e3b3f5434f423d1d5d0f9daed64c5ecc8fcf365651a9c7c41713a08",
          "triangles": 13352,
          "gzip": {
            "url": "/models/nelsons-column/a2a1138a7e3b3f5434f423d1d5d0f9daed64c5ecc8fcf365651a9c7c41713a08/detail.glb.gz",
            "bytes": 143959,
            "sha256": "bc23ecd960414c19e4baf35a1fde1f1890776c9d03308e17d538a92e8c76d2f8",
            "encoding": "gzip-file"
          }
        }
      }
    },
    {
      "id": "palace-of-westminster",
      "revision": "601479b75470f7b8310288036a80e78c2f4dc2faa421e32fe2e837f1d9ac2332",
      "anchor": [
        -0.1246865838037018,
        51.49935725233581
      ],
      "minZoom": 15,
      "detailZoom": 17,
      "metadata": "/assets/palace-of-westminster/9a294063534c355ae32e1bd4a22601f480997bb5972ccdf770420a1e5e5fb066/asset.json",
      "lods": {
        "low": {
          "url": "/models/palace-of-westminster/4b2d578e7a33abef6760a850a9510e0ba0a37df721b97463e1449f9b9cb43b8b/low.glb",
          "bytes": 249620,
          "sha256": "4b2d578e7a33abef6760a850a9510e0ba0a37df721b97463e1449f9b9cb43b8b",
          "triangles": 5176,
          "gzip": {
            "url": "/models/palace-of-westminster/4b2d578e7a33abef6760a850a9510e0ba0a37df721b97463e1449f9b9cb43b8b/low.glb.gz",
            "bytes": 90272,
            "sha256": "4cc85402ac4b182d5c81bc5f6cf98e24e7432eb15f1b395c8884d1b73c0227e9",
            "encoding": "gzip-file"
          }
        },
        "detail": {
          "url": "/models/palace-of-westminster/eb9baac16ca2163d920b4e6ee5656e7371966b46c1e8b741f5d4be1e16e7f24b/detail.glb",
          "bytes": 1449028,
          "sha256": "eb9baac16ca2163d920b4e6ee5656e7371966b46c1e8b741f5d4be1e16e7f24b",
          "triangles": 32538,
          "gzip": {
            "url": "/models/palace-of-westminster/eb9baac16ca2163d920b4e6ee5656e7371966b46c1e8b741f5d4be1e16e7f24b/detail.glb.gz",
            "bytes": 513226,
            "sha256": "63349b9334d2369d3796024f5004174fa5d5f3fe0ad86527a0610ad18f2fe411",
            "encoding": "gzip-file"
          }
        }
      }
    }
  ]
}

Cache: 1 year · immutable. Open example ↗

Request occupied cells intersecting a padded viewport. Models can appear in several cells; deduplicate by id and revision. Account for camera pitch and tall buildings, then cull against 3D bounds.

Get model metadata

GET/assets/{id}/{publicationRevision}/asset.json

Returns placement, downloads, provenance and review information for one model. Follow the metadata path from a tile or the full dataset response.

Path parameters id — model ID. publicationRevision — metadata revision from the model entry.

200 OK · application/json
A model metadata object.

FieldTypeDescription
id / namestringStable model ID and display name.
revision / publicationRevisionstringContent revision; metadata revision also includes review state.
approvedbooleanWhether this exact content revision has been approved.
anchornumber[2]WGS84 [longitude, latitude].
axes / units / headingstring / numberGLB orientation and units. Heading is baked into the geometry.
boundsnumber[4]Ground bounding box: [west, south, east, north].
boundsBlenderMnumber[2][3]Local [min, max] corners, X east / Y north / Z up, in metres.
minZoom / detailZoomnumberSuggested display and detail-LOD zoom thresholds.
lods.low / lods.detailobjectRaw GLB url, bytes, sha256, triangles and a gzip download descriptor.
source / spatialSource / previewobjectDownload descriptors: url, bytes and sha256. Files use independent content hashes under /objects/.
metadata / validationstringPaths to this metadata and its structural validation report.
replacementFootprint / basemapReplacementobjectFootprint and optional dataset-specific extrusion replacement hints.
entranceLightsnumber[][3]Optional local light anchors in GLB axes.
authors / attribution / artisticLicense / spatialDataLicense / licenseScopearray / stringAuthorship, credits and component licensing.
wikidata / modelSourcesstring / arrayOptional Wikidata Q-ID and imported geometry provenance: source authors, original-file hashes, licenses and modifications.
osm / references / assistance / reviewobject / array / stringSource provenance, reference credits, assistance disclosure and review record.
Response example · selected fields
{
  "id": "elizabeth-tower",
  "name": "Elizabeth Tower",
  "revision": "a753f2b89a4c25178256c3de24e6c84cd436d600d63ea7ccc69377133f7cdbd9",
  "publicationRevision": "b910cdfc2a7e4a309b85071fd272c7905a1cc83173051e62b00518ff68bc6c3a",
  "approved": false,
  "anchor": [
    -0.12457352696457669,
    51.500700465991045
  ],
  "axes": "X east / Y up / Z south",
  "units": "metres",
  "heading": 0,
  "minZoom": 15,
  "detailZoom": 17,
  "boundsBlenderM": [
    [
      -7.490651607513428,
      -7.439363956451416,
      0
    ],
    [
      7.542989730834961,
      7.59157133102417,
      96
    ]
  ],
  "lods": {
    "low": {
      "url": "/models/elizabeth-tower/073f09850da39f08fa5bb4b5b7a4036360ddaba0e46fc1dab4aab9994ca2d674/low.glb",
      "bytes": 205680,
      "sha256": "073f09850da39f08fa5bb4b5b7a4036360ddaba0e46fc1dab4aab9994ca2d674",
      "triangles": 4746,
      "gzip": {
        "url": "/models/elizabeth-tower/073f09850da39f08fa5bb4b5b7a4036360ddaba0e46fc1dab4aab9994ca2d674/low.glb.gz",
        "bytes": 67219,
        "sha256": "58286788e3e4a02b685f243d05ededfbe92f5f848bf084f586b8709e53dec9b3",
        "encoding": "gzip-file"
      }
    },
    "detail": {
      "url": "/models/elizabeth-tower/cfc00bc16755d9dd8a989f1751ecb62deeec44f44c98a21a50db111bc462aaf3/detail.glb",
      "bytes": 1431068,
      "sha256": "cfc00bc16755d9dd8a989f1751ecb62deeec44f44c98a21a50db111bc462aaf3",
      "triangles": 33510,
      "gzip": {
        "url": "/models/elizabeth-tower/cfc00bc16755d9dd8a989f1751ecb62deeec44f44c98a21a50db111bc462aaf3/detail.glb.gz",
        "bytes": 419553,
        "sha256": "762e8028e28ea129d7596262cc53a6c7ddae8e9f4813c20c6d57484bd4a7401d",
        "encoding": "gzip-file"
      }
    }
  },
  "source": {
    "url": "/objects/37b6f0f248a7396b1de686b6d23fd569bcda2fe9e1790f626550cc59699af05a/source.blend.gz",
    "bytes": 763794,
    "sha256": "37b6f0f248a7396b1de686b6d23fd569bcda2fe9e1790f626550cc59699af05a"
  },
  "spatialSource": {
    "url": "/objects/dd860be52fb2944ea153b8091881803b6ad6616fc1e6da26b74286cf7e5ac9ae/spatial-source.json",
    "bytes": 60254,
    "sha256": "dd860be52fb2944ea153b8091881803b6ad6616fc1e6da26b74286cf7e5ac9ae"
  },
  "attribution": "Open Landmarks; contains © OpenStreetMap contributors, ODbL-1.0; Architectural measurements from the linked official sources",
  "artisticLicense": "CC-BY-4.0",
  "spatialDataLicense": "ODbL-1.0"
}

Cache: 1 year · immutable. Open example ↗

Download a model

GET/models/{id}/{sha256}/{lod}.glb

Returns a complete, texture-free glTF binary. Use the download URL from lods.low or lods.detail.

Path parameters id — model ID. sha256 — hash of the raw GLB. lod — low or detail.

200 OK · model/gltf-binary
Binary GLB bytes. Append .gz for the explicit gzip file (application/gzip, no Content-Encoding); decompress it once before loading. The gzip descriptor gives the compressed size and hash.

Cache: 1 year · immutable. Open example ↗

JavaScript · download and decompress
const origin = 'https://open-landmarks.benmaps.fr';
const response = await fetch(new URL(asset.lods.detail.gzip.url, origin));
if (!response.ok) throw new Error('Model request failed');
const bytes = await new Response(response.body.pipeThrough(
  new DecompressionStream('gzip')
)).arrayBuffer();
// Pass bytes to a glTF loader.

Use the raw GLB where native gzip decompression is unavailable. V1 needs no Draco, Meshopt or texture decoder. Retain the current LOD until its replacement has loaded.

Dataset and sources

These GET resources also cache for one year. Follow their paths from the catalogue or model metadata.

FieldTypeDescription
catalogue.assetsJSON{schemaVersion, release, assets} with complete model metadata. Open example ↗
catalogue.sourceDatabaseJSON{license, attribution, assets} with OSM-derived source records. Open example ↗
asset.source.urlgzip fileEditable Blender source; decompress before opening.
asset.spatialSource.urlJSONPer-model OSM spatial source extract.
asset.preview.urlWebPStatic model preview.
asset.validationJSONStructural validation report.

There is one global dataset. No collection parameter is needed.

HTTP behavior

FieldTypeDescription
200 OKsuccessResource exists. HEAD returns headers without a response body.
304 Not ModifiedcacheA conditional request can reuse the cached representation.
404 Not FounderrorUnknown resource, release, model or unoccupied tile. Error bodies are not a defined JSON schema.

The release pointers revalidate after 60 seconds. Release data, model files and source revisions cache for one year and retain their URLs. JSON can use negotiated HTTP compression; explicit .gz files require client decompression. V1 has no server-side search or query filters.

Placement and attribution

GLB vertices use metres, X east / Y up / Z south. Ordinary ground-relative models add terrain elevation once; models with terrainPlacement.datum: "sea-level" use their explicit elevationM instead. Do not reapply heading. Convert boundsBlenderM to GLB axes before culling; use the full bounds for long bridges.

FieldTypeDescription
terrainComponentsobjectOptional explicit per-vertex building ownership and bounded component grounding. Each building moves rigidly to its own sampled floor; basement ends meet the slope. Restore flat-ground geometry when terrain is disabled and preserve native buildings while terrain samples are unavailable.
kindstringOptional model category; bridge models declare "bridge".
terrainPlacementobjectOptional explicit sea-level origin and bounded terrain contact zones. Contact heights are local to the origin; apply only the declared shore transitions and support skirts. Keep the rigid span at its authored elevation.
bridgeReplacementobjectOptional road source-layer, exact names and line coverage threshold. Replace matching road lines only while the bridge is resident and terrain placement is supported. Preserve approach continuations outside the footprint and restore the native roads on unloading or failure.

Preserve material base colors and adapt light and emissive intensity to your scene. Suppress overlapping basemap extrusions after the model loads. basemapReplacement IDs apply only to the named dataset snapshot.

Retain each model’s attribution and source links, including © OpenStreetMap contributors. See licensing and attribution for component terms.