Skip to content
ankane edited this page Aug 23, 2011 · 53 revisions

The Graph API is the core of Facebook’s new interface. Let’s play with it.

API Changes in 1.2beta

With Koala 1.2beta, we’re consolidating all the API classes into Koala::Facebook::API. The GraphAndRestAPI class proved it’s easy to provide access to both the Graph and REST APIs in a single class, so there’s no reason to provide three classes when one would do. Don’t worry — this is a non-breaking change — the old GraphAPI, RestAPI, and GraphAndRestAPI classes are all aliased to API (with a deprecation warning).

Graph API: now in your browser!

Important side note: did you know you can play with the Graph API in your browser? It’s one of my favorite aspects of the new API. Facebook has released a Graph API Explorer, which lets you get an access token and explore the Graph easily. You can also make requests directly in your browser; for each example coming up, I include a link to the equivalent query. (If you haven’t been to http://graph.facebook.com, you should definitely click through and play with the results. Try your own nickname!)

Since I’m abbreviating the API results for space, I strongly encourage you to check it out.

Initializing

First, you need to create your API object that you will use to make your calls. If you want, you can also pass an access token to access private or restricted data, as explained in the “Getting Private Data” section of this page.

@graph = Koala::Facebook::GraphAPI.new # pre 1.2beta
@graph = Koala::Facebook::API.new # 1.2beta and beyond

Note that you can also use the GraphAndRestAPI class, which allows all-in-one access to both the Graph and Rest API.

Getting public data

Let’s get some data from Facebook.  To learn about an object, just use the get_object method.  For instance, you can learn about people:

# http://graph.facebook.com/koppel
@graph.get_object("koppel")
# => {"name"=>"Alex Koppel", "id"=>"2905623", "last_name"=>"Koppel", "link"=>"http://www.facebook.com/koppel", "first_name"=>"Alex"}

And Pages:

# http://graph.facebook.com/contextoptional
@graph.get_object("contextoptional")
# => {"name"=>"Context Optional, Inc.", "id"=>"7204941866", ....}

Even anonymously, you can get certain connections like a Page’s feed:

# http://graph.facebook.com/contextoptional/feed
@graph.get_connections("contextoptional", "feed")
# => array_of_stream stories

Or pictures:

# http://graph.facebook.com/koppel/picture
@graph.get_picture("koppel")
# => "http://profile.ak.fbcdn.net/v224/784/109/q2905623_7065.jpg"

p. Note: You can pass a ‘type’ hash key with a value of ‘small’, ‘normal’, ‘large’, or ‘square’ to obtain different picture sizes, with the default being ‘square’. Also, you may need the user_photos permission.

As well as details about individual public stories:

# http://graph.facebook.com/7204941866_117111188317384
@graph.get_object("7204941866_117111188317384")  # remember this ID
# => {"name"=>"Bare Escentuals Cosmetics",
#     "message"=>"We've just launched the Bare Escentuals "Mom & Me" application!",
#     "likes"=>3,
#     ....
#    }

You can also searches public posts for the keyword of your choice:

# http://graph.facebook.com/search?q=koala
@graph.search("koala")
# => {"data"=> [{"from"=>{"name"=>"Amy", ...}, "id"=>....,
#     "message"=>"My apartment is infested with koala bears...."}]}

You can also pass nil as the first parameter to #search in conjunction with a “type” argument to see all of the public objects of a given type:

# http://graph.facebook.com/search?type=post
@graph.search(nil, {:type => "post"})
# => {"data"=> [{"from"=>{"name"=>"Bob", ...}, "id"=>....,
#     "message"=>"I hope everyone can read this message...."}]}

Getting Private Data

Public data’s cool, but it’s often not enough. You want to know who your users are — their full details, their likes, their feed, their friends. Without an access token, you can’t get that:

@graph.get_connections("koppel", "likes")
# => Koala::Facebook::APIError: An access token is required to request this resource.

We’ll go over getting an access token in a moment. For now, head over to http://graph.facebook.com — Facebook’s Graph API developer site has a bunch of links, any of which will provide you with an access token. Copy that from the URL, and check out what you can do now:

# first, initialize a Graph API with your token
@graph = Koala::Facebook::GraphAPI.new(your_oauth_token) # pre 1.2beta
@graph = Koala::Facebook::API.new(your_oauth_token) # 1.2beta and beyond
 
# now, try that query again
# http://graph.facebook.com/koppel/likes?access_token=#{your_oauth_token}
@graph.get_connections("koppel", "likes")
# => [{"name"=>"Mechanics' Institute Library", ....}]

“me” is a very useful shortcut Facebook provides to getting the current user:

# http://graph.facebook.com/me?access_token=#{your_oauth_token}
@graph.get_object("me")
# => {"name"=>"Alex Koppel", ....}

With a user’s access token, you get any public information, plus additional information through extended permissions (see the OAuth section).

Writing to the Graph

Reading’s all well and good, but no discussion of the graph would be complete without some writing. In order to write to the social graph, you’ll need to prompt your user for the publish_stream extended permission (see the OAuth section).

For the sake of simplicity, let’s assume the token we got above has the right permissions; otherwise, you’ll get an error. (Since writing to the graph involves sending POST requests, the browser follow-along unfortunately has to end.)

Let’s start by posting to our own walls using the put_wall_post method.

@graph.put_wall_post("hey, i'm learning kaola")
# => {"id"=>"2905623_123183957698327"}

p. Oops — we misspelled Koala! How embarrassing.
@graph.delete_object("2905623_123183957698327")
# => true

Let’s never speak of that again, okay?

You can also write to other people’s walls. For instance, I’ll send a link to a cool (if sappy) comic to my husband.

@graph.put_wall_post("explodingdog!", {:name => "i love loving you", :link => "http://www.explodingdog.com/title/ilovelovingyou.html"}, "tmiley")
=> {"id"=>"83901496_520908898070"}

Speaking of family, Mother’s Day was coming up when I wrote this. Let’s go back to that earlier post about the Mother’s Day app my company just released, and like it.

@graph.put_like("7204941866_117111188317384")
# => true

Now it has 4 likes:

@graph.get_object("7204941866_117111188317384")
# => {"message"=>"We've just launched the Bare Escentuals "Mom & Me" application", "likes"=>4...}

Actually, changed my mind. I’m not a huge cosmetics fan.

@graph.delete_like("7204941866_117111188317384")
# => true

Personal confession: I still haven’t picked out a gift for my mom. Time to talk about how I need to do that.

@graph.put_comment("7204941866_117111188317384", "Can't believe Mother's Day's just a week away!  I'd better get on that gift.")
# => {"id"=>"7204941866_117111188317384_448625"} # ID of the comment

That’s more or less it for the Graph API. All the methods you just saw wrap a generic put_object method, which you can use whenever the convenience methods don’t work for you.

def put_object(parent_object, connection_name, args = {}) .... 

Retrieving Pages of Results

Thanks to jagthedrummer for this contribution!

When fetching data from Facebook that returns a list of results (i.e. using API#get_connections or API#search) Facebook returns a limited number of results per request. To help make paging through these results easier, Koala returns a GraphCollection object, a subclass of Array, that includes a few methods to ease getting the next and previous pages of results.

@result = @graph.get_connections('me', 'feed')
@result.class
# => Koala::Facebook::GraphCollection

# You can use a GraphCollection just like a normal Array or results
@result.first
# => {"actions" => [], "message" => "This my feed message.", ...}

To get the next (or previous) page of results, use the next_page (or previous_page) method on a GraphCollection.

@next_page = @result.next_page
# => [{"actions" => [], "message" => "This my feed message.", ...}, ...] 

@next_page.class
# => Koala::Facebook::GraphCollection

Paging Across Multiple (User) Requests

While paging through results is fun, most of the time you’ll want to fetch the next page of results only when requested by the user. The next_page_params and previous_page_params methods in conjunction with API#get_page method makes this a snap.

API#next_page_params returns an array with two entries describing the API URL to fetch the next page of results: the path and a hash of parameters.

@results.next_page_params
# => ['"me/feed", {"limit => "25", "access_token" => "...", ...}]

Using the result of next_page_params as the single argument to API#get_page you can retrieve the next page of your results.

Here’s an example using Rails:

# /app/controllers/foo_controller.rb
def index
  # get the first page, or a next/previous page if appropriate params are sent
  @results = params[:page] ? @graph.get_page(params[:page]) : @graph.get_connections("me", "feed")
end
# /app/views/foo/index.html.erb
<% @results.each do |result| %>
  <!-- Display each result -->
<% end %>

<%= link_to 'Previous', url_for(:page => @results.previous_page_params) %>
<%= link_to 'Next', url_for(:page => @results.next_page_params) %>

Notice that API#get_connections only needs to be called once, when you fetch the first page of results. By using next_page_params to populate the “page” URL parameter, you can use params[:page] as a single parameter to API#get_page to get the next set of results (as above).

This example takes advantage of how Rails serializes an array as URL parameters (and how Rails interprets URL parameters when handling requests.) Even without this functionality, however, creating appropriate parameters to use from next_page_params should be fairly straight forward.

Being a Page

Sometimes, a Facebook user isn’t just a Facebook user, she’s a Page. The Graph API makes it straightforward to act for a Page a user manages.

First, get the user to grant your app the manage_pages permission. Then, you can get the Page’s access token, and use that to create a new API object:

# you can easily get the access token for a single page:
page_info = @user_graph.get_object(page, :fields => "access_token") # pre 1.2beta
# => {"access_token" => page_token, "id" => page_id}
page_token = @user_graph.get_page_access_token(page_id) # 1.2beta and beyond
# => access_token
# (if you don't get access_token, you're missing the manage_pages permission)
@page_graph = Koala::Facebook::GraphAPI.new(page_token) # pre 1.2beta
@page_graph = Koala::Facebook::API.new(page_token) # 1.2beta and beyond

# you can now use @page_graph to do things on behalf of the page
@user_graph.put_object('some-profile-id', 'feed', :message => 'This is posted as the user')
@page_graph.put_object('some-profile-id', 'feed', :message => 'This is posted as the page')
# you can also get a list of the user's pages and associated access tokens
# through the accounts connection (if you have manage_pages)
pages = @user_graph.get_connections(user_id, "accounts")
# => [{"name"=>"pageName", "id"=>"pageID", "access_token"=>"PageToken"}, ...other pages...]

# note on permissions: 
#   "The permissions granted by a user to your application will now also be applicable to their pages."
#    see http://developers.facebook.com/docs/reference/api/

If the Graph API returns false

In some cases — for instance, if the user has opted out of the Facebook Platform entirely — your Graph API calls may return false instead of the expected object. It’s rare, but it does happen — something to keep in mind as you develop. See http://forum.developers.facebook.net/viewtopic.php?id=61050.

Clone this wiki locally