PublicEarth API Tutorial

This tutorial is a brief introduction to the PublicEarth API, and will take you through most of the basic content retrieval routines available in the API.

The PublicEarth API is a RESTful API. You’ll make simple HTTP requests to http://api.publicearth.com and receive back straightforward XML documents. We’ve tried to keep these XML document results simple, consistent and to-the-point. They’re easy to parse should you be using StAX, E4X, Nokogiri, or any XML parser of choice.

Authentication

The PublicEarth API supports a few different types of authentication. First, you may simply login to the web site and make call through your browser. I’d recommend using Firefox for this, as its XML output is quite legible. This is a great way to test calls visually and make sure you’re getting what you expected.

One step further, HTTP Basic authentication may be used against any PublicEarth user account.

Finally, we support both two-legged and three-legged OAuth. If you’re not familiar with OAuth, there’s a few reasonable online tutorials hanging around Google, and more than likely an OAuth client library exists for your language of choice. I’m not going to go into OAuth here, but we do have an OAuth page that goes into it a bit more.

The PublicEarth Data Model

PublicEarth’s content is centered around a few key pieces of information. At the heart of it all is the place. A place exists in a category. It has photos, details, features, and keywords. It also has position, and optionally, route or region geographic information as well. The details about a place are constrained by metadata, called attributes. Attributes are also associated with a category, to offer suggestions for possible details about a place based on what category it belongs to. Users may also rate a place, or vote on moods surrounding a place, such as “friendly”, “traditional”, or “expensive”.

Right now, there are a couple of limitations to PublicEarth places that we’re working on solving. A place may only exist in a single category. If the place belongs in more than one category, you’ll have to pick the one it’s “most like”. Or you may duplicate the place in more than one category. Unfortunately, duplicating the place does not link the two places at all, so editing the description on one place does not update it in other categories as well. We’ll get this straightened out in the coming months.

Categories

PublicEarth categories are organized into a hierarchical structure, with general categories at the top, working there way down one or two levels into more detailed categories. Note that a place may only be assigned to what we call a leaf-level category, in other words a category at the bottom of the structure, with no child categories of its own.

Let’s start with getting a list of the top-level categories in the hierarchy:

http://api.publicearth.com/v2/categories.xml

If you’re authenticated, clicking on the above link should display something like this:

  <?xml version="1.0" encoding="UTF-8"?>
  <categories total="12">
    <category id="AttractionsEntertainment">
      <name>Attractions &amp; Entertainment</name>
      <slug>attractions-entertainment</slug>
      <created>2008-10-10T14:09:01Z</created>
      <updated>2010-01-13T16:38:20Z</updated>
    </category>
    <category id="Essentials">
      <name>Daily Life</name>
      <slug>essentials</slug>
      <created>2008-10-10T14:09:04Z</created>
      <updated>2010-01-13T16:38:43Z</updated>
    </category>
    
    ... removed for brevity ...
    
  </categories>

This XML should be pretty straightforward, so I won’t go into much detail on it. Two things worth mentioning. First, whenever you request a multitude of some object via the API, each item will be wrapped in a parent XML tag that’s a plural of that object. For example, categories → category. Second, when there is a list of items coming back, we always put the total in that pluralized parent tag. You’re welcome to parse the child XML and count the results yourself, but we thought it would make some tasks a little easier to just skip the routines for parsing a bunch of XML in your client software if you noticed a total="0" up there.

To get more information about a category, pass in either the category ID or slug:

http://api.publicearth.com/v2/categories/attractions-entertainment.xml

You’ll notice this is pretty boring, and you’ve really already seen these results:

  <?xml version="1.0" encoding="UTF-8"?>
  <category id="AttractionsEntertainment">
    <name>Attractions &amp; Entertainment</name>
    <slug>attractions-entertainment</slug>
    <created>2008-10-10T14:09:01Z</created>
    <updated>2010-01-13T16:38:20Z</updated>
  </category>

Details About a Category

There’s quite a bit of information you can get around a category, but you may not always want to see it all. You can get a list of attributes associated with the category, what features are in a category, the number of places in a category, and what child categories are associated with this category. You won’t necessarily need all that information with each request, though you’re welcome to get it. We’ve tried to whittle things down with filter parameters on the request, so you can ask for exactly what you need and nothing more.

