Chapter 18. Web Services: The APIs

We have discussed the basics of how web services work, and we touched on how to use them, but we have not discussed what services are already available. After all, if you have defined a module in an application to fetch a certain bit of information, it would be better defined as a publicly available service, if possible. You do not want to reinvent the wheel if you do not have to.

To that end, publicly available web services have supplied developers with the APIs to their services to make it easier to use them. This is also helpful for getting “up and running” quickly, something that is important in today’s world of rapid application deployment. It would be impossible, however, to go over all of the publicly available web services that exist today; new ones pop up all the time while old and obsolete ones disappear, and a service’s interface could change over time to better reflect the needs of developers.

Instead, I will highlight some of the better known, well-documented, and more readily used web services to give you a leg up on beginning to develop with them. And though they may change, at least you’ll have the foundation available to begin programming.

Publicly Available Web Services

An important thing for a web developer to know is what services are out there and how to use them. Without this knowledge, you have to search the Internet for what you need and hope that you find it in a short amount of time. Otherwise, it is costing you or your employer—as they say, “time is money.”

To make it easier for you to find publicly available web services, I have divided them into different categories and listed some of the more useful ones. In this section, I also demonstrate the use of a few web services to familiarize you with how they work. For more information on web services, see Appendix C.

Blogging Services

Blogging has become a huge phenomenon over the past several years, and blogs can be found in both the private and professional sectors. In fact, the line between personal and professional blogs, especially concerning technology, has blurred. After all, most of us cannot help but write about and experiment with technology even when it is on our own time.

Larger blog sites and operations have begun to see a real demand for services that allow developers to access the blogging system’s content and controls programmatically from within other applications. This has also led to the pleasant side effect of third-party tools being developed for programmatic remote access to blog systems.

These APIs range from direct access of management tools for blogging software to simple searching of blog content, and everything in between. In this section, I will list some of the more popular APIs of these blogging web services and discuss their functionality so that you will know what blog tools are available to you.

The following is a list of some of the more popular blogging APIs:

MSN Spaces

MSN Spaces is a service that allows external editing of text and attributes of weblog posts using the MetaWeblog programming interface. You can find the API documentation for this interface at http://msdn2.microsoft.com/en-us/library/bb259702.aspx.

Akismet

Akismet is a blogging tool to help prevent spam from interfering with a blog’s content or usability. It is available for personal and commercial use, and you can find the API to interact with it programmatically at http://akismet.com/development/api/.

TypePad

TypePad is a blog service catering to professionals and small businesses looking to create blogs for their sites. With its Atom API, you can do such things as programmatically post and read a blog. The API documentation is at http://www.sixapart.com/pronet/docs/typepad_atom_api.

FeedBurner

FeedBurner is a library of web services focused on blogging, and offers common blog functionality programmatically through its two APIs: FeedFlare and Feed Awareness. You can find documentation on these APIs at http://www.feedburner.com/fb/a/developers.

FeedBlitz

FeedBlitz is a blogging service that allows you to manage a blog through email for services such as user profiles, subscriptions, and syndications. You can find the API documentation to manage this information programmatically at http://feedblitz.blogspot.com/2006/10/feedblitz-api.html.

Weblogs.com

Weblogs.com is a ping service used to automatically inform VeriSign whenever the content of your site’s blog is updated so that it can, in turn, note this change on its web site. You can find the API documentation for this interaction at http://weblogs.com/api.html.

Technorati

Technorati is a service that keeps track of the millions of blogs that are on the Web today, organizing them and other media forms to make them more manageable. You can find the API documentation to manage these services programmatically at http://developers.technorati.com/wiki.

A good example of using a blogging service API in an application is FeedBurner’s Feed Management API, also known as MgmtAPI on the FeedBurner site. The MgmtAPI enables FeedBurner publishers to create and manage their accounts programmatically and can facilitate the following functions: find, get, add, modify, delete, and resync. This capability can be useful on its own or combined with other web services to create a mashup (see Chapter 19). All of these blog APIs may not work in the same way, but they are all fairly easy to use.

For a simple example, we will look at the MgmtAPI Find Feeds functionality. MgmtAPI uses the REST protocol for all its functionality, and returns XML for its response. The Request URL looks like this:

http://api.feedburner.com/management/1.0/FindFeeds?user=[username]&
password=[password]

This method has no parameters associated with it, other than the standard authentication parameters, and it simply returns a list of all the feeds associated with the user.

The response XML has a schema document located at http://api.feedburner.com/management/1.0/FindFeedsResponse.xsd. Basically, five fields are returned with the response, as shown in Table 18-1.

Table 18-1. The fields returned from a FeedBurner response

Field

Description

feeds

This is the root element that contains all of the returned feeds.

feed

This element represents a single feed.

id

This is an attribute associated with the feed and gives it its uniqueness.

uri

This is an attribute that represents the URI for the feed.

title

This attribute is the title for the feed.

A sample response for a Find Feeds request would look something like this:

<?xml version="1.0" encoding="utf-8" ?>
<feeds>
    <feed id="6" uri="trey-rants" title="Where Are the Standards?" />
    <feed id="26" uri="trey" title="Using OpenOffice as Your Word Processor" />
    <feed id="1999" uri="trey-sarah" title="Latest with the Twins" />
</feeds>

No server-specific errors were associated with this request. If the user passed to the server does not have any feeds, the feeds element in this simply has no children.

Example 18-1 shows the basics of how to call this request within PHP and handle the results. Unlike in the REST call we made in Example 17-6 in Chapter 17, in this example we use the PEAR library HTTP:Request for better error handling of the response. You can do what you want with the response, as we’ve discussed in detail throughout Part II of this book.

Example 18-1. Calling the FeedBurner MgmtAPI’s Find Feeds method using PHP

<?php
/**
 * Example 18-1. Calling the FeedBurner MgmtAPI's Find Feeds method using PHP.
 *
 * This file is just a simple example of fetching data using REST and parsing
 * the results.  Much more could be done on the server side, especially if part
 * of a mashup, in this script.
 */

/**
 * The file, user.inc, contains the username and password for the REST request.
 */
require_once('user.inc'),
/**
 * This is the PEAR HTTP:Request library used to make our request.
 */
require_once('HTTP/Request.php'),

/* Set up the request */
$request =& new HTTP_Request("http://api.feedburner.com/management/"
    ."1.0/FindFeeds?user=$username&password=$password");
$request->addHeader('Accept', 'application/atom+xml'),

/* Get the results of the request */
$results = $request->sendRequest( );

/* Begin the response text */
$response = '<?xml version="1.0" encoding="utf-8"?>';

/* Was there a problem with the request? */
if (PEAR::isError($results))
    $response .= '<response code="500">'.$response->getMessage( ).'</response>';
else {
    $code = $request->getResponseCode( );
    $response .= '<response code="'.$code.'">';
    $xml = new SimpleXMLElement($results);

    /* We can check for whatever codes we want here */
    switch ($code) {
        case 200:
            /* Were there any feeds? */
            if ($xml->children( )) {
                $response .= '<feeds>';
                /* Loop through the feeds */
                foreach ($xml->children( ) as $feed) {
                    $response .= '<feed>';
                    $response .= "<title>{$feed['title']}</title>";
                    $response .= "<link>{$feed['uri']}</link>";
                    $response .= '</feed>';
                }
                $response .= '</feeds>';
            } else
                $response .= '<feeds />';
            break;
        default:
            $response .= '<feeds />';
            break;
    }
    $response .= '</response>';
}
/*
 * Change the header to text/xml so that the client can use the return string
 * as XML
 */
header('Content-Type: text/xml'),
/* Give the client the XML */
print($response);
?>

Bookmark Services

Bookmarking, at least in terms of the sites that offer it, is the ability to track and share (by category) saved bookmarks with others around the world. The del.icio.us service has made bookmarking popular, as the del.icio.us web site is by far one of the most popular when it comes to blogging, photo and video sharing, and so on.

Here are some of the well-known web service APIs that are available:

del.icio.us

del.icio.us is a bookmarking service used to keep track of the types of material an individual may be interested in, and allows users to share these bookmarks with others. You can find the API documentation to programmatically control this functionality at http://del.icio.us/help/api/.

Simpy

Simpy is a bookmarking service for social interaction that enables users to tag and share bookmarks and notes. The web service allows for programmatically interfacing with the site. You can find the API documentation at http://www.simpy.com/doc/api/rest.

Blogmarks

Blogmarks is another social bookmarking service, though it is more “blog-like” than an actual blog. Through the use of its AtomAPI, you can retrieve Atom feeds from the site that GET, POST, DELETE, and PUT bookmarks. The AtomAPI documentation is at http://dev.blogmarks.net/wiki/DeveloperDocs.

Ma.gnolia

Ma.gnolia allows developers to access features for managing and collecting bookmark data from their site from other applications. You can find the API documentation to interact with Ma.gnolia from outside programs at http://ma.gnolia.com/support/api.

These web service APIs are easy enough to use, but because of its popularity, I’ll show a little more of the del.icio.us API. del.icio.us uses REST over HTTPS for all of its API calls, so a username and password are required just as they were in Example 18-1. The REST URI for adding a post to del.icio.us programmatically is:

https://api.del.icio.us/v1/posts/add?

You can add to this request a couple of required parameters, plus several more optional ones. Table 18-2 lists these parameters.

