Deeper look into Friendfeed API

FriendFeed is the new hotness and many people have asked for an API to take the service to the next level. There aren’t any example apps built yet, nor has there been much developer feedback yet. A whole lot of things just became possible, though.

As for technical details: FriendFeed is first releasing Python and PHP libraries, there’s an undisclosed access limit and oAuth authentication is "coming soon" (we hope so).

If you’re less than on fire about APIs and their potential – check out our post called APIs and Developer Platforms, A Discussion of the Pros and Cons – and know that 16 of the 18 authorities quoted in that post were interviewed entirely through a 3rd party Twitter client using that API.

If you’re a Twitter user you know how essential to Twitter that company’s API has become, an estimated 80% or more of Twitter use comes in through the API and the constellation of 3rd party services that leverage it. The FriendFeed API may be the most eagerly awaited since Twitter’s

This Aint Just RSS Readin’

Casual users should take note that FriendFeed is far more than just an RSS aggregator. Check out the podcast and transcript of our interview with the company’s founders in early February for details. See also my recent interview with RSS keystone Dave Winer, where we discussed FriendFeed more than anything else. You’d have seen it already if you were my friend on FriendFeed.

Commenting, feed and item display, liked-by-a-friend item exposure and a smooth friend recommendation path are some of the key differentiators of FriendFeed. In February at least, only 70% of the feeds coming into FF were RSS feeds, too. The rest are from other kinds of 3rd party APIs that the FriendFeed team has tied into by hand. There are many different Lifestreaming apps, but FriendFeed has a lot of momentum, a good user experience, renders well on mobile and has caught peoples’ imaginations. It’s also got some heavyweight backers.
The Possibilities

Some of the examples from the FriendFeed announcement are these:
"[The API is] designed to make it possible for anyone to payday loans improve FriendFeed or integrate FriendFeed into other applications. You can develop a FriendFeed interface for a mobile phone, build a FriendFeed widget for your blog, or develop an application that makes it easy to post photos to your feed from your iPhone."

I’m cheering for an Adobe AIR desktop interface, APML import/export and some sophisticated item-level recommendations. How about a FriendFeed/Imeem mashup? I’d love to listen to a streaming radio station of all the music that my FriendFeed friends favorite on their respective music networks. Oh the possibilities are many. This is a very exciting announcement.

Requests and Data Formats

All requests to the FriendFeed API are simple HTTP GET and POST requests. For example, you can fetch the JSON version of the most recent 30 public entries published to FriendFeed by fetching http://friendfeed.com/api/feed/public.

All of the API requests that output feeds are available in four formats: JSON, a simple form of XML, RSS 2.0, and Atom 1.0. JSON is the default output format. To request a different output format, simply add an format= argument to the URL:

    * http://friendfeed.com/api/feed/public?format=json
    * http://friendfeed.com/api/feed/public?format=xml
    * http://friendfeed.com/api/feed/public?format=rss
    * http://friendfeed.com/api/feed/public?format=atom

The other API requests, like posting a new comment on an entry, only support the JSON and XML output formats since they do not output feed-oriented data.

Authentication

If you are publishing data to FriendFeed or if you are requesting the feed that includes data from a user with a private feed, your HTTP requests must be authenticated.

All FriendFeed users have a Remote Key to provide third party applications access to their FriendFeed. A FriendFeed Remote Key is just like a password, except that it is only used for third party applications, so it only provides access to the functionality defined by the API. Users can easily reset it if a third party application abuses the API.

All requests that require authentication use HTTP Basic Authentication. The username should be the user’s nickname, and the password should be the user’s Remote Key. You can direct user’s to http://friendfeed.com/remotekey to get their remote key if they have not memorized it. See the FriendFeed API Application Guidelines for a complete set of recommendations of how to present authentication in your application.

The Python and PHP libraries available at http://code.google.com/p/friendfeed-api/ implement authentication for all methods that require it.

Remote Key

A remote key is a kind of password that you can give to third-party applications and websites to let them interact with FriendFeed on your behalf. There are limits to what can be done using a remote key, which means it’s a lot safer than giving a site your FriendFeed password.

JSON Callbacks

The JSON output format supports an additional argument callback= that wraps the JSON output in a function call to a function of your choice. This functionality is available to enable you to use the API with JavaScript within a web browser. For example, http://friendfeed.com/api/feed/public?callback=foo outputs:

foo({"entries":[…]})

Using JSON and callbacks, you can place the FriendFeed API request inside a <script> tag, and operate on the results with a function elsewhere in the JavaScript code on the page.

All authentication is ignored if the callback= argument is given, so JSON callbacks only work with public feeds.

Reading FriendFeed Feeds
Overview
Feed Formats

The JSON form of the feeds has the following structure:

    * entries[]
          o id – the FriendFeed entry UUID, used to add comments/likes to the entry
          o title
          o link
          o published
          o updated
          o user{} – the user who shared this entry
                + id – the user’s FriendFeed UUID
                + nickname – the user’s FriendFeed nickname, used in FriendFeed URLs
                + profileUrl – the user’s profile URL on FriendFeed
          o service{} – the service from which the entry came
                + id – the service’s FriendFeed ID, e.g., "picasa"
                + name – the service’s official name, e.g., "Picasa Web Albums"
                + profileUrl – the user’s profile URL on this service
          o comments[]
                + date
                + user{} – same structure as the user{} structure above
                + body – the textual body of the comment
          o likes[]
                + date
                + user{} – same structure as the user{} structure above
          o media[] – the videos/images associated with the entry
                + title? – the title of the media file
                + player? – the player for this media file (e.g., the YouTube.com URL with the embedded video)
                + thumbnails[] – the thumbnails for this media file
                      # url
                      # width
                      # height
                + content[] – the different versions of the media file
                      # url
                      # type – the MIME type of the media file
                      # width
                      # height

The simple XML format (output=xml) has the same structure as the JSON. The RSS and Atom formats use the standard RSS and Atom attributes for title, link, published, and updated, and include extension elements for all of the other meta-data.

Dates in JSON and dates in the FriendFeed extension elements in the Atom and RSS feeds are in RFC 3339 format in UTC. You can parse them with the strptime string "%Y-%m-%dT%H:%M:%SZ".

Filtering & Paging

All of the feed methods below support the following additional arguments:

    * service – only return entries from the service with the given ID, e.g., service=twitter
    * start – return entries starting with the given index, e.g., start=30
    * num – return num entries starting from start, e.g., num=10

Methods

/api/feed/public – Fetch all Public Entries

Returns the most recent public entries on FriendFeed:

http://friendfeed.com/api/feed/public

Using the FriendFeed Python library:

service = friendfeed.FriendFeed()
feed = service.fetch_public_feed()
for entry in feed["entries"]:
    print entry["title"]

/api/feed/user/NICKNAME – Fetch Entries from a User

Returns the most recent entries from the user with the given nickname:

http://friendfeed.com/api/feed/user/bret

If the user has a private feed, authentication is required.

Using the FriendFeed Python library:

service = friendfeed.FriendFeed()
feed = service.fetch_user_feed("bret")
for entry in feed["entries"]:
    print entry["title"]

/api/feed/user/NICKNAME/comments – Fetch Entries a User Has Commented On

Returns the most recent entries the user has commented on, ordered by the date of that user’s comments:

http://friendfeed.com/api/feed/user/bret/comments

If the user has a private feed, authentication is required.
/api/feed/user/NICKNAME/likes – Fetch Entries a User Has "Liked"

Returns the most recent entries the user has "liked," ordered by the date of that user’s "likes":

http://friendfeed.com/api/feed/user/bret/likes

If the user has a private feed, authentication is required.
/api/feed/user/NICKNAME/discussion – Fetch Entries a User Has Commented On or "Liked"

Returns the most recent entries the user has commented on or "liked":

http://friendfeed.com/api/feed/user/bret/discussion

If the user has a private feed, authentication is required.
/api/feed/user – Fetch Entries from Multiple Users

Returns the most recent entries from a list of users, specified by nickname:

http://friendfeed.com/api/feed/user?nickname=bret,paul,jim

If more than one nickname is specified, the feed most recent entries from all of the given users. If any one of the users has a private feed, authentication is required.

Using the FriendFeed Python library:

service = friendfeed.FriendFeed()
feed = service.fetch_multi_user_feed(["bret", "jim", "paul"])
for entry in feed["entries"]:
    print entry["title"]

/api/feed/home – Fetch the Friends Feed

Returns the entries the authenticated user would see on their FriendFeed homepage – all of their subscriptions and friend-of-a-friend entries:

http://friendfeed.com/api/feed/home

Authentication is always required.

Using the FriendFeed Python library:

service = friendfeed.FriendFeed(nickname, remote_key)
feed = service.fetch_home_feed()
for entry in feed["entries"]:
    print entry["title"]

/api/feed/search – Search

Executes a search over the entries in FriendFeed. If the request is authenticated, the default scope is over all of the entries in the authenticated user’s Friends Feed. If the request is not authenticated, the default scope is over all public entries.

http://friendfeed.com/api/feed/search?q=friendfeed

The query syntax is the same syntax as http://friendfeed.com/search/advanced. The query operators are:

    * who: -restricts the search to a specific user, e.g., who:bret
    * service: restricts the search to a specific service ID, e.g., service:twitter

Using the FriendFeed Python library:

service = friendfeed.FriendFeed()
feed = service.search("who:bret friendfeed")
for entry in feed["entries"]:
    print entry["title"]

Publishing To FriendFeed

All of the calls to publish information to FriendFeed are HTTP requests. You can perform test calls from a web browser using the HTTP Basic Authentication built into your browser at http://friendfeed.com/static/html/apitest.html.

Requests to FriendFeed are rate limited, which, e.g., limits the number and size of thumbnails you can upload in a day. Normal uses should fall well within our rate limits. If you encounter HTTP 403 errors because of rate limits, and you think the limit is erroneous, please let us know in the developer forum.

Create New Entries
/api/share – Publish Links or Messages

A POST request to /api/share will publish a new entry on the authenticated user’s feed. The arguments are:

    * title – required – The text of the new entry.
    * link – The URL of the new entry. If it is not specified, the new entry will look like a quoted message. If specified, it will look like a link.
    * comment – If specified, the given text is posted as a comment under the new entry.
    * imageN_url, imageN_link – The thumbnail images for the entry, specified from a 0-based index. image0_url specifies the URL of the image, which will be resized to the maximum size of a thumbnail and stored on FriendFeed’s servers. If image0_link is not given, the thumbnail will link to the main link URL. If it is specified, the thumbnail will link to the specified image0_link.

Example usage with the FriendFeed Python library:

service = friendfeed.FriendFeed(nickname, remote_key)

# Publish a text message
service.publish_message("Testing the FriendFeed API")

# Publish a link
service.publish_link("Testing the FriendFeed API", "http://friendfeed.com/api/")

# Publish a link with thumbnail images
service.publish_link(
    title="Testing the FriendFeed API",
    link="http://friendfeed.com/api/",
    image_urls=[
        "http://friendfeed.com/static/images/jim-superman.jpg",
        "http://friendfeed.com/static/images/logo.png",
    ],
)

Example usage with curl:

curl -u "nickname:remotekey" -d "title=Testing+the+FriendFeed+API&link=http://friendfeed.com/" http://friendfeed.com/api/share

Upload Images with Entries

The /api/share method can also accept uploaded images encoded as multipart/form-data. This encoding is the standard used for file uploads within web browsers.

If any images are uploaded with the /api/share request, the original and the thumbnail are stored on FriendFeed’s servers, and the thumbnail is displayed with the entry.

By default, the thumbnails will link to the destination link for the entry. If you want each uploaded image to link somewhere else, you can specify the link in the IMAGENAME_link argument. For example, if your uploaded image is POST argument file0, you can specify the link for that thumbnail as file0_link.

Comment and Like Entries
/api/comment – Add or Edit Comments

A POST request to /feed/comment will add a comment or edit an existing comment on a FriendFeed entry. The arguments are:

    * entry – required – The FriendFeed UUID of the entry to which this comment is attached.
    * body – required – The textual body of the comment.
    * comment – If given, the FriendFeed UUID of the comment to edit. If not given, the request will create a new comment.

Example usage from the Python library:

service = friendfeed.FriendFeed(nickname, remote_key)
service.add_comment(
    entry="550e8400-e29b-41d4-a716-446655440000",
    body="Testing the FriendFeed API",
)

Example usage with curl:

curl -u "nickname:remotekey" -d "entry=550e8400-e29b-41d4-a716-446655440000&body=Testing+the+FriendFeed+API" http://friendfeed.com/api/comment

/api/comment/delete – Delete a Comment

A POST request to /feed/comment/delete will delete an existing comment. The arguments are:

    * entry – required – The FriendFeed UUID of the entry to which this comment is attached.
    * comment – required – The FriendFeed UUID of the comment to delete.

/api/like – "Like" an Entry

A POST request to /feed/like will add a "Like" to a FriendFeed entry for the authenticated user.

    * entry – required – The FriendFeed UUID of the entry to which this comment is attached

Example usage from the Python library:

service = friendfeed.FriendFeed(nickname, remote_key)
service.add_like("550e8400-e29b-41d4-a716-446655440000")

Example usage with curl:

curl -u "nickname:remotekey" -d "entry=550e8400-e29b-41d4-a716-446655440000" http://friendfeed.com/api/like

/api/like/delete – Delete a "Like"

A POST request to /feed/like/delete will delete an existing "Like." The arguments are:

    * entry – required – The FriendFeed UUID of the entry to which this comment is attached.

Authentication

If your application requires authentication, you use the following terminology FriendFeed nickname or email and Remote key in your login form. Your login form should contain a link to http://friendfeed.com/remotekey for users who have not memorized their key. It should open in a new window using target="_blank" so that the remote key page does not interrupt your application’s flow.

0 I like it
0 I don't like it