Bring your own map

You already run MapLibre (or any renderer that reads the MapLibre style specification) and want Yatmo’s basemap and neighbourhood data without the SDK’s view. Point your map at a Yatmo style, then draw POIs and isochrones from the REST API. This is what the SDKs do internally.

Styles and tiles

Seven styles, the same as the web plugin. Each style file references the Yatmo vector tiles and glyphs, so you only need the style URL:

Name In Type Description
liberty default https://map.yatmo.com/osm_liberty.json
basic style https://map.yatmo.com/osm_basic.json
bright style https://map.yatmo.com/osm_bright.json
3d style https://map.yatmo.com/osm_3d.json (extruded buildings)
positron style https://map.yatmo.com/osm_positron.json (light grey)
dark style https://map.yatmo.com/osm_dark.json
liberty_stonehedge style https://map.yatmo.com/osm_liberty_stonehedge.json

Tiles are worldwide OpenMapTiles-schema vector tiles (tile_planet.json TileJSON, zoom 0 to 14), glyphs are served from the same tile hosts. The style and tile hosts are open, served over HTTPS with a permissive CORS policy, and cached by a CDN.

Load the style in MapLibre

// iOS, MapLibre Native
let map = MLNMapView(frame: view.bounds, styleURL: URL(string: "https://map.yatmo.com/osm_liberty.json"))
map.setCenter(CLLocationCoordinate2D(latitude: 50.8520525, longitude: 4.3442926), zoomLevel: 15, animated: false)
// Android, MapLibre Android
mapView.getMapAsync { map ->
    map.setStyle("https://map.yatmo.com/osm_liberty.json")
    map.cameraPosition = CameraPosition.Builder().target(LatLng(50.8520525, 4.3442926)).zoom(15.0).build()
}

Text labels use the map’s name:xx fields where the tiles carry them; the styles default to the local name.

Draw the POIs

When the camera settles, call GET /Points with the visible bounds and the mobile headers, and add one annotation per result:

curl "https://be.yatmo.com/Points?bound1=50.848,4.338&bound2=50.856,4.350&language=FR&groupSamePositions=true&caringForBigResponse=true" \
  -H "LicenseKey: YOUR_FRONTEND_KEY" -H "X-Yatmo-App-Id: com.myagency.homes" -H "X-Yatmo-Platform: ios"
[
  { "n": "Ecole Maternelle Christian Merveille", "t": "Preschool", "la": 50.852508, "ln": 4.343613,
    "p": "10010001000000", "i": "30", "si": "", "g": false, "rpt": "0", "sd": "{}", "fid": null },
  { "n": "STIB/MIVB - 89 - WESTLAND SHOPPING - GARE CENTRALE", "t": "Bus stop (Dansaert)", "la": 50.851241, "ln": 4.344952,
    "p": "10020001000001", "i": "60", "si": "23", "g": false, "rpt": "0", "sd": "{\"sh\":\"...\"}", "fid": null }
]

bound1 is the south-west corner and bound2 the north-east corner, as lat,lng. Fields: n name, t translated type, la / ln position, p category id, i icon id (comma separated when several POIs share the spot), si sub-icon ids (transit lines), g grouped, sd specific data as JSON text. Only request from zoom 13 upwards and debounce camera events by about 300 ms: the web plugin does both.

To filter by category, pass poiTypesIds=id1,id2 with ids from GET /SimplifiedCategories?language=FR, which returns the ids grouped by Education, Transports, Motorways, Shopping and Tourism.

POI icons

Icons are PNG files on a CDN per country, at 24 or 32 pixels with a @2x variant:

{cdn}/icons24/{i}@2x.png        marker icon, i = the "i" field
{cdn}/icons32/{i}@2x.png
{cdn}/subicons24/{si}@2x.png    transit line badge, si = each value of the "si" field
CDN base URL per country
BE https://beprod-chh6e6e9hhg8bwha.z01.azurefd.net/
FR https://frprod-atf6hrhkezbhdqem.z01.azurefd.net/
NL https://nlprod-euexhcaedwekb9g9.z01.azurefd.net/
LU https://luprod-d3azhthcdgc5d7e2.z01.azurefd.net/
CH https://chprod-ebercaa7bddnbvbz.z01.azurefd.net/
DE https://deprod.azureedge.net/
IT https://itprod2.azureedge.net/
ES https://esprod.azureedge.net/
PT https://ptprod.azureedge.net/
IE https://ieprod.azureedge.net/
UK https://ukprod.azureedge.net/
AT https://atprod.azureedge.net/
CA https://caprod-hba9fuctcmdqcfea.z01.azurefd.net/
GR https://yatmogrprod-egf4hqdje7a8f4hd.z01.azurefd.net/
MA https://yatmomaprod-ecesacfgcmc3dugj.z01.azurefd.net/
HR https://yatmohrprod-aebpfxd3crhcfeh6.z01.azurefd.net/
MT https://yatmomtprod-bveegpf9csapdcdp.z01.azurefd.net/
SI https://yatmosiprod-cxftg7d7g5bua8hv.z01.azurefd.net/
RS https://yatmorsprod-cdguargcaqcxhcgg.z01.azurefd.net/
CY https://yatmocyprod-bkg4g7f2b6hwahav.z01.azurefd.net/
BA https://yatmobaprod-d8duf5bffkdvg5b0.z01.azurefd.net/
ME https://yatmomeprod-eafne6d5g3g0h3g2.z01.azurefd.net/
BG https://yatmobgprod-dqbzcte0aeg3c2b7.z01.azurefd.net/
AL https://yatmoalprod-b4cpebdzd2cnerfu.z01.azurefd.net/
AU https://yatmoauprod-g5gfbkbjhhduewdk.z01.azurefd.net/

Cache the images on the device: the same forty icons come back on every screen.

Isochrones

GET /Isochrone/GetMultipleTimes returns the 5, 10 and 20 minute areas in one call as GeoJSON polygons, largest last, ready for a fill layer:

curl "https://be.yatmo.com/Isochrone/GetMultipleTimes?travelMode=Walking&latitude=50.8520525&longitude=4.3442926&language=FR" \
  -H "LicenseKey: YOUR_FRONTEND_KEY" -H "X-Yatmo-App-Id: com.myagency.homes"
[
  { "label": "5 min",  "iso": { "type": "Polygon", "coordinates": [[[4.34078, 50.84992], ...]] } },
  { "label": "10 min", "iso": { "type": "Polygon", "coordinates": [...] } },
  { "label": "20 min", "iso": { "type": "Polygon", "coordinates": [...] } }
]

Add them as one GeoJSON source with three features and a fill layer at 10 to 15% opacity, drawn under the POI markers. Transit isochrones can take a few seconds: show them when they arrive rather than blocking the map.

Fair use

Attribution

The basemap is built from OpenStreetMap data with the OpenMapTiles schema. Keep an attribution control visible or a line in your app’s about screen: “© OpenStreetMap contributors, © OpenMapTiles, © Yatmo”. The SDKs show it by default.

Related: Custom map UI recipe (web) · iOS SDK · Android SDK · Overview.