API Responses as Feeds

You know three things that would be cool?

  • the ability to subscribe to the output of a Flickr API call in a feed aggregator
  • the ability to get the results of Flickr API calls as KML (or GeoRSS)
  • if all those devices that support RSS feeds (like photo frames!) also supported the Flickr API.

You see where I’m going with this don’t you?

You can already specify that you want the output format of a Flickr API call to be REST (POX), XML-RPC, SOAP (shudder, not sure that one still works), JSON, or serialized PHP. We always wanted to support formats like KML, or Atom but we were never quite sure how to represent the results of a call to flickr.photos.getInfo() or flickr.photos.licenses.getInfo() as a KML.

Last week we finally got around to pushing out our 80% solution — an experimental response format for API methods that use the standard photos response format that allows you to request API responses as as one of our many feed formats.

You can now get the output of flickr.photos.search(), or flickr.favorites.getList() as Atom, or GeoRSS, or KML, or whatever.

API Feed Types

The syntax is "&format=feed-{SOME_FEED_IDENTIFER}" where the feed identifiers follow the same convention you use when fetching…feeds.

  • feed-rss_100, API results will be returned as a RSS 1.0 feed
  • feed-rss_200, API results will be returned as a RSS 2.0 feed
  • feed-atom_10, API results will be returned as a Atom 1.0 feed
  • feed-georss, API results will be returned as a RSS 2.0 feed
    with corresponding GeoRSS and W3C Geo elements for geotagged
    photos
  • feed-geoatom, API results will be returned as a Atom 1.0 feed
    with corresponding GeoRSS and W3C Geo elements for geotagged
    photos
  • feed-geordf, API results will be returned as a RSS 1.0 feed
    with corresponding GeoRSS and W3C Geo elements for geotagged
    photos
  • feed-kml, API results will be returned as a KML 2.1 feed
  • feed-kml_nl, API results will be returned as a KML 2.1 network
    link feed

And remember, format is an API arg, and needs to be included in your API signature if you’re making a signed API call.

Namespaces, pagination, bits and bobs

You’ll find the feeds now include the venerable xmlns:flickr=”urn:flickr:” namespace. This is used to declare bits that don’t fit elsewhere like pagination.

Pagination information is passed as a single namespaced (‘urn:flickr:)
element under the feed’s root (or “channel” element if it has one). For
everything but RSS 1.0 based feeds it looks like this:

<flickr:pagination total="480" page="1" pages="96"
per_page="5" />

For RSS 1.0 we do a little RDF dance:

<flickr:flickr>
     <pagination>
             <total>480</total>
             <page>1</page>
                 <pages>32</pages>
             <per_page>15</per_page>
     </pagination>
</flickr:flickr>

Speaking of pagination, to start with we’ve enforced a maximum “per
page” limit of 15. If people have a reasonable use case we may
consider raising the limit but otherwise we need to account for the
extra data/size that feed formats add.

You’ll also find some extras like

<entry>
    ...
    <flickr:views>3</flickr:views>
    <flickr:original type="png" href="http://farm4.static.flickr.com/3074/2783931781_12f84e4079_o.png" width="640" height="480" />
</entry>

Error Handling

If an error occurs, the API will return a 400 HTTP status code.

Flickr error codes and message are returned as X-FlickrErrCode and X-FlickrErrMessage
HTTP headers. For example:

X-FlickrErrCode: 111
X-FlickrErrMessage: Format "feed-lolcat" not found

Caveats and Warnings

  • This is EXPERIMENTAL. It might change, it might go away, but we hope not. We also could potentially make it better based on all your awesome feedback.

  • This is not available for all methods. If you call photos.getInfo and
    ask for a feed response format all you will get is an error.

  • Just like any API call (or feed usage or really anything else) you are required to respect the copyright of the photographer.

  • These are still API calls. All the usual rules about usage apply.
    You are still bound by the Flickr API TOU and any other rules,
    capricious or not, we apply to API usage. Including rate limits. If
    you feed this in to an overly-aggressive aggregator we will make your
    API key cry. (In an entirely non-creepy way)