Table 18-2. The parameters that can be used to add a post to del.icio.us

Parameter

Required?

Description

description

Yes

The description of the item.

dt

No

The date stamp of the item in the format:

CCYY-MM-DDThh:mm:ssZ

extended

No

Notes for the item.

replace

No

Whether to replace the post if the URL has already been given. The default is no.

shared

No

Makes the item private. The default is no.

tags

No

Tags for the item (space-delimited).

url

Yes

The URL of the item.

For a successful post, the server will respond as follows:

<result code="done" />

If the post failed, however, the response will be:

<result code="something went wrong" />

Using PHP on the server, Example 18-2 shows how an Add request can be executed with PEAR and the response captured to notify the client. This example assumes that the information to post is coming from a POST from the client.

Example 18-2. Adding a post programmatically to del.icio.us using PHP

<?php
/**
 * Example 18-2. Adding a post programmatically to del.icio.us using PHP.
 *
 * This file demonstrates how to take the form post from the client and post
 * this data to del.icio.us using a REST architecture.  The result from the
 * post is sent back to the client.
 */


/**
 * The file, user.inc, contains the username and password for the REST request.
 */
require_once('user.inc'),
/**
 * This is the PEAR HTTP:Request library used to make our request.
 */
require_once('HTTP/Request.php'),

/* Is there something to post? */
if (!isempty($_REQUEST['description']) && !isempty($_REQUEST['url'])) {
    /* Set up the request */
    $request =& new HTTP_Request("https://$username:[email protected]/v1"
        ."/posts/add?url=".$_REQUEST['url']. "&description="
        .$_REQUEST['description']);
    $request->addHeader('Accept', 'application/atom+xml'),

    /* Get the results of the request */
    $results = $request->sendRequest( );

    /* Begin the response text */
    $response = '<?xml version="1.0" encoding="utf-8"?>';

    /* Was there a problem with the request? */
    if (PEAR::isError($results))
        $response .= '<response code="500">'.$response->getMessage( ).'</response>';
    else {
        $code = $request->getResponseCode( );
        $response .= '<response code="'.$code.'">';
        $xml = new SimpleXMLElement($results);
        $response .= $xml['code'];
        $response .= '</response>';
    }
} else
    $response .= '<response code="500">There was nothing to post.</response>';
/*
 * Change the header to text/xml so that the client can use the return string
 * as XML
 */
header('Content-Type: text/xml'),
/* Give the client the XML */
print($response);
?>

Financial Services

Financial institutions are beginning to see the advantages of having a web service attached to their financial information. Most services are offered at a price, as these types of services are more useful to a corporation or business than to an individual. Examples of services being offered today are those that involve the various stock markets, accounting control to an application, invoicing, credit checking, mutual fund prices, and currency rates.

A sample of some of these web services follows:

Blinksale

Blinksale is an online invoice service that allows users to invoice clients from a web browser. The API makes it easier for a developer to build this functionality into another application, and you can find it at http://www.blinksale.com/api.

StrikeIron Historical Stock Quotes

The StrikeIron Historical Stock Quotes service provides developers with a means for gathering detailed information on a stock ticker symbol for a specified date programmatically in an application. The API documentation for this service is at http://www.strikeiron.com/developers/default.aspx.

Dun and Bradstreet Credit Check

Dun and Bradstreet Credit Check enables developers to do credit checks against potential business clients programmatically through SOAP requests. You can find the API documentation providing access to these credit checks at http://www.strikeiron.com/ProductDetail.aspx?p=223.

NETaccounts

NETaccounts offers financial accounting from the web browser. Through its API it offers the basic CRUD operations. The API documentation showing these operations is available at http://www.netaccounts.com.au/api.html.

These services give you everything you need to start adding financial web service data into your own Ajax applications without much work. The only real downside with financial services is that they all charge fees for usage, but if you can justify those costs, the benefits of adding this kind of data can be enormous.

Mapping Services

One of the hottest topics for application development is in the realm of web mapping. This subject, more commonly referred to as Geographic Information Systems (GIS) within the industry, has some promising applications. This is especially true when used in a mashup with other available data sets.

Most people are visual by nature; as such, using maps to help convey a stat or fact adds good value to an application. For example, is it easier to get a list of addresses for restaurants in a district of a city you are unfamiliar with, or to get a map with the locations marked on it? Think about what started with MapQuest and driving directions, and is now a commonplace and expected function of these types of sites—a map marking the route with supplementary text giving step-by-step directions. This kind of visual aid is what web mapping is all about. Having access to mapping service APIs opens the door for developers to create many new and useful tools.

Many mapping services are available; here we will look at several of the bigger players so that you can get an idea of what they offer. A sample of the API, and of course, something visual, will accompany the list of mapping services. Here is this list:

Google Maps

Google Maps is a service that allows a developer to place maps in an application, with the use of JavaScript to control the map’s features and functions. This API, which gives developers all the functionality found with Google Maps for their own applications, is available at http://www.google.com/apis/maps/.

Yahoo! Maps

Yahoo! Maps enables developers to publish maps, created from Yahoo!’s engine, on their sites. The API allows for easy integration into existing applications, quickly giving a site a Web 2.0 look. You can find the API documentation for all of the Yahoo! Maps functionality at http://developer.yahoo.com/maps/.

ArcWeb

ArcWeb, a service provided by ESRI, allows you to integrate mapping functionality into a browser, without having to create it from scratch. You can find the API to use this service at http://www.esri.com/software/arcwebservices/index.html.

FeedMap

FeedMap’s BlogMap allows a developer to geocode a blog, making it locatable by geographic area. The API documentation outlining this functionality is available at http://www.feedmap.net/BlogMap/Services/.

Microsoft MapPoint

Microsoft MapPoint is a mapping service that enables you to integrate high-quality maps and GIS functionality into an existing web application with minimal effort. The API documentation for MapPoint is available at http://msdn.microsoft.com/mappoint/mappointweb/default.aspx.

MapQuest’s OpenAPI

MapQuest’s OpenAPI lets developers use JavaScript to integrate maps into a web application or site. The API documentation for OpenAPI is located at http://www.mapquest.com/features/main.adp?page=developer_tools_oapi.

Map24 AJAX

Map24 AJAX is a mapping service that allows a developer to place a Map24 map into an application with the use of JavaScript. The API documentation for programmatically adding these maps is available at http://devnet.map24.com/index.php.

Virtual Earth

Microsoft’s Virtual Earth combines the features of its MapPoint web service with other GIS digital imagery to create a robust platform that can be used in the government or business sector. You can find the API documentation for using Virtual Earth at http://dev.live.com/virtualearth/default.aspx?app=virtual_earth.

Yahoo! makes it easy to use its mapping API to create custom maps and embed them into an existing application. After obtaining an application ID from Yahoo!, using the Yahoo! Maps AJAX API library is a snap. The first thing to do is to include the library into your application, like so:

<script type="text/javascript"
    src="http://api.maps.yahoo.com/ajaxymap?v=3.0&appid=[Application Id]">
</script>

Once you have the library, you just create a placeholder element for the map that you can shape with CSS rules into whatever size you need. After that, simply decide whether to use latitude and longitude coordinates to specify the starting map location, or the built-in geocoding feature. Example 18-3 shows how to add a simple map control to an application that has some elementary tools included with it.

Example 18-3. Adding a Yahoo! Map control using the Yahoo! Maps AJAX API library

<html>
    <head>
        <script type="text/javascript"
            src="http://api.maps.yahoo.com/ajaxymap?v=3.0&appid=[Application Id]">
        </script>
        <style type="text/css">
            #mapContainer {
                height: 600px;
                width: 600px;
            }
        </style>
    </head>
    <body>
        <div id="mapContainer"></div>
        <script type="text/javascript">
            //<![CDATA[
            /* Create a latitude/longitude object */
            var myPoint = new YGeoPoint(38.64, -90.24);
            /* Create a map object */
            var map = new YMap(document.getElementById('mapContainer'));

            /* Add a map type control */
            map.addTypeControl( );
            /*
             * Set the map type to one of: YAHOO_MAP_SAT, YAHOO_MAP_HYB, or
             * YAHOO_MAP_REG
             */
            map.setMapType(YAHOO_MAP_REG);
            /* Add a pan control */
            map.addPanControl( );
            /* Add a slider zoom control */
            map.addZoomLong( );
            /* Display the map centered on a latitude and longitude */
            map.drawZoomAndCenter(myPoint, 3);
            //]]>
        </script>
    </body>
</html>

Figure 18-1 shows what this code would produce in the application. Its main features are the panning and zooming tools, and the ability to toggle among satellite, map, and hybrid modes.

The result of putting a Yahoo! Map control into a web page

Figure 18-1. The result of putting a Yahoo! Map control into a web page

A good addition to this type of map is the ability to add features that contain notations without having to know any extra programming. By having your script pass GeoRSS tagged files through the API interface, Yahoo! Maps will automatically add these features to the map. The World Wide Web Consortium (W3C) has a basic Geo (WGS84 lat/long) Vocabulary for defining these XML-based files, of which Yahoo! Maps takes advantage in RSS 2.0 format. You can find more information on this vocabulary at http://esw.w3.org/topic/GeoInfo. Yahoo! Maps bases its XML file on the GeoRSS 2.0 standard, and uses channel and item elements to define the data. Example 18-4 shows an example of a GeoRSS feed.