To get additional information, simple pass one or more values into the include parameter on your request URL. For example, to get the child categories:

http://api.publicearth.com/v2/categories/attractions-entertainment.xml?include=children

And you’ll get back:

  <?xml version="1.0" encoding="UTF-8"?>
  <category id="AttractionsEntertainment">
    <name>Attractions &amp; Entertainment</name>
    <slug>attractions-entertainment</slug>
    <created>2008-10-10T14:09:01Z</created>
    <updated>2010-01-13T16:38:20Z</updated>
    <children total="9">
      <category id="WatchingSports">
        <name>Watching Sports</name>
        <slug>watching-sports</slug>
        <created>2008-10-10T14:08:59Z</created>
        <updated>2010-01-13T16:38:41Z</updated>
      </category>
      <category id="GamingCasino">
        <name>Gaming &amp; Casinos</name>
        <slug>gaming-casino</slug>
        <created>2008-10-10T14:09:00Z</created>
        <updated>2010-01-13T16:38:14Z</updated>
      </category>
    
      ... trimmed for brevity ...
    </children>
  </category>

Maybe you just want to see what attributes are associated with this category, to see what kind of information the user may indicate about a place in that category. I’ll jump down to a leaf-level (since that’s all we can assign places to anyway) and see what attributes it suggests:

http://api.publicearth.com/v2/categories/horse-racing.xml?include=attributes

Results:

 
  <category id="HorseRacing">
    <name>Horse Racing</name>
    <slug>horse-racing</slug>
    <created>2008-11-19T23:35:00Z</created>
    <updated>2009-10-26T19:12:30Z</updated>
    <attributes total="30">
      <attribute id="67ab82ba-b692-11dd-965c-2b9cc0a32673">
        <name>contact_email</name>
        <slug>contact_email</slug>
        <priority>214</priority>
        <data_type>string</data_type>
        <allow_many>false</allow_many>
        <read_only>false</read_only>
        <required>false</required>
        <local>false</local>
      </attribute>
      
      ... there are many more ...
      
    </attributes>
  </category>

After making this call, you’d know what form fields to present to a user when creating or updating a place in the “Horse Racing” category.

To get the number of places in a category and all of its children, pass in the places value to include:

http://api.publicearth.com/v2/categories/attractions-entertainment.xml?include=places

Results:

  <?xml version="1.0" encoding="UTF-8"?>
  <category id="AttractionsEntertainment">
    <name>Attractions &amp; Entertainment</name>
    <slug>attractions-entertainment</slug>
    <created>2008-10-10T14:09:01Z</created>
    <updated>2010-01-13T16:38:20Z</updated>
    <places>187784</places>
  </category>

So at the time of writing this tutorial, we have a little shy of 200,000 attractions in our database.

Many queries in the PublicEarth API may be restricted by a geographic bounding box. If we’d like to find the number of places around Boulder, Colorado, we may supply its bounding box along with the places filter:

http://api.publicearth.com/v2/categories/attractions-entertainment.xml?include=places&amp;swx=-105.398605&amp;swy=39.9465862&amp;nex=-105.1424862&amp;ney=40.0833165

Results:

  <?xml version="1.0" encoding="UTF-8"?>
  <category id="AttractionsEntertainment">
    <name>Attractions &amp; Entertainment</name>
    <slug>attractions-entertainment</slug>
    <created>2008-10-10T14:09:01Z</created>
    <updated>2010-01-13T16:38:20Z</updated>
    <places>143</places>
  </category>

Notice how our number of places count has shrunk significantly.

Pretty much any time you’re requesting a list or count of places, you can pass in a set of coordinates for a bounding box to limit the search, defined by the southwest and northeast corners’ longitude and latitude coordinates.

                      (nex, ney)   
             +------------X
             |            |
             |            |
             X------------+
         (swx, swy)

Oh, and make sure to remember that x = longitude and y = latitude. Most people get those backwards because we all casually say “latitude, longitude”, which is really “y, x”.

You may request more than one set of data simultaneously. Just pass in a comma-separated list of values to the include parameter:

http://api.publicearth.com/v2/categories/attractions-entertainment.xml?include=places,attributes

To get everything about a category (children, places, attributes, etc.), there’s a shortcut: “all”.

http://api.publicearth.com/v2/categories/attractions-entertainment.xml?include=all

Searching for Categories

If you’re not sure what category you’re looking for, you may perform a free-text search across all categories. The search attempts to not only match on the name of a category, but also find categories that might be related to the keywords you submit. For example, if you search for “rollercoasters”, you should get back Amusement Parks.

Just request the categories.xml and pass in a q parameter with your keywords.

http://api.publicearth.com/v2/categories.xml?q=rollercoasters

And accordingly, you get back a set of categories, with Amusement Parks leading the list:

  <?xml version="1.0" encoding="UTF-8"?>
  <categories total="5">
    <category id="AmusementParks">
      <name>Amusement &amp; Theme Parks</name>
      <slug>amusement-parks</slug>
      <created>2008-10-10T14:09:01Z</created>
      <updated>2009-10-26T19:10:23Z</updated>
    </category>
    <category id="HotelsAndMotels">
      <name>Hotels &amp; Motels</name>
      <slug>hotels-and-motels</slug>
      <created>2008-10-10T14:09:00Z</created>
      <updated>2009-10-26T19:09:53Z</updated>
    </category>
    
    ... truncated ...
    
  </categories>

In all likelihood you got back Hotels & Motels because somebody mentioned a hotel being near some world-famous rollercoaster.

Places

There are two paths in the PublicEarth API from which to retrieve places. First, you may call for places directly:

http://api.publicearth.com/v2/places.xml

Result:

  <?xml version="1.0" encoding="UTF-8"?>
  <places total="10">
    <place id="b07b09b0-9e6a-11dd-b5ee-001c23d3f67b">
      <name>Scottdale Armory</name>
      <url>http://www.publicearth.com/places/historic-site/scottdale-armory&lt;/url&gt;
      <category>historic-site</category>
      <latitude>40.104075</latitude>
      <longitude>-79.585246</longitude>
      <details total="3" full="false">
        <detail id="46026114-c975-11de-a61b-cb9fffc32278" definition="description">
          <values total="1">
            <value language="en" contributor="4634cd50-af83-11dd-856a-123139009c23" updated="2008-10-19T23:48:17Z">
              National Register of Historic Places.
            </value>
          </values>
        </detail>
      </details>
      <keywords total="0"></keywords>
    </place>
    
    ... more places ...
    
  </places>

This call will return a selection of popular places. If you’re curious, “popularity” is roughly based on how rich the details of the place, how many people have shown an interest in the place, and how active the work on the place is.

Note in the above results that you don’t receive all the potential information about a place. For example, the <details> in the place shown above indicates three details about the place, but only a single <detail> tag is included. We’ll see below how to retrieve the additional information about a place (similar to a category).

You may also get a list of recently modified places:

http://api.publicearth.com/v2/places.xml?recent=true

If you’re looking for places in a specific category, call the places through the category you’re looking for:

http://api.publicearth.com/v2/categories/restaurants/places.xml

That request will return similar results to the first popular places request we made above, but all the results will be limited to the Restaurants category.

You may also limit the results by geography, in the same way we limited the places count in a category previously. Let’s find some popular restaurants in Boulder, Colorado:

http://api.publicearth.com/v2/categories/restaurants/places.xml?swx=-105.398605&amp;swy=39.9465862&amp;nex=-105.1424862&amp;ney=40.0833165

Here’s what we see:

  <?xml version="1.0" encoding="UTF-8"?>
  <places total="10">
  	<place id="a483d6c4-4968-11de-a1c2-00163e6a6ba1">
  		<name>Sort Of Snarfs</name>
  		<url>http://www.publicearth.com/places/restaurants/sort-of-snarfs&lt;/url&gt;
  		<category>restaurants</category>
  		<latitude>40.007029</latitude>
  		<longitude>-105.274967</longitude>
  		<details total="8" full="false"></details>
  		<keywords total="0"></keywords>
  	</place>
  	<place id="a7fc6dfa-4758-11de-b7eb-00163e6a6ba1">
  		<name>Cereality</name>
  		<url>http://www.publicearth.com/places/restaurants/cereality&lt;/url&gt;
  		<category>restaurants</category>
  		<latitude>40.014553</latitude>
  		<longitude>-105.261389</longitude>
  		<details total="8" full="false"></details>
  		<keywords total="0"></keywords>
  	</place>

  	... truncated for brevity ...

  </places>