Putting it together: ego feeds

Turns out ‘kellan’ is a popular baby name these days, so whenever I go ego surfing Flickr I tend to see pictures of two year olds. This changes (for now) when I limit my searching to my friends photos. Using API feeds I can now build an ego feed of photos from my friends, like so:

flickr.photos.search:
   user_id => 51035734193@N01,
   contacts => all,
   text => kellan,
   sort => date-posted-desc,
   api_key => {API_KEY}
   auth_token => {AUTH_TOKEN}
   format => feed-atom_10

api.flickr.com/services/rest/?auth_token=xxxx&user_id=51035734193%40N01&
   contacts=all&format=feed-atom_10&sort=date-posted-desc&text=kellan
   &api_key=xxxx&method=flickr.photos.search&api_sig=xxxx

Putting it together: near home

Or a KML feed of the most interesting, safe, CC licensed photos, within 10 kilometers of a point (say your home), suitable for remixing:

flickr.photos.search:
   license => 1,2,4,5,7,
   sort => interestingness-desc,
   lat => 40.661699,
   lon => -73.98947,
   radius => 10,
   safe_search => 1,
   api_key => {API_KEY}
   format => feed-kml

api.flickr.com/services/rest/?auth_token=xxx&license=1%2C2%2C4%2C5%2C7&
  lat=40.661699&lon=-73.98947&radius=10&safe_search=1
  &format=feed-atom_10&api_key=xxxx&method=flickr.photos.search
  &api_sig=xxxxx

You get the idea.

Standard Photos Response, APIs for a civilized age.

Funny story. I went to write a blog post and when the time came to link to the documentation of our standard “standard photos response” structure, I found we had never documented it!

Okay. Maybe that wasn’t so funny.

But anyway, this is the blog post before that other blog post, so that when I write that other blog post I’ve got something to point to.

And besides you should know this stuff if you’re using the API. It’s good stuff.

Standard Photos Response

The standard photos response is a data structure that we use when we want to return a list of photos. Most prominently the ever popular swiss-army-API flickr.photos.search() uses it, but also methods like flickr.favorites.getList() or flickr.groups.pools.getPhotos().

Beyond a common structure that gets serialized across all our different API response formats, standard photos response methods share a common set of arguments for sorting and paging (after all these are lists of photos), and the special extras argument.

Standard Photo Response, the XML Serialization

You’re basic standard photos response looks like this. It’s just an envelope for delivering a list of photos.

<rsp stat="ok">
  <photos page="1" pages="7" perpage="100" total="608">
    <photo id="2777191844" owner="51035734193@N01" secret="653a19d017" server="3059" farm="4" title="FAIL" ispublic="1" isfriend="0" isfamily="0"/>
    <photo id="2771521705" owner="51035734193@N01" secret="1878507379" server="3178" farm="4" title="In the street" ispublic="1" isfriend="0" isfamily="0"/>
  </photos>
</rsp>

We’ve got the standard Flickr <rsp> root element, a <photos> container describing the full list and the page we’re on, and some <photo> elements that include everything we need to display a photo.

extras: the concept

Another largely undocumented deep structure in the Flickr API is a distinction between getList() and getInfo() methods. We tend to return a pared down list of identifiers, and provide methods for getting more info about individual items. Generally it’s a very useful pattern, and saves us all bandwidth, processing, and data rot.

However sometimes (often?) you’re wanting to display a bunch of photos, and having to roundtrip to call flickr.photos.getInfo() for every single one of them is annoying. (not to mention slow, and likely to get you frowned upon by our ops team)

That’s where extras come in. The idea behind extras is you can selectively enrich the bare bones list I showed you earlier with the metadata you need to display your bunch of photos, without the round trip, and without fetching more then you’ll need.

extras: the details

