Retrieve Venues

The Who’s On First API allows you to query and retrieve Who’s On First data including venue data via a REST-ish interface.

In this tutorial, you will use the API to retrieve venues in New York City's Flatiron District and display them on a map. To do this, you will:

  1. Create a Map
  2. Find Info With Spelunker
  3. Retrieve Data using the API
  4. Display the data

Step 1: Create a Map

We are going to utilize mapzen.js to make our initial map.

To do this, we need to create a html page. Within that page, we use the code below to create the map.

  <!DOCTYPE html>
<html lang="en">
  <head>
    <title>My Web Map</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://mapzen.com/js/mapzen.css">
    <script src="https://mapzen.com/js/mapzen.min.js"></script>
    <style>
      #map {
        height: 100%;
        width: 100%;
        position: absolute;
      }
      html,body{margin: 0; padding: 0;}
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script>
      L.Mapzen.apiKey = 'your-mapzen-api-key';
      var map = L.Mapzen.map('map', {
        tangramOptions: {
          scene: {
            import: [
              'https://mapzen.com/carto/refill-style/8/refill-style.zip', 'https://mapzen.com/carto/refill-style/8/themes/color-gray.zip'
          ] } }
      });
      map.setView([40.741331,-73.989332], 19);
    </script>
  </body>
</html>

To learn more about mapzen.js, check out it's Get Started tutorial.

Step 2: Find Info With Spelunker

Now, we need some background info (WOF ID, latitude, longitude, etc...) to best utilize the API. To do this, we are going to take a look at the Spelunker.

Search for Flatiron District New York in the Spelunker. Find the one that is the locality in the United States. You should find the page below.

Note the wof id. You can find it if you scroll down, it also the number located near the top of the page preceded by / and followed by .geojson. For the Flatiron District, this is 85869245.

Also, verify that you map is centered on the the right coordinates and the level is set correctly. For our purposes, we are going to level 19.

  <script>
  L.Mapzen.apiKey = 'your-mapzen-api-key';
  var map = L.Mapzen.map('map');
  map.setView([40.741331,-73.989332], 19);
</script>

Step 3: Retrieve Data using the API

To retrieve data using the API, we are going to utilize the mapzen.whosonfirst.api.js file.

Add the script to your html file.

<script src="mapzen.whosonfirst.api.js"></script>

Also add jquery we are going to use that later.

<script src="jquery.min.js"></script>

This script will allow you to make the queries available through the WOF API.

Add the following helper function to make those calls from your html file. Note that we are using the whosonfirst.places.getDescendants API method. We include geom: so we are able to obtain information about the venue.

  function runWhosOnFirstAPI() {
// Setup the API key
mapzen.whosonfirst.api.set_handler('authentication', function() {
  return 'your-mapzen-key';
});

// See: https://mapzen.com/documentation/wof/methods/#whosonfirst.places.getDescendants
// San Francisco's WOF ID
var parent_id = '85869245';
var method = 'whosonfirst.places.getDescendants';
var data = {
  id: '85869245',
  per_page: 500,
  extras: 'geom:', // this gets us lat/lng coords
};

// Ok now we actually call the API
mapzen.whosonfirst.api.execute_method_paginated(method, data, onsuccess, onerror, onprogress);
};

Add the following helper functions. Not that the show_venue function has not yet been created.

  // NOOP (we are using onprogress instead)
var onsuccess = function() { return; };

// Just log errors to the JS console
var onerror = function(rsp) {
  console.error(rsp);
};

// Take all the API results and show them on the map
var onprogress = function(rsp) {
  //console.log(rsp);
  for (var i = 0; i < rsp.places.length; i++) {
    var place = rsp.places[i];
    show_venue(place);
  }
};

Step 4: Display the Data

Now we are going to display the data. To do this, we are going to write a show_venue function. The show_venue function takes a place's latitude and longitude and stylizes it as a circle with a fill and stroke using the marker style. For our purposes, we have selected a shade of grey.

  // Venues are shown as a green circle
var markerStyle = {
  "weight": 2,
  "opacity": .6,
  "fillOpacity": .2,
  "radius": 9,
  "fillColor": "#888888",
  "color": "#888888"
};

// How we should handle each API result
var show_venue = function(place) {
  var marker = L.circleMarker({
    lat: place['geom:latitude'],
    lng: place['geom:longitude']
  }, markerStyle);
  map.addLayer(marker);
};

Your code should now resemble:

  <!DOCTYPE html>
<html lang="en">
  <head>
    <title>My Web Map</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://mapzen.com/js/mapzen.css">
    <script src="https://mapzen.com/js/mapzen.min.js"></script>
    <style>
      #map {
        height: 100%;
        width: 100%;
        position: absolute;
      }
      html,body{margin: 0; padding: 0;}
    </style>
  </head>
  <body onload="runWhosOnFirstAPI()">
    <div id="map"></div>
    <script src="../javascript/mapzen.whosonfirst.api.js"></script>
    <script src="../javascript/jquery.min.js"></script>
    <script>
    L.Mapzen.apiKey = 'mapzen-aetZmeQ';
    var map = L.Mapzen.map('map', {
      tangramOptions: {
        scene: {
          import: [
            'https://mapzen.com/carto/refill-style/8/refill-style.zip', 'https://mapzen.com/carto/refill-style/8/themes/color-gray.zip', 'https://mapzen.com/carto/refill-style/8/themes/detail-1.zip'
        ] } }
    });
    map.setView([40.741331, -73.989332], 19);
			
    var markerStyle = {
      "weight": 2,
      "opacity": .6,
      "fillOpacity": .2,
      "radius": 9,
      "fillColor": "#888888",
      "color": "#888888"
    };

    // How we should handle each API result
    var show_venue = function(place) {
      var marker = L.circleMarker({
        lat: place['geom:latitude'],
        lng: place['geom:longitude']
      }, markerStyle);
      map.addLayer(marker);
    };

    // NOOP (we are using onprogress instead)
    var onsuccess = function() { return; };

    // Just log errors to the JS console
    var onerror = function(rsp) {
        console.error(rsp);
    };

    // Take all the API results and show them on the map
    var onprogress = function(rsp) {
      //console.log(rsp);
      for (var i = 0; i < rsp.places.length; i++) {
        var place = rsp.places[i];
        show_plane(place);
      }
    };

    function runWhosOnFirstAPI() {
      // Setup the API key
      mapzen.whosonfirst.api.set_handler('authentication', function() {
        return 'mapzen-aetZmeQ';
      });

      // Get all the venues in the Flatiron District
      // See: https://mapzen.com/documentation/wof/methods/#whosonfirst.places.getDescendants
      var parent_id = '85869245';
      var method = 'whosonfirst.places.getDescendants';
      var data = {
        id: parent_id,
        per_page: 500,
        extras: 'geom:', // this gets us lat/lng coords
      };

      // Ok now we actually call the API
      mapzen.whosonfirst.api.execute_method_paginated(method, data, onsuccess, onerror, onprogress);
    };
    </script>
  </body>
</html>

When you refresh your html page, you should see this.

Congrats, you just made a map of venues in New York City's Flatiron District using the WOF API.