You can see that all the results fall inside the Boulder, Colorado bounding box we indicated in the URL, and they’re all in the category “restaurants”.

Search for Places

Search for places in the same way you searched for categories above. Simply call the places.xml and pass in the q parameter with your keywords. Let’s see what’s popular in PublicEarth around “seafood”

http://api.publicearth.com/v2/places.xml?q=seafood

Our results:

  <?xml version="1.0" encoding="UTF-8"?>
  <places total="10">
  	<place id="c1a0b236-1592-11de-ab61-9786f2055779">
  		<name>Straits Restaurant - Palo Alto</name>
  		<url>http://www.publicearth.com/places/restaurants/straits-cafe-palo-alto&lt;/url&gt;
  		<category>restaurants</category>
  		<latitude>37.420613</latitude>
  		<longitude>-122.137174</longitude>
  		<details total="26" full="false">
  			<detail id="b3f36dda-c975-11de-935a-df761db89a56" definition="description">
  				<values total="1">
  					<value language="en" contributor="b7f61930-e534-11dd-bbb2-8f42e2e5ae1c" updated="2009-03-20T21:04:51Z">
          According to Caroline Bates of &lt;i&gt;Gourmet Magazine&lt;/i&gt;, "As showcased at Straits Café, the cooking of Singapore is the most seductive cuisine on the earth." The focus is on Singapore cuisine with touches of various other cultures–Indonesian, Chinese, Indian, and Nonya. Executive chef Chris Yeo creates a unique blend of the various cuisines. Enjoy the Asian hospitality as you feast on portions of Soto Ayam—the aromatic chicken soup or Ayam Rendang—chicken simmered in a light curry with garlic, blue ginger and grated coconut. Pair your meal with a pick from the exquisite wine list or try the House Specialty Cocktails. See website for menu, gallery, online reservations and more.
            </value>
  				</values>
  			</detail>
  		</details>
  		<keywords total="0"></keywords>
  	</place>
  	<place id="e2ab83b6-1600-11de-946b-e7bfe2c96864">
  		<name>Briarhurst Manor</name>
  		<url>http://www.publicearth.com/places/restaurants/briarhurst-manor&lt;/url&gt;
  		<category>restaurants</category>
  
    ... truncated ...
    
  </places>

Again, notice the 26 details about this first result, Straits Restaurant.

You may also limit the search to a specific region (bounding box). Let’s search for “seafood” in Boulder, Colorado:

http://api.publicearth.com/v2/places.xml?q=seafood&amp;swx=-105.398605&amp;swy=39.9465862&amp;nex=-105.1424862&amp;ney=40.0833165

Results:

  <places total="10">
    <place id="f41d48f6-149c-11de-aabc-3b656a424251">
    <name>Boulder Cork</name>
    <url>http://www.publicearth.com/places/restaurants/boulder-cork&lt;/url&gt;
    <category>restaurants</category>
    <latitude>40.03489</latitude>
    <longitude>-105.253712</longitude>
    <details total="22" full="false">
      <detail id="0d8ee60c-c977-11de-89b0-0fa4fbebab7c" definition="description">
        <values total="1">
          <value language="en" contributor="b7f61930-e534-11dd-bbb2-8f42e2e5ae1c" updated="2009-03-19T15:45:20Z">
            Since 1969, this popular southwestern spot has been a popular lunch and dinner haven for Boulder's professional crowd. The interior looks like an upscale home in New Mexico, complete with an adobe fireplace and wood beam ceiling.This is the place to go for big cuts of prime rib; choose from a 12 ounce portion or an 18 ounce cut. Other dinner entrees include free range chicken, boneless trout and a clutch of other seafood options. The wine list features a number of domestic selections.
          </value>
        </values>
      </detail>
    </details>
    <keywords total="0"></keywords>
    <photo id="2c1d1d10-c4f8-11de-8c33-3b803d680b84" contributor="22f7d214-b727-11dd-98cd-a7d55d123b4b">
      <filename>1256868103_Picture 6.jpg</filename>
    
    ... truncated early ...