There are currently 13 different extras available, and we add new ones periodically as new concepts come online, or you make a compelling enough case for them.

As of today they are: license, date_upload, date_taken, owner_name, icon_server, original_format, last_update, geo, tags, machine_tags, o_dims, views, media.

license

Is the photo “All rights reversed”? Licensed under one of the CC license?

<photo id="2777191844" owner="51035734193@N01" secret="653a19d017"
 server="3059" farm="4" title="FAIL" ispublic="1" isfriend="0" isfamily="0" 
 license="3"/>

license=”3” means Attribution-NonCommercial-NoDerivs, you can get our mappings with flickr.photos.licenses.getInfo().

date_upload, date_taken, last_update

When was the photo uploaded to Flickr? When do we think it was taken? When was its metadata last twiddled?

<photo id="2772368826" owner="51035734193@N01" secret="1078392104"
 server="3122" farm="4"       title="Finger on the button" ispublic="1" isfriend="0" isfamily="0"
 license="3"  dateupload="1219006901" datetaken="2008-08-17 12:38:06" 
datetakengranularity="0"     lastupdate="1219117103"/>

Yes the extras param is called date_upload the attribute is dateupload, what can I say, legacy. Notice also that dateupload and lastupdate are epoch seconds, while datetakengranularity is probably best ignored.

owner_name and icon_server

Everything you need to properly credit the photographer, including their name, and the info necessary to display their buddyicon.

<photo id="2772368826" owner="51035734193@N01" secret="1078392104" 
server="3122" farm="4" title="Finger on the button" ispublic="1" isfriend="0" isfamily="0" 
ownername="kellan" iconserver="54" iconfarm="1"/>

geo

If the photo was geotagged include the latitude, longitude, and accuracy of the geotagging.

<photo id="2772368826" owner="51035734193@N01" secret="1078392104" 
server="3122" farm="4" title="Finger on the button" ispublic="1" isfriend="0" isfamily="0" 
latitude="40.714666" longitude="73.957333" accuracy="16"/>

tags and machine_tags

Note these are the “clean” versions of the tags and machine tags, which means spaces, and most punctuation will have been stripped. Safe to display in HTML, and useable as URL fragments.

<photo id="2772368826" owner="51035734193@N01" secret="1078392104" 
server="3122" farm="4" title="Finger on the button" ispublic="1" isfriend="0" isfamily="0" 
tags="nyc streetart williamsburg ph:camera=iphone3g" 
machine_tags="ph:camera=iphone3g"/>

original_format and o_dims

Assuming you’re making API calls as a member who is authorized to download a photo (e.g. the photographer) you can ask for details about the unmodified, full resolution photo that was uploaded. Get the original file format, the secret needed to construct the URL to the photo, and what the original’s dimensions are.

<photo id="2772368826" owner="51035734193@N01" secret="1078392104" 
server="3122" farm="4" title="Finger on the button" ispublic="1" isfriend="0" isfamily="0" 
originalsecret="xxxxxxxx" originalformat="jpg" o_width="1200" 
o_height="1600"/>

views

How many times has this photo been viewed by folks other then the person who uploaded it?

<photo id="2772368826" owner="51035734193@N01" secret="1078392104" 
server="3122" farm="4" title="Finger on the button" ispublic="1" isfriend="0" isfamily="0" 
views="9"/>

media

Is it a photo? Or a video? Has it been processed and is it ready for displaying? (media_status is a lot more useful for videos)

<photo id="2771521705" owner="51035734193@N01" secret="1878507379" 
server="3178" farm="4" title="In the street" ispublic="1" isfriend="0" isfamily="0" 
media="photo" media_status="ready"/>

Wow. What a list. Really, what more could anyone ever want? (that’s rhetorical)

The punch line

That’s standard photos responses, and how to use extras (paging and sorting is left as an exercise to the reader). Mastering the format is the key to building both interesting and performant API applications. use the metadata, love the metadata, and ditch the round trip.

And now for the that next blog post I mentioned ….