|
|
FriendFeed API Documentation
Introduction
The FriendFeed API enables developers interact with the FriendFeed web site programmatically via simple HTTP requests.
This is the technical documentation for the API. Other important links:
- FriendFeed API Homepage
- FriendFeed API Developer Forum
- FriendFeed API Application Guidelines
- FriendFeed API Python, PHP, and C# Libraries
Core Concepts
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.
Note: We are currently exploring adding OAuth support as well. If you are interested in this support, let us know in the FriendFeed developer forum.
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[]
- id - the FriendFeed entry UUID, used to add comments/likes to the entry
- title
- link
- published
- updated
- hidden - if true, this entry should be hidden based on the user's preferences
- user{} - the user who shared this entry
- id - the user's FriendFeed UUID
- name - the user's full name
- nickname - the user's FriendFeed nickname, used in FriendFeed URLs
- profileUrl - the user's profile URL on FriendFeed
- 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"
- iconUrl - the URL of the favicon for this service
- profileUrl - the user's profile URL on this service
- comments[]
- date
- id - the UUID of the comment
- user{} - same structure as the user{} structure above
- body - the textual body of the comment
- likes[]
- date
- user{} - same structure as the user{} structure above
- 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
- via{}? - present if this entry came from an API client
- name - the name of the API client, e.g., "Alert Thingy"
- url - the official URL of the API client, e.g., http://www.alertthingy.com/
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.
Get User Profile Information
/api/user/USERNAME/profile - Get services and subscriptions
Returns list of all of the user's subscriptions (people) and services connected to their account:
http://friendfeed.com/api/user/bret/profile
The returned JSON has the form:
- id - the user's FriendFeed UUID
- name - the user's full name
- nickname - the user's FriendFeed nickname, used in FriendFeed URLs
- profileUrl - the user's profile URL on FriendFeed
- services[] - the services connected to the user's account
- id - the service's FriendFeed ID, e.g., "picasa"
- name - the service's official name, e.g., "Picasa Web Albums"
- url - the official URL of the service, e.g., http://picasaweb.google.com/
- iconUrl - the URL of the favicon for this service
- profileUrl? - the user's profile URL on this service, if any
- username? - the user's username for this service, if any
- subscriptions[] - the user's this user is subscribed to
- id
- name
- nickname
- profileUrl
Sign in to add a comment

I'm thinking of writing an app to search for all my Twitter friends on Friend Feed. I can see how I could go about finding them on the advanced search page.
But how do I add them as a friend without webscraping?
Also, it would be nice to get an API to get the list of the available Friend Feed services for building drop down boxes, etc. Especially if we don't need a remote key to get that information.
I would also like to be able to retrieve a list of services.
How about a way for users to sign up on Friend Feed through our site?
So we re-direct them, they sign up, and get sent back to our sites.
thelevybreaks: we will add that feature. Thanks for bring it up.
How about 1) An api that lets you add and remove friends? 2) An api that lets you add virtual friends? 3) letting virtual friends comment/like your posts?
The XML output doesn't seem to totally line up with the documented structure above. iconUrl has been added to 'service' and the comments are in multiple 'comment' tags. Not sure re: likes and media as my stream doesn't have them in at the moment (presume it's multiple like and media tags).
Hi. If I search on 'bell' with the api it seems to match on user names and link text as well as the title. This means I get everything posted by 'Clayton Bell' to friendfeed rather than things having to do with 'bell'. (Nothing personal Clayton) Is there a way to restrict the search to the actual content (title) rather than a whole bunch of fields ?
JeffNClark: unfortunately, there is no way to restrict your search currently, but this is a common feature request, so we will likely add that capability in the future.
I'd like an optional argument to /api/share that would cause an error to be returned if the user's feed is public. This could be used for "unlisted" material.
How about a way to pull comments for a specific item to display along with my other blog comments.
Hi!
I'm trying to delete a comment, but can't get it work... I have no UUID for comments in xml file!?
Here is a <comment> structure : <comment>
</comment>Thx for help!
Going along with bastien, could we have a method to pull back a single comment based on ID?
Comment IDs have now been added! Thanks for letting us know about it.
I'd love to be able to get a structure of the user's hidden services and an API call to hide a service.
I'd also like to be able to query the FOAF structure: given a Twitter user, find their Friend Feed account name, given a Friend Feed account name, find their Twitter username, etc.
I'd absolutely LOVE a REST based way to create an imaginary friend in one click. Then you could create a Greasemonkey script for twitter.com that put an "Add this person to Friend Feed" link on user pages.
Given only the entry id (550e8400-e29b-41d4-a716-446655440000), we should be able to query the API to get the data structure for it.
engtech: since you'll be using GM, you can already use the web interface to add/remove/list Imaginary Friends. See the friendfeedfun.rb file I posted to the FF dev forum for ideas, and I implemented the list functionality in the Filters script from a few days ago. (Aviv/FF)
The XML profile doesn't quite match the docs... instead of <subscriptions> .. </subscriptions> and <services> .. </services> with arrays of elements, it returns separate <subscription> and <service> elements.
Simple search for everyone, both using web page and API, doesn't return any results fresher than around 6am April 25th.
Is there a way to request all entries for a specific URL?
ydfeed: there is no way to request all entries for a specific URL currently.
the csharp implementation of the Entry class currently does not appear to be populated. For example (and most annoying), the Service value doesn't indicate the service origin of each entry. Each Entry.Service.IconUrl? value is always null as well. Is there any plan to fix this? Thanks, love the service overall.
Is there a function to quickly validate a user's login credentials (username and RemoteKey?)? Similar to twitter's "verify_credentials" and pownce's "verify callback".
It would just be really nice to confirm immediately for a user whether we're able to successfully use the account info they provide when enabling integration, rather than waiting until they first post and having them discover an "unauthorized" error then.
Please, add Serialized PHP output :o|
I don't understand how paging is supposed to work. The document mentions that:
"start - return entries starting with the given index, e.g., start=30 "
What is that index? Is it the entry id? If so, why does start=foo-bar-UUID returns the entries up to the specified id and not the ones after that? Is there some other way I can obtain the list of updates after a specific entry that I have cached?
patith: it is like the Google search result pages. start=30 means "start on the 30th most recent entry". You would page 30 at a time with start=0, start=30, start=60, etc.
Some users have too many friends and we fetch their profiles data slowly :o(
I submit to remove subscriptions from /api/user/USERNAME/profile method and create dedicated method.
Could you add blogs titles into /api/feed/home method results ? Thank :o)
How could I get the line that says: "published photos on Flickr" and such? That tell me the exact action? Currently, all the activities (favouriting a photo on Flickr, posting a photo on Flickr, etc.) look the same from the API.
Is there any info about that, or it's not possible to get this at the moment?