The “Boulder Cork”—definitely a Boulder restaurant, and you’ll notice “seafood” right in the description.

You may also filter search results by category. Simply prepend the category to the URL. Try looking for Hotels and Motels that offer “cookies” in Boulder, Colorado:

http://api.publicearth.com/v2/categories/hotels-and-motels/places.xml?q=cookies&amp;swx=-105.398605&amp;swy=39.9465862&amp;nex=-105.1424862&amp;ney=40.0833165

I won’t show the results, but PublicEarth’s search engine does recommend the Briar Rose Bed and Breakfast.

More Details About a Place

Once you have a reasonable looking place, you can ask for more information about that place by passing in its ID or slug, similar to how we looked up category details.

Let’s take that Briar Rose Bed and Breakfast for our example.

http://api.publicearth.com/v2/places/briar-rose-bed-and-breakfast.xml

Here’s what we get back:

  <?xml version="1.0" encoding="UTF-8"?>
  <place id="aa2eed26-149c-11de-9e64-639f58b87e8e">
    <name>Briar Rose Bed and Breakfast</name>
    <slug>briar-rose-bed-and-breakfast</slug>
    <url>http://www.publicearth.com/places/hotels-and-motels/briar-rose-bed-and-breakfast&lt;/url&gt;
    <category>hotels-and-motels</category>
    <latitude>40.014624</latitude>
    <longitude>-105.26701</longitude>
    <details total="26" full="false">
        <detail id="2090bebc-c975-11de-9185-1f104aa348b5" definition="description">
          <values total="1">
              <value language="en" contributor="b7f61930-e534-11dd-bbb2-8f42e2e5ae1c" updated="2009-03-19T15:43:16Z">
                This cozy, English style country inn, located in the heart of the shopping district near the historic Goss-Grove neighborhood, has the honor of being Boulder's first bed and breakfast. The distinctive rooms feature individual designs, along with private baths, antique furniture, original art and fresh flowers. The Honeymoon and Anniversary rooms also have wood burning fireplaces. The courtyard gardens are exquisite and worth seeing even if you are not a guest at the inn.
              </value>
          </values>
        </detail>
    </details>
    <keywords total="0"></keywords>
  </place>

A couple of items to be aware of. First, every place will at least have a latitude and longitude value. Some places may have route and region geographic information, in a format known as Well Known Text, or WKT. WKT is understood by a variety of geographic systems, included ESRI, PostGIS, and Oracle Spatial.

Second, the URL indicated in the results will take the user directly to the place details page on the PublicEarth web site. You’re welcome to pass that directly along to the users.

Place Details

In the search results, the place indicated 26 details about the business, but only the description came back. If you’d like to get the rest of those details, pass along the full attribute:

http://api.publicearth.com/v2/places/briar-rose-bed-and-breakfast.xml?full=true

I’m not going to include the results, as they’re quite long.

Photos

Another trucated bit of data is the photos associated with a place. We return a single photo by default, and if you’ve taken a peek at some of the resulting XML that includes a photo, you’ll understand why we return only one. Each photo associated with a place has a transmogrification to one of five or six sizes (perhaps more by the time you read this). Currently all sizes are returned with each photo (not the images themselves, just a URL to the image online). So, we return a single photo, enough to display a sample to the user.

To get all the photos, pass in the photo parameter:

http://api.publicearth.com/v2/places/briar-rose-bed-and-breakfast.xml?photo=true

Again, you can click on the above link if you’d like to see the photo details fleshed out for the place.

Geography

Since rendering regions and routes for a place can be more difficult and not likely to be implemented by many clients, not to mention quite voluminous, so we’ve made it an optional result. If you’d like the WKT text defining the region or route for a place, pass along the cg parameter (for “complete geography”):

http://api.publicearth.com/v2/places/big-lagoon-state-park-us-2.xml?cg=true

Without the cg parameter, you’ll notice only the latitude and longitude of the place is returned.

Revised on January 29, 2010 02:02 by seanbowman