Event Aggregators

Google Calendar and 30boxes.com are examples of online calendars meant to allow individuals and small groups of people to coordinate their appointments. Complementing such calendars are event aggregators that gather and list events, many of which are public events. In the following sections, I’ll cover two event aggregators that are programmable and hence mashable: Upcoming.yahoo.com and Eventful.com.


The URL for Upcoming.yahoo.com is as follows:


The URL for a specific event is as follows:


For example, the following is the URL for CHI2007:


Feeds from Search Results

Upcoming.yahoo.com makes much of its data available through RSS 2.0 feeds. Let’s consider an example. To look for events with the keyword Bach in the San Francisco Bay Area, you can use the following search:


In general, the URL for searching events is as follows:


where you can set sort to w (to sort by popularity), r (by relevance), and p (by recently added).

The previous search gives you HTML. You can also get feeds out of the search results as either RSS 2.0 or iCalendar. The RSS 2.0 feed includes Dublin Core data, uses the xCal extension (http://en.wikipedia.org/wiki/XCal) to encode calendaring information, and includes latitude and longitude data encoded with the Compact W3C Basic Geo encoding (see Chapter 13 for details on this encoding):


Take a look at a specific instance of an event:

                   <xCal:summary>San Francisco Symphony: Bach and Handel</xCal:summary>
                     <xCal:x-calconnect-venue-name>Davies Symphony Hall</xCal:x-calconnect-venue-Â
                     <xCal:x-calconnect-street>201 Van Ness Avenue</xCal:x-calconnect-street>
                     <xCal:x-calconnect-city>San Francisco Bay Area</xCal:x-calconnect-city>
                     <xCal:x-calconnect-country>United States</xCal:x-calconnect-country>
                    <xCal:url type='Venue Website'>http://upcoming.yahoo.com/venue/17246/

You can get an iCalendar version of the results, which you can subscribe to using an ­iCalendar-­cognizant calendar (for example, Apple iCal, Google Calendar, or Microsoft Outlook 2007):


Note the use of the webcal URI scheme (http://en.wikipedia.org/wiki/Webcal). The ?webcal scheme tells the recipient to subscribe to the feed—to track updates—rather than just doing a ­one-­time import of the iCalendar feed. (Note that you can replace webcal with http to get the contents of the iCalendar feed.)


What can you do with these feeds coming from Upcoming.yahoo.com? One example is to generate KML out of the RSS 2.0 feeds, which already contain geolocations for the events. In fact, you can use Yahoo! Pipes for this very task:


This pipe takes as input the parameters that can be used to generate an upcoming RSS 2.0 feed from Upcoming.yahoo.com (q, loc, and sort) and uses the Location Extractor operator to extract the geoRSS elements from the feed.


 You can extend the pipe to encompass the other search options at Upcoming.yahoo.com, such as date ranges or categories.

You can run the pipe for Bach events close to Berkeley, California, sorted by relevance:


Note that running this pipe generates a Yahoo! map showing the events contained in the feed. In addition to the RSS 2.0 feed version here:


which isn’t that interesting (since Upcoming.yahoo.com already generates an RSS 2.0 feed), you can get a KML version of this feed (by changing the _render parameter to kml):


From Chapter 13, you learned how to sort KML feeds on Google Maps:


Read-Only Parts of the API

Let’s now turn to the Upcoming.yahoo.com API. You can find the documentation for the API here:


You can generate a key to use for the API here:


The upcoming API is structured to be similar (but not identical) in detail to the Flickr REST API. The authentication is simpler and less sophisticated, but you’ll see the method parameter and api_key (similar naming). The base URL for the API is as follows:


Like the Flickr API, you need a method (event.search), an api_key, and other parameters for the given method, which are documented here:


There is a wide range of options (such as date range and precise location, in addition to paging parameters such as per_page and page). In this case, we’re using the search_text and location parameters to put together an HTTP GET request:


to which you get back a series of event elements:

               <event id="166104" name="San Francisco Symphony: Bach and Handel"
                      description="Christophers makes music of three centuries ago sound Â
               contemporary and utterly vital. Here, he conducts Baroque blockbusters, music of Â
               dazzling color and invention."
                      start_date="2008-04-05" end_date="" start_time="20:00:00" end_time="" 
                      selfpromotion="0" metro_id="2;1311;1403;1849;1934;2122;2289;2466;2638;2962" 
                      user_id="59509" category_id="1" date_posted="2007-03-18 10:59:58" 
                      distance="10.91" distance_units="miles" latitude="37.7774" 
                      geocoding_precision="address" geocoding_ambiguous="0" 
                      venue_name="Davies Symphony Hall"
                      venue_address="201 Van Ness Avenue" venue_city="San Francisco Bay Area"
                      venue_state_name="California" venue_state_code="ca" venue_state_id="5"
                      venue_country_name="United States" venue_country_code="us"  

Note what you get back. In addition to the “what” and “when” of the event, there is also specific geocoding. You can make a map (for example, converting this KML and displaying it on a map), which I showed earlier in the case of using the RSS 2.0 feed.

What else can do you with the API without authentication?

  • You can use event.getInfo to retrieve information about public events given its event_id. For example, you can use the WWW2008 Conference (http://upcoming.yahoo.com/? event/205875) here:



    to get the following:

                      <?xml version="1.0" encoding="UTF-8"?>
                      <rsp stat="ok" version="1.0">
                        <event id="205875" name="WWW 2008 (17th International World Wide Web Â?Conference)"
                          description="&quot;The World Wide Web Conference is a global event bringing Â?together key researchers, innovators, ?decision-?makers, technologists, Â?businesses, and standards bodies working to shape the Web. Since its inception Â?in 1994, the WWW conference has become the annual venue for international Â?discussions and debate on the future evolution of the Web.&quot;"
                          start_date="2008-04-21" end_date="2008-04-25" start_time="" end_time="" 
                          selfpromotion="0" metro_id="420" venue_id="33275" user_id="18772" 
                          url="http://www2008.org/" date_posted="2007-06-12" latitude="" Â?longitude=""
                          geocoding_precision="" geocoding_ambiguous=""
                          venue_name="Beijing International Conference Center"
                          venue_address="No.8 Beichendong Road Chaoyang District" Â?venue_city="Beijing"
                          venue_state_name="Beijing" venue_state_code="bj" venue_state_id="171" 
                          venue_country_code="cn" venue_country_id="44" venue_zip="" venue_url=""
  • You can use metro.getForLatLon to retrieve a venue for a given latitude and longitude. Let’s use the latitude and longitude for a building on the UC Berkeley campus in Berkeley, California:


    to formulate the following request:


    which returns this:

                         <?xml version="1.0" encoding="UTF-8"?>
                         <rsp stat="ok" version="1.0">
                           <metro id="2" name="San Francisco" code="sf" state_id="5" ?state_name="California" 
                                  country_id="1" country_name="United States" country_code="us"/>

Parts of the API That Require Authentication

You will need to supply a callback URL for ­token-­based authorization if you need that. How do you authenticate? The documentation is here:


Getting the Token

The documentation tells you how to set up a callback URL for ­web-­based applications. I consider this a simpler case in which you don’t set any callback URL and manually read off a token. That is, load up this in your browser, and read the frob:


Then get a token with an auth.getToken call:


to which you will get the following:

                  <?xml version="1.0" encoding="UTF-8"?>
                  <rsp stat="ok" version="1.0">
                  <token token="[TOKEN]" user_id="[USER_ID]" user_username="[USERNAME]" 
                         user_name="[FULLNAME]" />
Adding an Event with the API

Let’s use the API to add an event with the event.add method, which is documented here:


To add an event, issue an HTTP POST request with the following parameters:

  • api_key (required)

  • token (required)

  • name (required)

  • venue_id (numeric, required)

  • category_id (numeric, required)

  • start_date (YYYY-MM-DD, required)

  • end_date (YYYY-MM-DD, optional)

  • start_time (HH:MM:SS, optional)

  • end_time (HH:MM:SS, optional)

  • description (optional)

  • url (optional)

  • personal (1=visible to friends only or 0=public, optional, defaults to 0)

  • selfpromotion (1=self-promotion or 0=normal, optional, defaults to 0)

For an example, I added the JCDL 2008 conference to Upcoming.yahoo.com:


The best way is to practice using the user interface of Upcoming.yahoo.com to help you pick out the venue ID and category ID:


The location (found at http://www.jcdl2008.org/location.html) is the Omni William Penn Hotel in Pittsburgh, Pennsylvania. When you type the name of the hotel and its city into Upcoming.yahoo.com, it locates a venue. But how do you get the ID? You can use the API method venue.search (http://upcoming.yahoo.com/services/api/venue.search.php):


to which you get the following:

                  <?xml version="1.0" encoding="UTF-8"?>
                  <rsp stat="ok" version="1.0">
                    <venue id="56189" name="Omni William Penn Hotel" address="530 William Penn Place"
                      city="Pittsburgh" state="Pennsylvania" zip="" country="United States"
                      user_id="120115" metro_id="77" private="0" distance="0.14" 
                      latitude="40.4406" longitude="-79.997" geocoding_precision="address"  
                      state_code="pa" state_id="39" country_code="us" country_id="1"/>

The conclusion is that the venue ID is 56189.

The next question is, how do you get the category ID? You can use the category.getList method (http://upcoming.yahoo.com/services/api/category.getList.php):


to get:

                  <?xml version="1.0" encoding="UTF-8"?>
                  <rsp stat="ok" version="1.0">
                  <category id="1" name="Music" description="Concerts, nightlife, raves" />
                  <category id="2" name="Performing/Visual Arts" description="Theatre, dance, opera, Â
                  exhibitions" />
                  <category id="3" name="Media" description="Film, book readings" />
                  <category id="4" name="Social" description="Rallies, gatherings, user groups" />
                  <category id="5" name="Education" description="Lectures, workshops" />
                  <category id="6" name="Commercial" description="Conventions, expos, flea markets" />
                  <category id="7" name="Festivals" description="Big events, often multiple days" />
                  <category id="8" name="Sports" description="Sporting events, recreation" />
                  <category id="10" name="Other" description="Who knows?" />
                  <category id="11" name="Comedy" description="Stand-up, improv, comic theatre" />
                  <category id="12" name="Politics" description="Rallies, fundraisers, meetings" />
                  <category id="13" name="Family" description="Family/kid-oriented music, shows, 
                  theatre" />

For this event, let’s pick Education (category 5).

Finally, I grab the description from here:


Since 2001, the Joint Conference on Digital Libraries has served as the major international forum focused on digital libraries and associated technical, practical, and social issues . . .

Four hundred attendees are expected for the five days of events including a day of cutting edge tutorials; 3 days of papers, panels, and keynotes; and a day of research workshops.

OK—let’s piece together a curl invocation that will create a new event in Upcoming.yahoo.com. Here is a Python program to generate the curl command:

                  import urllib
                  # parameters for creating the upcoming event
                  method = 'event.add'
                  api_key = '[API-KEY]'
                  token = '[TOKEN]'
                  name = 'Joint Conference on Digital Libraries (JCDL) 2008'
                  venue_id = '56189'
                  category_id = '5'  #education
                  start_date = '2008-06-15'
                  end_date = '2008-06-20'
                  description = """
                  url = 'http://www.jcdl2008.org/'
                  params = {'api_key': api_key, 'method':method, 'token':token, 'name':name, Â
                  'venue_id':venue_id, 'category_id': category_id, Â
                            'start_date':start_date, 'end_date':end_date, 'description': description, Â
                            'url': url}
                  command = 'curl -v -X POST -d "%s" %s' % (urllib.urlencode(params), "http://upcoming.Â?yahooapis.com/services/rest/")
                  print command

The resulting curl command is as follows:

                  curl -v -X POST -d "venue_id=56189&name=Joint+Conference+on+Digital+Libraries+Â
                  %28JCDL%29+2008&end_date=2008-06-20&url=http%3A%2F%2Fwww.jcdl2008.org%2F&descriptionÂ?{description}&start_date=2008-06-15&token=[TOKEN]&api_key=[API-KEY]&method=event.addÂ?&category_id=5" http://upcoming.yahooapis.com/services/rest/

Remember that [TOKEN] is the authentication token received from the auth.getToken call issued earlier. The resulting event in Upcoming.yahoo.com is as follows:


API Kits for Upcoming.yahoo.com

To find API kits for Upcoming.yahoo.com, you can start with the links here:


Although there does not seem to be any publicly available PHP kits at this point, you can find one for Python here:


Since this project currently has no downloads, you get the source via Subversion:

svn checkout http://upcoming-python-api.googlecode.com/svn/trunk/ ?upcoming-?python-api

The following code searches for events with the Bach ?keyword that are within five miles of Berkeley, California:

               #from upcoming_api import Upcoming
               from upcoming_api import UpcomingCached
               import string
               #upcoming = Upcoming(UPCOMING_API_KEY)
               upcoming = UpcomingCached(UPCOMING_API_KEY)
               bach_events = upcoming.event.search(search_text='Bach', location="Berkeley, CA")
               print "There are %s events." % (len(bach_events))
               for event in bach_events:
                   print "%s\t%s\t%s" % (event['id'], event['name'], event['description']),
                   v = upcoming.venue.getInfo(venue_id=event['venue_id'])
                   print "%s\t%s\t%s\t%s" % (v[0]['name'], v[0]['address'], v[0]['city'], Â
                   # metro_id are ;-delimited list.  Sometimes  the metro list is empty....
                       m_ids = string.split(event['metro_id'],";")
                   # deal with only the first metro on the list
                       m = upcoming.metro.getInfo(metro_id=m_ids[0])
                       print 'metro name: ', m[0]['name']
                       print "no metro name"

Here is an additional line of Python to add an event to Upcoming.yahoo.com:

               new_event = upcoming.event.add(token=token,name=name,venue_id=venue_id, \
               category_id=category_id, start_date=start_date,end_date=end_date, \

 As of this writing, I had to update upcoming_api.py to make sure UPCOMING_API is set to http://upcoming.yahooapis.com/services/rest/.


Eventful.com is another event aggregator that has an API. You can find the web site here:


Its API is documented is here:


The list of methods in the API is here:


To use the API, you need to request a key from here:


The base URL for RESTful calls is here:

http://api.evdb.com/rest/{path for methods}

For example:


Searching for Events (Using Feeds)

Before we jump into the API, let’s see how to look at the URL language to search for events in the user interface and to return feeds. You can search for Bach events within five miles of Berkeley, California, with this:


You can get these results as an RSS 2.0 feed:


or as an Atom 1.0 feed:


You can change this Atom feed into KML using Yahoo! Pipes the way we did so for Upcoming.yahoo.com. The Eventful.com feeds have latitude/longitude information embedded (specifically, in the GeoRSS GML encoding). For example:

                   <gml:pos>37.72084 -122.476619</gml:pos>

You can run Yahoo! Pipes here:


to generate a KML feed for ­Bach-­related events in the Berkeley area:


Searching for Events (Using the API)

Let’s first get an XML response from the /events/search method, which is documented here:


to which you get event elements like this:

               <event id="E0-001-005962514-3">
                 <title>SF State Recital by Roger Woodward, piano faculty</title>
                 <description> &lt;b&gt;Details:&lt;/b&gt;&lt;br&gt;Program: J.S. Bach: Well-Â?Tempered Clavier, Book I </description>
                 <start_time>2007-10-23 20:00:00</start_time>
                 <venue_name>San Francisco State University</venue_name>
                 <venue_address>1600 Holloway Avenue</venue_address>
                 <city_name>San Francisco</city_name>
                 <country_name>United States</country_name>
                 <geocode_type>EVDB Geocoder</geocode_type>
                 <created>2007-09-02 00:19:50</created>
                 <modified>2007-09-02 04:07:16</modified>

Interestingly enough, we can also get iCalendar and RSS directly from the API. To get ­iCalendar, you use the /events/ical method documented here:


To get the Bach keyword–related events within five miles of Berkeley as an iCalendar feed, use this:


You can also change http to webcal and feed it to Google Calendar.

PHP API Kit for Eventful.com

You can find a list of API kits for Eventful.com here:


For PHP, there are two choices. One is Services_Eventful, which we won’t cover here, and the other is Services_EVDB (which seems to be compatible with PHP 4 and 5). You can find the code here:


Let’s say you want to extract this:


The corresponding REST call is as follows:


Note that the default is a 25-mile radius of the location. This shows how you can do this with the Services_EVDB PHP API kit:

               // http://api.eventful.com/libs/Services_EVDB
                   ini_get( 'include_path' ) . PATH_SEPARATOR . "/home/rdhyee/pear/lib/php" . 
               PATH_SEPARATOR . '/usr/local/lib/php'
               require 'Services/EVDB.php';
               // Enter your application key here. (See http://api.evdb.com/keys/)
               $app_key = '[APP_KEY]';
               $evdb = &new Services_EVDB($app_key);
               // Authentication is required for some API methods.
               $user     = $_REQUEST['user'];
               $password = $_REQUEST['password'];
               if ($user and $password)
                 $l = $evdb->login($user, $password);
                 if ( PEAR::isError($l) )
                     print("Can't log in: " . $l->getMessage() . "\n");
               // All method calls other than login() go through call().
               $args = array(
                 'id' => $_REQUEST['id'],
               $event = $evdb->call('events/get', $args);
               if ( PEAR::isError($event) )
                   print("An error occurred: " . $event->getMessage() . "\n");
                   print_r( $evdb );
               // The return value from a call is an XML_Unserializer data structure.
               print_r( $event );

To see this code in action on Eventful.com, the event number is E0-001-004433237-3:[255]


Python API Kit for Eventful.com

You can find the documentation for eventfulpy here:


As of writing, the latest version is as follows:


See “Installing simplejson and httplib2 on Windows Python” in case you run into problems installing the dependencies for eventfulpy.

The following code shows how to query for events and list the results:

               import eventful
               api = eventful.API('[API-KEY]')
               # If you need to log in:
               events = api.call('/events/search', q='Bach', l='Berkeley, CA', within='5', \
               units='mi', time='future', page_size=50)
               for event in events['events']['event']:
                   print "%s at %s" % (event['title'], event['venue_name'])

Let’s now write JCDL 2008 to Eventful.com. Note that like Upcoming.yahoo.com, Eventful.com also uses IDs for venues. The following code has a venue_search method to help locate venues and their corresponding IDs:

               # parameters for creating the upcoming event -- now I want to write it to eventful
               name = 'Joint Conference on Digital Libraries (JCDL) 2008'
               start_date = '2008-06-15'
               end_date = '2008-06-20'
               description = """
               url = 'http://www.jcdl2008.org/'
               def venue_search(keywords,location):
                   print out possibilities...
                   import eventful
                   api = eventful.API('[API-KEY]')
                   vs = api.call('/venues/search', keywords = keywords, location=location)
                   for v in vs['venues']['venue']:
                       print "%s\t%s\t%s" % (v['id'], v['name'], v['address'])
               import eventful
               api = eventful.API('[API-KEY]')
               tz_olsen_path = 'America/New_York'
               all_day = '1'
               privacy = 1
               tags = ''
               free = 0
               # this is the eventful venue_id for the hotel.
               eventful_venue_id = 'V0-001-000412401-5'
               ev = api.call('/events/new', title=name, start_time=start_date, \
                             stop_time=end_date, tz_olsen_path=tz_olsen_path, all_day=all_day, \
                             description=description, privacy=privacy, venue_id=eventful_venue_id)
               import pprint

With success, you get back an ID for the event (http://eventful.com/events/E0-001-006801918-6):

               {u'id': u'E0-001-006801918-6',
                u'message': u'Add event complete',
                u'status': u'ok'}