Example 18-4. A sample GeoRSS feed to use with Yahoo! Maps

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
        xmlns:ymaps="http://api.maps.yahoo.com/Maps/V2/AnnotatedMaps.xsd">
    <channel>
        <title>Example RSS Data</title>
        <link><![CDATA[http://www.oreilly.com]]></link>
        <description>Sample result</description>
        <ymaps:Groups>
            <Group>
                <Title>Museums</Title>
                <Id>museums</Id>
                <BaseIcon width="16" height="16">
                    <![CDATA[http://developer.yahoo.com/maps/star_blue.gif]]>
                </BaseIcon>
            </Group>
            <Group>
                <Title>Parks</Title>
                <Id>parks</Id>
                <BaseIcon width="16" height="16">
                    <![CDATA[http://developer.yahoo.com/maps/star_green.gif]]>
                </BaseIcon>
            </Group>
        </ymaps:Groups>
        <item>
            <title>St. Louis Art Museum</title>
            <link><![CDATA[http://www.stlouis.art.museum/]]></link>
            <description>The St. Louis Art Museum</description>
            <ymaps:Address>1 Fine Arts Drive</ymaps:Address>
            <ymaps:CityState>St. Louis, MO</ymaps:CityState>
            <ymaps:GroupId>museums</ymaps:GroupId>
        </item>
        <item>
            <title>Missouri History Museum</title>
            <link>
                <![CDATA[
                    http://www.mohistory.org/content/HomePage/HomePage.aspx
                ]]>
            </link>
            <description>The Missouri History Museum</description>
            <ymaps:Address>5700 Lindell Blvd</ymaps:Address>
            <ymaps:CityState>St. Louis, MO</ymaps:CityState>
            <ymaps:GroupId>museums</ymaps:GroupId>
        </item>
        <item>
            <title>City Museum</title>
            <link><![CDATA[http://www.citymuseum.org/home.asp]]></link>
            <description>City Museum</description>
            <ymaps:Address>701 N 15th St</ymaps:Address>
            <ymaps:CityState>St. Louis, MO</ymaps:CityState>
            <ymaps:GroupId>museums</ymaps:GroupId>
        </item>

        <item>
            <title>Forest Park</title>
            <link><![CDATA[http://www.forestparkforever.org/HTML/]]></link>
            <description>Forest Park Forever</description>
            <ymaps:Address>5595 Grand Dr</ymaps:Address>
            <ymaps:CityState>St. Louis, MO</ymaps:CityState>
            <ymaps:GroupId>parks</ymaps:GroupId>
        </item>
        <item>
            <title>Tower Grove Park</title>
            <link>
                <![CDATA[http://stlouis.missouri.org/parks/tower-grove/]]>
            </link>
            <description>Tower Grove Park</description>
            <ymaps:Address>4256 Magnolia Ave</ymaps:Address>
            <ymaps:CityState>St. Louis, MO</ymaps:CityState>
            <ymaps:GroupId>parks</ymaps:GroupId>
        </item>
    </channel>
</rss>

To include this type of data in a map, simply add the following code to the JavaScript:

/* The sample overlay data from a GeoRSS file */
map.addOverlay(new YGeoRSS('http://www.holdener.com/maps/sample.xml'));

This is just a simple example of using the Yahoo! Maps API. Other map service APIs are similar in their ease of use, though they differ from each other in one way or another. Such a variety of mapping service APIs is available that it should not be too difficult to find one that meets your needs.

Music/Video Services

Many music and video capabilities are available on the Web today, from streaming video to Internet radio stations. In fact, so many exist that it is hard to even begin to list the choices available for developers in the form of web services. Both the business and private sectors have come to realize how effective music and video media on the Web can be. And not just for personal enjoyment, either, but also for sharing homemade or favorite sources of this media with the rest of the world.

Services such as YouTube were instant successes, and they have become a major source of community sharing for the world in the medium of streaming video. YouTube is so successful that a number of similar services made for a specific purpose are now thriving on the Web. Because of this popularity, it was only natural for a number of web services to be created that aid in the use and functionality of these sites.

Here are a select few of these services:

SeeqPod

SeeqPod is a web service that suggests music recommendations based on songs submitted to it. You can find the API documentation for access to the service at http://www.seeqpod.com/api/.

Rhapsody

Rhapsody is a site that lets you stream music from its “browser” from within your web browser, and lets you search the music database that it keeps. The Rhapsody web service gives developers access to this technology on the site. The API documentation for using the service is located at http://webservices.rhapsody.com/.

Last.fm

Last.fm is the main site for the Audioscrobbler system, which collects data from people as they listen to music to track habits and song relationships, and makes those statistics available through its web service. You can find the API documentation for instructions on using this service at http://www.audioscrobbler.net/data/webservices/.

YouTube

YouTube is a community portal that offers users the ability to view and share videos on the Web. YouTube offers an API to this service that can be put to use from within other web applications. The API documentation to utilize the service is at http://www.youtube.com/dev.

Dave.TV

Dave.TV is a provider of video distributions in a community setting where users can share and view videos from the Web. Dave.TV offers a web API that allows for programmatic communication with its content delivery system. The API documentation for Dave.TV is at http://dave.tv/Programming.aspx.

As I mentioned earlier, a popular service on the Internet is the video sharing community of YouTube. Thanks to services such as this, users can easily search and view videos that are tagged by category from within other applications. There are no tricks to adding the functionality of YouTube and similar services, as they all provide fairly easy-to-use APIs for this purpose.

YouTube has both REST and XML-RPC access to its web service, though the following examples use REST. The service is easy to access and use, as it takes the following format to request data:

http://www.youtube.com/api2_rest?method=<method name>&dev_id=<developer id>
[&user=<YouTube user name>]

A successful response to this REST request takes the following format:

<ut_response status="ok">
    <!-- The XML for the response -->
<ut_response>

A request that ends in error, however, takes this form:

<ut_response status="fail">
    <error>
        <code>Code Number</code>
        <description>Description of code error.</description>
    </error>
</ut_response>

The following list shows the different errors that YouTube can return when a problem occurs:

1 (YouTube Internal Error)

There is a potential error with the YouTube API.

2 (Bad XML-RPC format parameter)

The passed parameter to the XML-RPC API call was of an incorrect type.

3 (Unknown parameter specified)

The parameter passed does not match any of those for the API being used.

4 (Missing required parameter)

A required parameter is missing for the API being used.

5 (No method specified)

No method was specified in the call to the API.

6 (Unknown method specified)

The API being used does not recognize the passed method.

7 (Missing dev_id parameter)

A dev_id parameter was not passed with the call to the API. (This parameter is required for all API calls.)

8 (Bad or unknown dev_id specified)

The dev_id parameter passed was not valid, and a valid dev_id is required for all API calls.

YouTube gives developers access to many requests—some dealing with user access and others dealing with video viewing. Table 18-3 lists these different methods and summarizes their usage.

Table 18-3. The different methods available for use with YouTube’s API

Method

Description

Required parameters

youtube.users.get_profile

This method retrieves the public information of a user profile.

method, dev_id, and user

youtube.users.list_favorite_videos

This method lists a user’s favorite videos.

method, dev_id, and user

youtube.users.list_friends

This method lists a user’s friends.

method, dev_id, and user

youtube.videos.get_details

This method displays the details for a video.

method, dev_id, and video_id

youtube.videos.list_by_tag

This method lists all videos that have the specified tag.

method, dev_id, tag, [page, per_page]

youtube.videos.list_by_user

This method lists all videos that were uploaded by the specified user.

method, dev_id, and user

youtube.videos.list_featured

This method lists the 25 most recent videos that have been featured on the front page of the YouTube site.

method and dev_id

youtube.videos.list_by_related

This method lists all videos that match any of the specified tags.

method, dev_id, tag, [page, per_page]

youtube.videos.list_by_playlist

This method lists all videos in the specified playlist.

method, dev_id, id, [page, per_page]

youtube.videos.list_popular

This method lists the most popular videos in the specified time range.

method, dev_id, and time_range

youtube.videos.list_by_category_and_tag

This method lists all of the videos that have the specified category id and tag.

method, dev_id, category_id, tag, [page, per_page]

With the youtube.videos.list_featured method as an example, a request to the service would look like this:

http://www.youtube.com/api2_rest?method=youtube.videos.list_featured&
dev_id=<developer id>

The response for this request looks like this:

 <video_list>
    <video>
        <author>macpulenta</author>
        <id>y14g50q4hQ0</id>
        <title>Scarlett Johansson - Speed Painting</title>
        <length_seconds>412</length_seconds>
        <rating_avg>4.5</rating_avg>
        <rating_count>4476</rating_count>
        <description>
            A new speed painting in Photoshop. At this time, a beautiful woman...
            Enjoy it.  And thanks for all your comments and messages to my other
            videos!! Gracias!!!

            (It was done with a digital tablet and the Background music is
            "Adagio for strings" by Dj Tiesto)
        </description>
        <view_count>859395</view_count>
        <upload_time>1121398533</upload_time>
        <comment_count>1883</comment_count>
        <tags>scarlett johansson speed painting photoshop</tags>
        <url>http://www.youtube.com/watch?v=y14g50q4hQ0</url>
        <thumbnail_url>
            http://static.youtube.com/get_still?video_id=y14g50q4hQ0
        </thumbnail_url>
        <embed_status>ok</embed_status>
    </video>
    .
    .
    .
</video_list>

This response can be sent from a server-side script directly to a client script that requested it with an Ajax call. Then it is necessary to parse the information needed for the particular client page so that it can be displayed. Let’s assume that the JavaScript code will be placing the data in an XHTML structure like this:

<div class="youTubeContainer">
    <div class="youTubeTitle"></div>
    <div class="youTubeThumb">
        <a href="">
            <img src="" alt="" title="" />
        </a>
    </div>
    <div class="youTubeDescription"></div>
</div>

Example 18-5 shows the JavaScript that handles the response from the server script and parses it to create the YouTube links in the application.

Example 18-5. Parsing a response from YouTube and putting the results into an XHTML application

/*
 * Example 18-5. Parsing a response from YouTube and putting the results into an
 * XHTML application.
 */

/**
 * This function, getYouTubeResults, takes the /xhrResponse/'s responseXML and
 * parses it, placing the necessary elements into the output string that will be
 * the /innerHTML/ of /someElement/.
 *
 * @param {Object} p_xhrResponse The XMLHttpRequest response from the server.
 * @return Returns whether the results were obtained correctly.
 * @type Boolean
 */
function getYouTubeResults(p_xhrResponse) {
    try {
        /* Get all of the video elements from the response */
        var videos = p_xhrResponse.responseXML.getElementsByTagName('video'),
        var output = '';

        /* Loop through the video elements and format the output */
        for (var i = 0, il = videos.length; i < il; i++) {
            output += '<div class="youTubeContainer">';
            output +=
                '<div class="youTubeTitle">' +
                videos[i].getElementsByTagName('title')[0].nodeValue +
                '</div>';
            output +=
                '<div class="youTubeThumb"><a href="' +
                videos[i].getElementsByTagName('url')[0].nodeValue +
                '"><img src="' +
                videos[i].getElementsByTagName('thumbnail_url')[0].nodeValue +
                '" alt="' + videos[i].getElementsByTagName('title')[0].nodeValue +
                '" title="' + videos[i].getElementsByTagName('title')[0].nodeValue +
                '" /></a></div>';
            output +=
                '<div class="youTubeDescription">' +
                videos[i].getElementsByTagName('description')[0].nodeValue +
                '</div>';
            output += '</div>';
        }
        /* Place the output in the document */
        $('someElement').innerHTML = output;
        /* Return true, indicating the function executed correctly */
        return (true);
    } catch (ex) {
        /*
         * There was a problem retrieving video, let the user know and return
         * false
         */
        $('someElement').innerHTML =
            'There was an error getting the YouTube videos.';
        return (false);
    }
}

News/Weather Services

Being a news junkie, it is important to me to get as much news information as I can as quickly as I can. Unfortunately, there has never been one site that gives me everything I want to use. As the number and variety of news services and RSS feeds have increased, however, so has the ability to create my own news sites that aggregate everything I want to view together at one time.

Some services supply news directly from their sites and provide that data through their own services. And other services grab different RSS feeds and provide a single point at which a variety of news can be obtained.

The following are some examples of news services:

NewsCloud

NewsCloud serves two purposes: it acts as a community for like-minded people to come together and express their ideas on corporate media and censorship, and it aggregates important news stories from around the Web. NewsCloud offers an API so that anyone can present his own NewsCloud data using his own applications. It is located at http://www.newscloud.com/learn/apidocs/.

NewsIsFree

NewsIsFree offers access to thousands of news sources through its portal, which allows for browsing news headlines. Currently featuring more than 25,000 news channels, NewsIsFree allows for programmatic access to creating, editing, and searching its sources through its API interface, which is located at http://www.newsisfree.com/webservice.php.

NewsGator

NewsGator is an information media company that deploys RSS aggregation solutions for all types of clients, from end users to corporate media companies. By providing an API to the resources NewsGator provides, anyone can develop applications to access and manipulate these resources outside of NewsGator. The API documentation is at http://www.newsgator.com/ngs/api/overview.aspx.

BBC

The BBC is a media broadcasting company in the United Kingdom that provides TV and radio feeds across the Internet. The BBC has provided an API to access its TV-Anytime database, which feeds TV and radio feeds. The documentation for this API is at http://www0.rdthdo.bbc.co.uk/services/api/.

WeatherBug

WeatherBug displays the latest weather conditions for a specific area, and includes the current weather conditions, severe-weather alerts in the United States, daily forecasts, and much more. WeatherBug provides an API to these services so that this functionality can be used on custom applications. The WeatherBug API documentation is located at http://api.weatherbug.com/api/.

I’ll use the NewsIsFree service for our news and weather services examples. NewsIsFree uses a SOAP interface for all communication to its web service. To use this service, the developer must have a valid username and password, plus a personal application key.

It is simple to create a request to NewsIsFree using PHP and SOAP. First, create a client connection using PHP 5’s built-in SOAP class, SoapClient( ):

$client = new SoapClient('http://newsisfree.com/nifapi.wsdl',
    array('trace' => 1, 'exception' => 0));

Then, simply call the API method with the necessary parameters. For example, to call the API method getNews( ), you would code the following:

$result = $client->getNews('[application key]',
                           '[login]',
                           '[password]',
                           '[site id]',
                           true);

Table 18-4 lists all of the API functions that are available for use with the NewsIsFree web service.

Table 18-4. The API functions for use with the NewsIsFree web service

Function

Description

createUser(application_key, login, password, createdLogin, createdPassword, email, deflang, username)

This function creates a new user with basic service on the site.

getPages(application_key, login, password)

This function returns the user’s page list.

createPage(application_key, login, password, name)

This function creates a page and returns the identifier for the newly created page.

getOrCreatePage(application_key, login, password, name)

This function will create a new page, if one does not exist, or else return the ID of the named page.

deletePage(application_key, login, password, id)

This function deletes the indicated page.

movePage(application_key, login, password, id, newId)

This function moves the indicated page underneath the newly indicated page.

renamePage(application_key, login, password, id, name)

This function changes the name of the indicated page.

showCategories(application_key, login, password)

This function returns a list of all news categories.

getSourceList(application_key, login, password, page)

This function returns an OPML outline string for the user’s source list for the indicated page, with a count of unread items in each source’s outline.

addSource(application_key, login, password, siteId, page)

This function adds a source to the indicated page.

deleteSource(application_key, login, password, siteId, page)

This function deletes the source indicated from the user’s source list.

moveSource(application_key, login, password, siteId, fromPage, toPage)

This function moves a source on the indicated page to the other indicated page.

mergeSources(application_key, login, password, page, opmlDocument)

This function merges a user’s source list with the passed source list on the indicated page.

replaceSources(application_key, login, password, page, opmlDocument)

This function replaces a user’s source list with the passed source list on the indicated page.

getUpdates(application_key, login, password, since)

This function gets a list of source IDs that have been updated since the indicated date for proper synchronization.

getNews(application_key, login, password, siteId, unreadOnly)

This function returns an RSS document for the indicated source.

getSourceContent(application_key, login, password, siteId)

This function returns an RSS document for the indicated source without user read states.

markRead(application_key, login, password, siteId, read)

This function sets all of the posts in the indicated source to be read or unread as indicated.

markSourcesRead(application_key, login, password, siteId)

This function sets all of the posts in the indicated source to be read.

getFeedInfoSummaryFromXmlUrl(application_key, login, password, xmlurls)

This function returns a list of sourceInfoSummary structures, one for each URL indicated.

setState(application_key, login, password, readItems, unreadItems)

This function sets a user’s read/unread state for a set of sources.

getItems(application_key, login, password, itemIds)

This function creates an ad hoc RSS feed from a list item’s IDs.

searchSources(application_key, login, password, search, lang, category)

This function searches sources in the indicated category.

directSearch(application_key, login, password, search, params)

This function searches the news using the passed parameters.

clipPost(application_key, login, password, itemId)

This function clips the specified item ID to the specified user clippings. Premium Account only.

unClipPost(application_key, login, password, itemId)

This function removes the specified item ID from the user clippings. Premium Account only.

For a getNews( ) request, the results are passed as an RSS feed, and they look like this:

<?xml version="1.0" encoding="UTF-8"?>
<rss version="0.92">
    <channel>
        <title>CNN</title>
        <link>/sources/info/2315/</link>
        <description>
            The world's news leader (powered by
            http://www.newsisfree.com/syndicate.php - FOR PERSONAL AND NON
            COMMERCIAL USE ONLY!)
        </description>
        <language>en</language><webMaster>[email protected]</webMaster>
        <lastBuildDate>05/03/07 02:59 7200</lastBuildDate>
        <image>
            <link>http://www.newsisfree.com/sources/info/2315/</link>
            <url>http://www.newsisfree.com/HPE/Images/button.gif</url>
            <width>88</width>
            <height>31</height>
            <title>Powered by NewsIsFree</title>
        </image>
        <item>
            <id>i,199624023,2315</id>
            <title>Armored truck robbers flee with $1.8 million</title>
            <link>
                http://rss.cnn.com/˜r/rss/cnn_topstories/˜3/113743933/index.html
            </link>
            <description>
                Read full story for latest details.&lt;p&gt;&lt;a
                href="http://rss.cnn.com/˜a/rss/cnn_topstories?a=rX51Ch"&gt;
                &lt;img id="hpeitemad"
                src="http://rss.cnn.com/˜a/rss/cnn_topstories?i=rX51Ch"
                border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
                &lt;img src="http://rss.cnn.com/˜r/rss/cnn_topstories/˜4/113743933"
                height="1" width="1"/&gt;
            </description>
            <read>0</read>
        </item>
        .
        .
        .
        <item>
            <id>i,199609740,2315</id>
            <title>Dow on best streak since 1955</title>
            <link>
                http://rss.cnn.com/˜r/rss/cnn_topstories/˜3/113721652/index.htm
            </link>
            <description>
                The Dow Jones industrial average hit another record high Wednesday,
                capping its longest winning stretch in almost 52 years as investors
                welcomed strong earnings, lower oil prices, media merger news and a
                strong reading on manufacturing.&lt;p&gt;
                &lt;a href="http://rss.cnn.com/˜a/rss/cnn_topstories?a=bodxMF"&gt;
                &lt;img id="hpeitemad"
                src="http://rss.cnn.com/˜a/rss/cnn_topstories?i=bodxMF"
                border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img
                src="http://rss.cnn.com/˜r/rss/cnn_topstories/˜4/113721652"
                height="1" width="1"/&gt;
            </description>
            <read>0</read>
        </item>
    </channel>
</rss>

Example 18-6 shows how to construct a request to NewsIsFree for the latest CNN news. The results are passed to the client as XML to be parsed and displayed to the user.

Example 18-6. Demonstrating how to use SOAP and PHP to pull data from the NewsIsFree web service

<?php
/**
 * Example 18-6. Demonstrating how to use SOAP and PHP to pull data from the
 * NewsIsFree web service.
 *
 * This example uses PHP 5's built-in SOAP class to request information from the
 * NewsIsFree web service.
 */

/* Set the parameters for the request query */
$app_key = '[application id]';
$login = '[login]';
$password = '[password]';
/* Site id 2315 is CNN */
$site = '2315';

$client = new SoapClient('http://newsisfree.com/nifapi.wsdl'),
try {
    $result = $client->getNews($app_key, $login, $password, $site, true);
    /*
     * Change the header to text/xml so that the client can use the return string
     * as XML
     */
    header('Content-Type: text/xml'),
    /* Give the client the XML */
    print($result[0]);
} catch (SoapFault $ex) {
    /* Something went wrong, show the exception */
    print($ex);
}
?>

It’s that easy to add news to an application.

Photo Services

When Flickr went live, it became an instant success and attracted millions of people who began to share their photos with the rest of the world. Since that time, other sites have been created with the same basic functionality, but with slightly different services. More important, communities exist within each of these sites, and they create many levels of communication and sharing between people all over the globe.

To increase their popularity and appeal to the development community, these photo services began to release APIs for their software so that outside web applications could reproduce the functionality offered on each site. These APIs help developers relatively easily do some pretty cool things in their web applications using web services like Flickr.

The following are some of the more popular photo APIs available:

Flickr

Flickr is a community photo sharing service that allows anyone to upload and share his photos with the rest of the world. The photos are tagged and categorized for easy searching and displaying of the Flickr data. A Flickr API and access to Flickr’s public data is available; the documentation for the API is located at http://www.flickr.com/services/.

SmugMug

SmugMug is a fee-based photo sharing service that stores photos for its customers and allows access to the photos through its site. SmugMug offers an API for anyone to utilize its services and functionality. The documentation for this API is at http://smugmug.jot.com/API.

Pixagogo

Pixagogo is a photo sharing and storage service that adds the ability to print the photos it stores. Pixagogo offers an API to its functionality so that you can build photo applications using its services. The documentation for Pixagogo’s API is located at http://www.pixagogo.com/Tools/api/apihelp.aspx.

Faces.com

Faces.com is a community site that allows individuals to upload and share photos and music, blog posts, and more. Faces.com provides an API so that you can build applications utilizing its technology, and you can find it at http://www.faces.com/Edit/API/GettingStarted.aspx.

Snipshot

Snipshot is a service that allows online editing of images from its site, and the ability to save the images to a remote address. Through its API, Snipshot allows for the programmatic editing of images from custom applications. Documentation for this API is located at http://snipshot.com/services/.

Flickr is one of the more popular services, so I’ll use it as an example. Flickr allows developers to request information from its web service in the REST, XML-RPC, and SOAP formats. An example REST request would look like this:

http://api.flickr.com/services/rest/?method=flickr.test.echo&name=value

Generally, the response format will be the same as that of the request, so a REST request would get a REST response. You can change the default response type using the format parameter in the request:

<?php
/* Set up the parameters for the request */
$params = array(
    'api_key'    => '[API key]',
    'method'    => 'flickr.blogs.getList',
    'format'      => 'json'
);

$encoded_params = array( );
/* Loop through the parameters and make them safe */
foreach ($paramas as $param => $value)
    $encoded_params[] = urlencode($param).'='.urlencode($value);
?>

There will be some debate as to which of Flickr’s response formats is the easiest to use. The choices are formatted XML with REST, XML-RPC, and SOAP; JavaScript Object Notation (JSON); and serialized PHP. The REST response is an easy response format to use, as it is a simple XML block. JSON, however, also has its advantages in size and structure. A successful JSON response is in this format:

jsonFlickrApi({
    "stat": "ok",
    "blogs": {
        "blog": [
            {
                "id"                 : "23",
                "name"               : "Test Blog One",
                "needspassword"      : "0",
                "url"                : "http://blogs.testblogone.com/"
            },
            {
                "id"                 : "76",
                "name"               : "Second Test",
                "needspassword"      : "1",
                "url"                : "http://flickr.secondtest.com/"
            }
        ]
    }
});

Meanwhile, if an error occurs, the JSON returned looks like this:

jsonFlickrApi({
    "stat"      : "fail",
    "code"      : "97",
    "message"   : "Missing signature"
});

Many methods are available with the Flickr API, as shown in Table 18-5. These methods can be separated by functionality, which you can see by breaking down the Flickr method names. All Flickr methods begin with the flickr namespace, followed by the function category the method is in—activity, auth, favorites, and so on.

Table 18-5. A list of available methods within the Flickr API

Method

Description

flickr.activity.userComments(api_key [, per_page [,page]])

This method returns a list of recent activity on photos commented on by the calling user.

flickr.activity.userPhotos(api_key [, timeframe [, per_page [, page]]])

This method returns a list of recent activity on photos belonging to the calling user.

flickr.auth.checkToken(api_key, auth_token)

This method returns the credentials attached to an authentication token.

flickr.auth.getFrob(api_key)

This method returns a frob to be used during authentication.

flickr.auth.getFullToken(api_key, mini_token)

This method returns the full authentication token for a mini token.

flickr.auth.getToken(api_key, frob)

This method returns the authentication token for the given frob, if one has been attached.

flickr.blogs.getList(api_key)

This method returns a list of configured blogs for the calling user.

flickr.blogs.postPhoto(api_key, blog_id, photo_id, title, description [, blog_password])

This method writes an existing photo to an existing blog.

flickr.contacts.getList(api_key [,filter [, page [,per_page]]])

This method returns a list of contacts for the calling user.

flickr.contacts.getPublicList(api_key, user_id [, page [,per_page]])

This method returns the contact list for a user.

flickr.favorites.add(api_key, photo_id)

This method adds a photo to a user’s favorites list.

flickr.favorites.getList(api_key [,user_id [,extras [,per_page [,page]]]])

This method returns a list of the user’s favorite photos which the calling user has permission to see.

flickr.favorites.getPublicList(api_key, user_id [, extras [, per_page [, page]]])

This method returns a list of favorite public photos for the given user.

flickr.favorites.remove(api_key, photo_id)

This method removes a photo from a user’s favorites list.

flickr.groups.browse(api_key [, cat_id])

This method browses the group category tree, finding groups and subcategories.

flickr.groups.getInfo(api_key, group_id)

This method returns information about a group.

flickr.groups.search(api_key, text [, per_page [, page]])

This method searches for groups.

flickr.groups.pools.add(api_key, photo_id, group_id)

This method adds a photo to a group’s pool.

flickr.groups.pools.getContext(api_key, photo_id, group_id)

This method returns the next and previous photos for a photo in a group pool.

flickr.groups.pools.getGroups(api_key [,page [,per_page]])

This method returns a list of groups to which you can add photos.

flickr.groups.pools.getPhotos(api_key, group_id [, tags [,user_id [, extras [, per_page [, page]]]]])

This method returns a list of pool photos for a given group, based on the permissions of the group and the user logged in.

flickr.groups.pools.remove(api_key, photo_id, group_id)

This method removes a photo from a group pool.

flickr.interestingness.getList(api_key [, date [, extras [, per_page [, page]]]])

This method returns the list of interesting photos for the most recent day or a user-specified date.

flickr.people.findByEmail(api_key, find_email)

This method returns a user’s NSID, given his email address.

flickr.people.findByUsername(api_key, username)

This method returns a user’s NSID, given his username.

flickr.people.getInfo(api_key, user_id)

This method returns information about a user.

flickr.people.getPublicGroups(api_key, user_id)

This method returns the list of public groups of which a user is a member.

flickr.people.getPublicPhotos(api_key, user_id [, extras [, per_page [, page]]])

This method returns a list of public photos for the given user.

flickr.people.getUploadStatus(api_key)

This method returns information for the calling user related to photo uploads.

flickr.photos.addTags(api_key, photo_id, tags)

This method adds tags to a photo.

flickr.photos.delete(api_key, photo_id)

This method deletes a photo from Flickr.

flickr.photos.getAllContexts(api_key, photo_id)

This method returns all visible sets and pools to which the photo belongs.

flickr.photos.getContactsPhotos(api_key [, count [, just_friends [, single_photo [, include_self [, extras]]]]])

This method returns a list of recent photos from the calling user’s contacts.

flickr.photos.getContactsPublicPhotos(api_key, user_id [, count [, just_friends [, single_photo [, include_self [, extras]]]]])

This method returns a list of recent public photos from a user’s contacts.

flickr.photos.getContext(api_key, photo_id)

This method returns the next and previous photos for a photo in a photo stream.

flickr.photos.getCounts(api_key [, dates [, taken_dates]])

This method returns a list of photo counts for the given date ranges for the calling user.

flickr.photos.getExif(api_key, photo_id [, secret])

This method returns a list of EXIF/TIFF/GPS tags for a given photo.

flickr.photos.getFavorites(api_key, photo_id [, page [, per_page]])

This method returns the list of people who have favored a given photo.

flickr.photos.getInfo(api_key, photo_id [, secret])

This method returns information about a photo.

flickr.photos.getNotInSet(api_key [, min_upload_date [, max_upload_date [, min_taken_date [, max_taken_date [, privacy_filter [, extras [, per_page [, page]]]]]]]])

This method returns a list of the user’s photos that are not part of any sets.

flickr.photos.getPerms(api_key, photo_id)

This method returns permissions for a photo.

flickr.photos.getRecent(api_key [, extras [, per_page [, page]]])

This method returns a list of the latest public photos uploaded to Flickr.

flickr.photos.getSizes(api_key, photo_id)

This method returns the available sizes for a photo.

flickr.photos.getUntagged(api_key [, min_upload_date [, max_upload_date [, min_taken_date [, max_taken_date [, privacy_filter [, extras [, per_page [, page]]]]]]]])

This method returns a list of the user’s photos with no tags.

flickr.photos.getWithGeoData(api_key [, min_upload_date [, max_upload_date [, min_taken_date [, max_taken_date [, privacy_filter [, sort [, extras [, per_page [, page]]]]]]]]])

This method returns a list of the user’s geo-tagged photos.

flickr.photos.getWithoutGeoDataapi_key [, min_upload_date [, max_upload_date [, min_taken_date [, max_taken_date [, privacy_filter [, sort [, extras [, per_page [, page]]]]]]]]])

This method returns a list of the user’s photos that have not been geo-tagged.

flickr.photos.recentlyUpdated(api_key, min_date [, extras [, per_page [, page]]])

This method returns a list of the user’s photos that have been recently created or recently modified.

flickr.photos.removeTag(api_key, tag_id)

This method removes a tag from a photo.

flickr.photos.search(api_key [, user_id [, tags [, tag_mode [, text [, min_upload_date [, max_upload_date [, min_taken_date [, max_taken_date [, license [, sort [, privacy_filter [, bbox [, accuracy [, machine_tags [, machine_tag_mode [, group_id [, extras [, per_page [, page]]]]]]]]]]]]]]]]]]])

This method returns a list of photos matching some criteria.

flickr.photos.setDates(api_key, photo_id [, date_posted [, date_taken [, date_taken_granularity]]])

This method sets one or both of the dates for a photo.

flickr.photos.setMeta(api_key, photo_id, title, description)

This method sets the meta-information for a photo.

flickr.photos.setPerms(api_key, photo_id, is_public, is_friend, is_family, perm_comment, perm_addmeta)

This method sets permissions for a photo.

flickr.photos.setTags(api_key, photo_id, tags)

This method sets the tags for a photo.

flickr.photos.comments.addComment(api_key, photo_id, comment_text)

This method adds a comment to a photo as the currently authenticated user.

flickr.photos.comments.deleteComment(api_key, comment_id)

This method deletes a comment from a photo as the currently authenticated user.

flickr.photos.comments.editComment(api_key, comment_id, comment_text)

This method edits the text of a comment for a photo as the currently authenticated user.

flickr.photos.comments.getList(api_key, photo_id)

This method returns the comments for a photo.

flickr.photos.geo.getLocation(api_key, photo_id)

This method returns the geodata for a photo.

flickr.photos.geo.getPerms(api_key, photo_id)

This method returns the permissions for who may view geodata for a photo.

flickr.photos.geo.removeLocation(api_key, photo_id)

This method removes the geodata associated with a photo.

flickr.photos.geo.setLocation(api_key, photo_id, lat, lon [, accuracy])

This method sets the geodata for a photo.

flickr.photos.geo.setPerms(api_key, is_public, is_contact, is_friend, is_family, photo_id)

This method sets the permission for who may view the geodata associated with a photo.

flickr.photos.licenses.getInfo(api_key)

This method returns a list of available photo licenses for Flickr.

flickr.photos.licenses.setLicense(api_key, photo_id, license_id)

This method sets the license for a photo.

flickr.photos.notes.add(api_key, photo_id, note_x, note_y, note_w, note_h, note_text)

This method adds a note to a photo.

flickr.photos.notes.delete(api_key, note_id)

This method deletes a note from a photo.

flickr.photos.notes.edit(api_key, note_id, note_x, note_y, note_w, note_h, note_text)

This method edits a note on a photo.

flickr.photos.transform.rotate(api_key, photo_id, degrees)

This method rotates a photo.

flickr.photos.upload.checkTickets(api_key, tickets)

This method checks the status of one or more asynchronous photo upload tickets.

flickr.photosets.addPhoto(api_key, photoset_id, photo_id)

This method adds a photo to the end of an existing photoset.

flickr.photosets.create(api_key, title [, description], primary_photo_id)

This method creates a new photoset for the calling user.

flickr.photosets.delete(api_key, photoset_id)

This method deletes a photoset.

flickr.photosets.editMeta(api_key, photoset_id, title [, description])

This method modifies the metadata for a photoset.

flickr.photosets.editPhotos(api_key, photoset_id, primary_photo_id, photo_ids)

This method modifies the photos in a photoset.

flickr.photosets.getContext(api_key, photo_id, photoset_id)

This method returns next and previous photos for a photo in a set.

flickr.photosets.getInfo(api_key, photoset_id)

This method returns information about a photoset.

flickr.photosets.getList(api_key [,user_id])

This method returns the photosets that belong to the specified user.

flickr.photosets.getPhotos(api_key, photoset_id [, extras [, privacy_filter [, per_page [, page]]]])

This method returns the list of photos in a set.

flickr.photosets.orderSets(api_key, photoset_ids)

This method sets the order of photosets for the calling user.

flickr.photosets.removePhoto(api_key, photoset_id, photo_id)

This method removes a photo from a photoset.

flickr.photosets.comments.addComment(api_key, photoset_id, comment_text)

This method adds a comment to a photoset.

flickr.photosets.comments.deleteComment(api_key, comment_id)

This method deletes a photoset comment as the currently authenticated user.

flickr.photosets.comments.editComment(api_key, comment_id, comment_text)

This method edits the text of a comment as the currently authenticated user.

flickr.photosets.comments.getList(api_key, photoset_id)

This method returns the comments for a photoset.

flickr.reflection.getMethodInfo(api_key, method_name)

This method returns information for a given Flickr API method.

flickr.reflection.getMethods(api_key)

This method returns a list of available Flickr API methods.

flickr.tags.getHotList(api_key [, period [, count]])

This method returns a list of hot tags for the given period.

flickr.tags.getListPhoto(api_key, photo_id)

This method returns the tag list for a given photo.

flickr.tags.getListUser(api_key [, user_id])

This method returns the tag list for a given user.

flickr.tags.getListUserPopular(api_key [, user_id [, count]])

This method returns the popular tags for a given user.

flickr.tags.getListUserRaw(api_key [, tag])

This method returns the raw versions of a given tag for the currently logged-in user.

flickr.tags.getRelated(api_key, tag)

This method returns a list of tags related to the given tag, based on clustered usage analysis.

flickr.test.echo(api_key)

This method echoes all parameters back in the response.

flickr.test.login(api_key)

This method checks whether the caller is logged in and then returns her username.

flickr.test.null(api_key)

This method is a null test.

flickr.urls.getGroup(api_key, group_id)

This method returns the URL to a group’s page.

flickr.urls.getUserPhotos(api_key [, user_id])

This method returns the URL to a user’s photos.

flickr.urls.getUserProfile(api_key [, user_id])

This method returns the URL to a user’s profile.

flickr.urls.lookupGroup(api_key, url)

This method returns a group NSID, given the URL to a group’s page or photo pool.

flickr.urls.lookupUser(api_key, url)

This method returns a user NSID, given the URL to a user’s photos or profile.

You can see from the length of Table 18-5 that the Flickr API covers just about anything a developer would want to do programmatically. Example 18-7 demonstrates how to make a REST request to the Flickr web service and get a JSON response that is sent to the client. The example gets the title of a specific photo on Flickr’s site that can be returned to the client.

Example 18-7. Making a REST call to the Flickr web service and getting a PHP response

<?php
/**
 * Example 18-7. Making a REST call to the Flickr web service and getting a
 * PHP response.
 *
 * This file demonstrates how to send a request to Flickr's API methods and
 * send the response to the client using the REST architecture and JSON.
 */

/* Set up the parameters for the request */
$params = array(
    'api_key'   => '[API key]',
    'method'    => 'flickr.blogs.getList',
    'format'    => 'json'
);

$encoded_params = array( );
/* Loop through the parameters and make them safe */
foreach ($paramas as $param => $value)
    $encoded_params[] = urlencode($param).'='.urlencode($value);

/* Make the API request */
$url = "http://api.flickr.com/services/rest/?".implode('&', $encoded_params);
$response = file_get_contents($url);
/* Send the response to the client to parse */
print($response);
?>

Example 18-8 demonstrates how easy it is to make the JSON response usable on the web page. It is also easy to modify this function to do something different from what it is doing.

Example 18-8. Demonstrating how to handle a JSON response from Flickr

/*
 * Example 18-8. Demonstrating how to handle a JSON response from Flickr.
 */

/**
 * This function, jsonFlickrResponse, takes the JSON response from the server
 * and parses the results by creating <div> elements to place the blog name in.
 * It sends the error code and message should an error occur in the request.
 *
 * @param {Object} p_xhrResponse The XMLHttpRequest response from the server.
 */
function jsonFlickrResponse(p_xhrResponse){
    var rsp = p_xhrResponse.responseText;

    /* Did we get a valid response? */
    if (rsp.stat == 'ok') {
        /* Loop through the log records */
        for (var i = 0, il = rsp.blogs.blog.length; i < il; i++) {
            var blog = rsp.blogs.blog[i];
            var div = document.createElement('div'),
            var txt = document.createTextNode(blog.name);

            div.appendChild(txt);
            document.body.appendChild(div);
        }
    /* Did we get a fail message? */
    } else if (rsp.stat == 'fail') {
        var div = document.createElement('div'),
        var txt = document.createTextNode(rsp.code + ': ' + rsp.message);

        div.appendChild(txt);
        document.body.appendChild(div);
    }
}

Reference Services

The Web is one great library, used to look up everything from antidisestablishmentarians to zooarchaeologists. OK, maybe not everything, but a great deal of content on the Web can be used as reference or for lookup. When sites such as Wikipedia arrived on the scene, the volume of information that could be referenced in one place skyrocketed.

Reference content is more than just articles on Wikipedia, however, a site which closely resembles encyclopedias of the past. The amount of information that can be gathered, from demographics to genealogical data, is really the reference information that I mean. Unfortunately, some of this information is still difficult to get in a single, usable form. From this chapter’s point of view, many reference sites still lack access as web services—even sites such as Wikipedia (at least as of the time of this writing, though a web service is in the works).

The following is a sample of some of the services available:

RealEDA Reverse Phone Lookup

The RealEDA Reverse Phone Lookup provides an interface to the names and addresses that are associated with any telephone number. This fee-based API allows outside applications to access and incorporate this information. The resources for this API are at http://www.strikeiron.com/productdetail.aspx?p=157.

ISBNdb

The ISBNdb service is a database containing book information taken from libraries around the world and provides research tools to this data. ISBNdb provides a developer API that allows for data requests from remote applications; its documentation is located at http://isbndb.com/docs/api/index.html.

Urban Dictionary

Urban Dictionary is a dictionary that provides definitions for modern-day slang. It provides an API so that you can look up words from within custom applications. You can find the documentation to this API at http://www.urbandictionary.com/tools.php.

SRC Demographics

SRC Demographics is a service providing access to demographic information based on the 2000 U.S. census. The API that is provided allows for applications deployed on any web site to seamlessly integrate this information. The documentation for this API is at http://belay.extendthereach.com/api/help/.

StrikeIron U.S. Census

StrikeIron U.S. Census is a fee-based service that allows for the retrieval of extensive information from the 2000 U.S. census. The API to the service allows for this information to be placed in custom web applications. The API documentation is located at http://www.strikeiron.com/developers/default.aspx.

StrikeIron Residential Lookup

StrikeIron Residential Lookup is a fee-based service allowing for the retrieval of residential information within the U.S. and Puerto Rico. The API allows for programmatic interfaces to this information that can be added to a web application. The API documentation is located at http://www.strikeiron.com/developers/default.aspx.

Something that is beginning to change, in small steps anyway, is the online availability of public information from local, state, and federal government agencies. However, a great deal of information still is not available on the Internet, or if it is, fees are associated with it. Only time will tell how much information will actually become available on the Internet, and what it will cost to access it.

Then there is the problem of sites that have good reference information available, whether or not a fee is involved. However, these sites have not created web services to access their information from outside their site frameworks. A major area where this is lacking is genealogical information. Again, in time, accessing reference information through web services will improve. We’ll just have to wait to see how long this will take.

Search Services

I think it is pretty safe to say that if you have been on the Web, you have conducted a search of some kind. Let’s face it, it can be pretty hard to find the content you are looking for, especially as the Web gets older and more mature. There is so much information on the Web, even within a single site, that you would be hard-pressed to find what you were looking for without performing at least one search.

This was not always the case. In the late 1990s, it was much easier to find specific content simply because the Web did not have the volume of information it has today (this assumes that the content you were looking for even existed!). The reverse is true today; the content is out there, somewhere, but it is much harder to find. I admit that I usually start to browse the Web from a Google search page unless I already know the place I need to start from (we all have favorites and bookmarks, after all).

The Web relies on searching, whether it’s from a site such as Google or Yahoo! or from within a site; blogs are an example of sites that need internal searching. Having APIs to some of the better search engines available can greatly enhance a web application; developers can add the searching directly into the application, saving trips to other places.

The following is a sample of some of the search services available:

Google AJAX Search API

Google is the most popular search engine on the Web, and it has been a leader in the web service API arena from the start. By providing an API to its searching capabilities, you can easily add Google Search to any web application. The documentation for this API is available at http://code.google.com/apis/ajaxsearch/.

Yahoo! Search

Yahoo! Search is another popular search engine on the Web that offers an API to access its search capabilities from an outside application. The documentation for the API is located at http://developer.yahoo.com/search/web/.

Windows Live Search

Windows Live Search is part of Microsoft’s Live suite of services and allows developers deeper control of Windows Live search functionality and social relationships through its API. The documentation for this API is located within MSDN at http://msdn2.microsoft.com/en-us/library/bb264574.aspx.

I touched on search service APIs in Chapter 16 where I explored some of the capabilities of Google’s AJAX Search API. The better APIs available are just as easy to use as Google’s is, and should not cause much trouble for developers to integrate them into an application.

Shopping Services

Most business owners have recognized by now that if you have something to sell, you better have a way to sell it online. This is, in no small part, thanks to sites such as Amazon and eBay, which have made shopping on the Web simple, quick, and painless.

Instead of investing money into their own sites and shopping technology, many small to medium-size businesses have turned to larger commercial sites for hosting and the technology to drive their business. One disadvantage to this is a slight loss of brand recognition, as consumers will see what is driving shopping carts with less emphasis on the business that brought them there. The ability to use these sites from a separate application or web site through APIs has changed all that.

Web services that enable developers to access the functionality of these larger e-commerce sites allow for better site integration and smoother, more seamless business applications. The following is a list of some of the shopping applications available:

Amazon

Amazon has a suite of web services available to developers. The Amazon E-Commerce Service provides product data and e-commerce functionality through an API that developers can utilize within an application. This API documentation is located at http://www.amazon.com/gp/browse.html/ref=sc_fe_l_2/103-1644811-9832630?%5Fencoding=UTF8&node=12738641&no=3435361.

DataUnison eBay Research

The DataUnison eBay Research service provides marketing data on eBay customer buying and selling trends. Its API gives developers access to eBay’s main categories and subcategories to pull all relevant information into separate web applications. You can find the documentation for this API at http://www.strikeiron.com/ProductDetail.aspx?p=232.

UPC Database

The UPC Database provides a database of contributor-provided UCC-12 (formerly UPC) and EAN/UCC-13 codes. With the provided API, developers can look up codes to products from within existing applications. The API documentation is at http://www.upcdatabase.com/xmlrpc.asp.

eBay

eBay provides a marketplace for more than 200 million users that buy and sell on the site. With the accessibility of eBay’s API, developers can access all of eBay’s functionality from outside applications with ease. The starting place for developers interested in different languages that work with eBay’s API is at http://developer.ebay.com/.

CNET

CNET is a data center for electronic products such as digital cameras, computers, and MP3 players, as well as a collection of software titles. CNET provides an API interface to functionality that interfaces with its services and that developers can integrate into other applications. The documentation to this API is located at http://api.cnet.com/.

As a quick example of using a shopping service, let’s look at eBay. eBay has done an awesome job of documenting its API and providing examples on how to use it properly. The API can be called using REST or SOAP, and eBay provides examples on how to use the API with Java, PHP, C#, and ASP, among others.

Tip

I highly recommend that you take some time to peruse eBay’s developer pages. There is enough information to get any developer, from novice to expert, on his way to building an application that incorporates eBay.

The following is an example of a REST request to eBay:

http://rest.api.ebay.com/restapi?CallName=GetSearchResults&
RequestToken=[UserToken]&RequestUserId=[UserName]&Query=[Query Words]&
Version=491&UnifiedInput=1

This example calls the method GetSearchResults, and expects a maximum of five results. An eBay UserName and UserToken are required to use this service. Table 18-6 shows the methods available in eBay using the REST API.

Table 18-6. REST methods available in the eBay API

Method

Description

GetSearchResults

This method is used to search eBay for specified items based on the parameters passed.

GetCategoryListings

This method is used to search eBay for specified items based on their category.

GetSearchResultsExpress

This method is used to search eBay for specified items based on the parameters passed, giving only brief details on each item found.

GetItem

This method is used to obtain detailed information on an item.

GetItemShipping

This method is used to estimate the shipping cost information for an item.

GetCategories

This method is used to get the latest category hierarchy.

GetPopularKeywords

This method is used to obtain the keywords that users have most frequently specified when searching eBay.

Every eBay REST API method requires the same basic parameters when a client makes a request. Table 18-7 describes the required input parameters.

Table 18-7. The required input parameters for REST requests in the eBay API

Parameter

Description

CallName

This parameter is the name of the API call.

RequestToken

This parameter is the UserToken for an eBay user corresponding to a specific eBay user.

RequestUserId

This parameter is the UserName of the eBay user whose token is specified with the RequestToken parameter.

UnifiedInput

This parameter is only for the method GetSearchResults, and indicates whether a unified schema is being used for input.

Version

This parameter specifies the API version being used with the call.

Schema

This parameter is only for the method GetSearchResults, and indicates that the response should be sent in a unified schema format.

The best way to understand how eBay’s web service works is to see how the server side would make a request to the server when a variable is passed to it. Example 18-9 shows how to handle this in PHP.

Example 18-9. Requesting search results from the eBay REST API

<?php
/**
 * Example 18-9. Requesting search results from the eBay REST API.
 *
 * This file is an example of searching eBay using its REST API, utilizing the
 * CURL package to make the request and return the results.
 */

/* Was a search request received? */
if (isset($_REQUEST['search_text'])) {
    $request_token =    '[UserToken]';
    $request_user_id =  '[UserName]';
    $query = $_REQUEST['search_text'];

    /* Create the REST string */
    $rest_request = 'http://rest.api.ebay.com/restapi?'
        .'RequestToken='.$request_token
        .'&RequestUserId='.$request_user_id
        .'&CallName=GetSearchResults'
        .'&Schema=1'
        .'&Query=''.urlencode($query).'''
        .'&MaxResults=10'
        .'&SearchInDescription=1'
    ;

    try {
        $curl_request = curl_init( );
        /* Set the URL to post the request to */
        curl_setopt($curl_request, CURLOPT_URL, $rest_request);
        /* This allows for errors to be handled */
        curl_setopt($curl_request, CURLOPT_FAILONERROR, 1);
        /* This allows for redirection */
        curl_setopt($curl_request, CURLOPT_FOLLOWLOCATION, 1);
        /* This sets the response to be set into a variable */
        curl_setopt($curl_request, CURLOPT_RETURNTRANSFER, 1);
        /* This sets a timeout for 30 seconds */
        curl_setopt($curl_request, CURLOPT_TIMEOUT, 30);
        /* This sets the post option */
        curl_setopt($curl_request, CURLOPT_POST, 0);
        /* Execute the CURL process, and set the results to a variable */
        $result = curl_exec($curl_request);
        /* Close the connection */
        curl_close($curl_request);
    } catch (Exception $ex) {
        $result = $ex.message;
    }
} else
    $result = "A search request was not sent.";
print ($result);
?>

Example 18-9 uses the CURL package, which must be installed on the web server on which the code will be executed. You will notice that I set some additional parameters as part of the GetSearchResults request. Here is a list of the parameters available to set with this method: Query, Category, ItemTypeFilter, PayPal, SearchInDescription, LowestPrice, HighestPrice, PostalCode, MaxDistance, Order, MaxResults, and Skip. Any of these could be sent as part of the request from the client; the server-side script would simply need to be modified to handle those $_REQUEST parameters as well.

Other Services

Of course, other services are available, but they do not fit well into a broad category. Furthermore, they range in functionality and complexity. If a developer needs a service, more than likely she will be able to find it on the Web somewhere with a bit of investigating. If a service has not been created yet, a few posts to forums might reveal someone else with the same needs. Collaborative efforts often produce great results.

The following is a sample of some of the other services available:

ESV Bible Lookup

The English Standard Version (ESV) Bible Lookup provides a way for users to search and read the ESV Bible online. The ESV Bible Lookup provides an API to access its functionality from outside sources, the documentation for which you can find at http://www.gnpcb.org/esv/share/services/api/.

Amnesty International

Amnesty International has provided a service that allows users to search for documents written about the freedom of expression, especially on the Internet. An API is provided to developers so that they can build custom applications that use the same database of content used by Amnesty International’s campaign. The documentation for this API is located at http://irrepressible.info/api.

411Sync

411Sync enables developers to have keyword searches available through mobile technology, giving sites better exposure to end users. The API for this functionality is available at http://www.411sync.com/cgi-bin/developer.cgi.

Windows Live Custom Domains

The Windows Live Custom Domains service allows developers to programmatically manage their Windows Live Custom Domains user base. The API documentation for this functionality is available at http://msdn2.microsoft.com/en-us/library/bb259721.aspx.

Sunlight Labs

Sunlight Labs provides clerical information about members of the 110th U.S. Congress, such as phone number, email address, district, and so on. An API facilitates this functionality; you can find the documentation at http://sunlightlabs.com/api/.

Food Candy

Food Candy is a social networking system for people who live for food. An API is available that helps developers with the functionality required of any social networking application. The API documentation is located at http://www.foodcandy.com/docs/html/index.html.

Facebook

Facebook is a social networking system that allows friends to keep in contact with one another online. Facebook provides an API that allows developers to programmatically add content to a Facebook account from outside applications. The documentation for this API is at http://developers.facebook.com/.

Ajax and the API

Some of these APIs treat Ajax differently than others. For example, a lot of the individual APIs are meant to be called by a server application that can then give results to a calling client. The Google Maps API, in contrast, is expected to be used entirely by the client, so its API is designed for use with JavaScript. These differences result in what I consider true Ajax functionality and pseudo-Ajax functionality.

The web services with true Ajax functionality give just that—the functionality is for the client to request data, have it retrieved via these services on the server, and then have it sent back to the client to be handled. This model can also fit both SOA and REST architecture, leaving that choice as an option that is not forced on the developer at this level.

This pseudo-Ajax web service functionality sits in those APIs where the Ajax calls are enacted within hidden <frame> or <iframe> elements and the Ajax is faked (and a little more complicated) in some cases. Of course, this pseudofunctionality is also the only viable solution to the problems that these services address. With these APIs, the developer must truly play within the constraints defined by the API, as there is no control over the code or how it works (without prototyping new functionality on top of the existing API).

With that in mind, this section will focus on those true Ajax APIs and how you can use them with Ajax. In Chapter 19, I will show you how to combine true and pseudo-Ajax functionality to create a working mashup.

XMLHttpRequest and the Web Service

True Ajax functionality is such because the call to the web service is controlled by a server script, and the client will use the XMLHttpRequest object to tell it what to do. The client must have knowledge of the service that will be used so that it can pass any necessary parameters to the server making the call. Like all Ajax calls, it must also know what will be coming back in the response.

Based on the client’s needs, a well-formed XHTML response could be sent that “plugs” right in to a part of the client. Services that update frequently can save time working this way for ease of use and functionality. Good examples of these are weather services, stock services, and any other small stat-based service. The other nice thing about Ajax approaches of this nature is that the client couldn’t care less about the protocol that will be used to call the web service. REST will be used for all communication with the server, and it is the developer’s decision whether to use GET or POST as the method of sending requests to the server. This helps to keep the client component of the web service call very simple. The other simple component in the model is the web service component itself, and it is simple only because the developer usually has no control over it.

The intermediary between the client and the web service, our server script, is where all of the real functionality lies. I intentionally did not say complexity or difficulty in that last sentence, as it does not have to be either in a lot of cases, and it would be misleading to say that it is. Figure 18-2 shows what the different parts of a web service model look like.

A simple model showing the use of the XMLHttpRequest object to facilitate calling web services from the server

Figure 18-2. A simple model showing the use of the XMLHttpRequest object to facilitate calling web services from the server

As you can see from Figure 18-2, the use of the XMLHttpRequest object allows a single page to make multiple requests for web services on the server. Without Ajax, the page would have to do the calling itself, which would then require a refresh of the entire page.

The Next Step with Services

As you have seen by this point, the number and variety of services is such that it would be difficult to not find what you are looking for from at least one of them. And even if you can’t find what you need, you can always build it yourself, as I showed you in Chapter 17. Once the services are in hand, knowing how to best utilize them in an application is the next obstacle. Some of the best uses of web services involve combining two or more services to create mashups. Chapter 19 will explore the creation and usage of mashups to demonstrate just how effective combining services can be.

Even if mashups are not your thing, hopefully the usefulness of web services in your applications has some appeal to you. Using a web service in your application has the potential to greatly reduce development time and speed up application deployment simply by being a resource to use, instead of having to create it all from scratch. Web services do not necessarily require Ajax to operate, but by utilizing this technology, your web applications will gain a little bit more Web 2.0 pizzazz.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset