Graph API, Making Batch Requests

Batching allows you to pass instructions for several operations in a single HTTP request. You can also specify dependencies between related operations (described in a section below). Facebook will process each of your independent operations in parallel and will process your dependent operations sequentially. Once all operations have been completed, a consolidated response will be passed back to you and the HTTP connection will be closed.

Simple batched requests

The batch API takes in an array of logical HTTP requests represented as JSON arrays - each request has a method (corresponding to HTTP method GET/PUT/POST/DELETE etc.), a relative_url (the portion of the URL after graph.facebook.com), optional headers array (corresponding to HTTP headers) and an optional body (for POST and PUT requests). The Batch API returns an array of logical HTTP responses represented as JSON arrays - each response has a status code, an optional headers array and an optional body (which is a JSON encoded string).

To make batched requests, you build a JSON object which describes each individual operation you'd like to perform and POST this to the Graph API endpoint at https://graph.facebook.com. The following example gets the current user's profile information and the first 50 friends from their friends list in a single request:

curl \
    -F ‘access_token=…’ \
    -F ‘batch=[{“method”:”GET”, “relative_url”:”me”},{“method”:”GET”, “relative_url”:”me/friends?limit=50”}]’ \
    https://graph.facebook.com

Once both operations have been completed, Facebook sends a response which encapsulates the result of all the operations. For each operation, the response includes a status code, header information, and the body. These are equivalent to the response you could expect from each operation if performed as raw requests against the Graph API. The body field contains a string encoded JSON object:

For the above request, the expected response would be of the form:

[
    { “code”: 200, 
      “headers”:[
          { “name”: ”Content-Type”, 
            “value”: ”text/javascript; charset=UTF-8” }
      ],
      “body”: ”{\”id\”:\”…\”}”},
    { “code”: 200,
      “headers”:[
          { “name”:”Content-Type”, 
            “value”:”text/javascript; charset=UTF-8”}
      ],
      “body”:”{\”data\”: [{…}]}}
]

Removing headers from the response

Because the headers returned can sometimes be much larger than the actual API response, you might want to remove them for efficiency. The API modifier include_headers can be set to false in order to remove the headers from this response.

Batch requests containing multiple methods

It is possible to combine operations that would normally use different HTTP methods into a single batch request. While GET and DELETE operations must only have a relative_url and a method field, POST and PUT operations may contain an optional body field. This should be formatted as a raw HTTP POST body string, similar to a URL query string. The following example writes a new post to the user's news feed, and then gets the top item from their news feed in a single operation:

curl \
    -F ‘access_token=…’ \
    -F ‘batch=[{ “method”:”POST”,“relative_url”:”me/feed”,“body”:”message=Test status update&link=http://developers.facebook.com/”},{ “method”:”GET”,“relative_url”:”me/feed?limit=1”}]’ \
    https://graph.facebook.com

The output of this call would be:

[
    { “code”: 200,
      “headers”: [
          { “name”:”Content-Type”, 
            “value”:”text/javascript; charset=UTF-8”}
       ],
      “body”:”{\”id\”:\”…\”}”
    },
    { “code”: 200,
      “headers”: [
          { “name”:”Content-Type”, 
            “value”:”text/javascript; charset=UTF-8”
          },
          { “name”:”ETag”, 
            “value”: ”…”
          }
      ],
      “body”: ”{\”data\”: [{…}]}
    }
]

The following example creates a new ad for a campaign, and then gets the details of the newly created object. Note the URLEncoding for the body param:

curl \
-F 'access_token=...' \
-F 'batch=[
  {
    "method":"POST",
    "name":"create-ad",
    "relative_url":"11077200629332/ads",
    "body":"ads=%5B%7B%22name%22%3A%22test_ad%22%2C%22billing_entity_id%22%3A111200774273%7D%5D"
  }, 
  {
    "method":"GET",
    "relative_url":"?ids={result=create-ad:$.data.*.id}"
  }
]' \
https://graph.facebook.com

Note: If you would like to scrape an object for multiple languages, you should use a single POST to do this. See localization guide.

Errors

Its possible that one of your requested operations may throw an error. This could be because, for example, you don't have permission to perform the requested operation. In this scenario, the batch API throws a similar response to the standard Graph API, but encapsulated in the batch response syntax:

curl \
     -F 'access_token=...'\
     -F 'batch=[{ "method":"POST","relative_url”:"me/feed","body":"message=Test update"}]' \
https://graph.facebook.com

Let say, for example, that the access token used above didn't have the publish_actions permission. The response would be of the form:

[
    { “code”: 403,
      “headers”: [
          {“name”:”WWW-Authenticate”, “value”:”OAuth…”},
          {“name”:”Content-Type”, “value”:”text/javascript; charset=UTF-8”} ],
      “body”: “{\”error\”:{\”type\”:\”OAuthException\”, … }}”
    }
]

Other requests within the batch should still complete successfully and will be returned, as normal, with a 200 status code.

Timeouts

Large or complex batches may timeout if it takes too long to complete all the requests within the batch. In such a circumstance, the result is a partially-completed batch. In partially-completed batches, responses from operations that complete successfully will look normal (see prior examples) whereas responses for operations that are not completed will be null.

The ordering of responses correspond with the ordering of operations in the request, so developers should process responses accordingly to determine which operations were successful and which should be retried in a subsequent operation.

[
    { “code”: 200,
      “headers”: [
          { “name”:”Content-Type”, 
            “value”:”text/javascript; charset=UTF-8”}
       ],
      “body”:”{\”id\”:\”…\”}”
    },
    null,null,null
]

In this example response, the first operation was successful but the rest of them were not. The developer should retry operations two, three and four.

Specifying dependencies between operations in the request

By default, the operations specified in the batch API request are independent - they can be executed in arbitrary order on the server and an error in one operation does not affect execution of other operations.

Often, the operations in the request are dependent - for example, the output of one operation may be used in the input of the next operation. The graph Batch API has support for this using the JSONPath expression format (http://code.google.com/p/jsonpath/). The JSONPath expression format provides a simple way to reference the data in a JSON object. In order to reference the results of a previous operation in another operation, you need to give a name to the previous (parent) operation, and then reference it inside the query string parameter or form post parameter using the JSONPath format. The syntax for embedding a JSONPath expression in a query string or form post parameter is {result=(parent operation name):(JSONPath expression)}. Note that for security reasons filter and script JSONPath constructs are not allowed in the JSONPath expression.

For example, to get the details of 5 of your friends, you can issue the following Batch request:

curl \
   -F 'access_token=...' \
   -F 'batch=[{ "method":"GET","name":"get-friends","relative_url":"me/friends?limit=5",},{"method":"GET","relative_url":"?ids={result=get-friends:$.data.*.id}"}]' \
   https://graph.facebook.com/

In the above example, the first operation is named get-friends, and the second operation uses the JSONPath syntax to extract all the friend ids from the output of the first operation in csv format. The JSONPath expression $.data.*.id implies "extract the id attribute from all children of the top level element called data". Note that the output of a JSONPath expression must be a primitive or a list of primitives - the list of primitives gets exploded as a csv string.

In the above example, the server detects that the second operation depends on the first one, since the second operation references the result of the first one using JSONPath. The server executes a dependent operation only after the operation it depends on has finished executing. If the parent operation execution results in an error, then the subsequent operation is not executed. Also, by default the output of the parent operation is not included in the response if the operation executed successfully. So, the response to the above Batch API request would look like

[
    null,
    { “code”: 200,
      “headers”:[
          { “name”:”Content-Type”, 
            “value”:”text/javascript; charset=UTF-8”}
      ],
      “body”:”{\”data\”: [{…}]}}
]

You can force the server to include the output for the parent operation even if it executed successfully by specifying "omit_response_on_success":false in the parent request operation. For example

curl \
     -F 'access_token=...' \
     -F 'batch=[{ "method":"GET","name":"get-friends", "relative_url":"me/friends?limit=5", "omit_response_on_success":false,}, { "method":"GET", "relative_url":"?ids={result=get-friends:$.data.*.id}"}]' \
     https://graph.facebook.com/

You can reference the results of a previous operation using JSONPath in form post parameters in addition to query string parameters. For example, the batch request below adds a status update that references a friend's name:

curl \
     -F 'access_token=...'  \
     -F 'batch=[{ "method":"GET","name":"one-friend","relative_url":"me/friends?limit=1",},{ "method":"POST", "relative_url":"me/feed", "body":"message={result=one-friend:$.data.0.name} is my friend"}]' \
     https://graph.facebook.com/

As mentioned above, the server automatically detects dependencies between operations based on the JSONPath expressions. However in some instances, the client may wish to specify dependencies between operations explicitly. This can be done using the depends_on attribute.

For example, in the request below, the fact that the second operation depends on the first one has been specified explicitly.

curl \
    -F 'access_token=...' \
    -F 'batch=[{ "method":"POST", "name":"first", "relative_url":"me/feed", "body":"message=Test status update"},{"method":"GET","depends_on":"first", "relative_url":"me/feed?limit=1"}]' \
    https://graph.facebook.com

Batch calls with JSONP

The Batch API supports JSONP, just like the rest of the Graph API - the JSONP callback function is specified using the callback query string or form post parameter.

Specifying different access tokens for different operations

All the above examples specify a single access token as a top level parameter. The Batch API is flexible and allows individual requests to specify their own access tokens as a query string or form post parameter. In that case the top level access token is considered a fallback token and is used if an individual request has not explicitly specified an access token.

This may be useful when you want to query the API using several users' different access tokens, or if some of your calls need to be made using an app access token.

You must include an access token as a top level parameter, even when all individual requests contain their own tokens.

Uploading binary data

Binary data can be specified as part of the multipart/mime portion of the batch API request. The batch Graph API allows uploading multiple binary items as part of a batch call. In order to do this, you need to add all the binary items as multipart/mime attachments to your request, and need each operation to reference its binary items using the attached_files property in the operation. The attached_files property can take a comma separated list of attachment names in its value.

The following example shows how to upload 2 photos in a single batch call:

curl 
     -F 'access_token=…' \
     -F 'batch=[{“method”:”POST”,“relative_url”:”me/photos”,“body”:”message=My cat photo”,"attached_files":"file1"},{“method”:”POST”,“relative_url”:”me/photos”,“body”:”message=My dog photo”,"attached_files":"file2"},]' \
     -F 'file1=@cat.gif' \
     -F 'file2=@dog.jpg' \
    https://graph.facebook.com

Using the Facebook SDK for PHP

You can make batch requests using the Facebook SDK for PHP. An example request may look like this:

try {
  $params = [
    [
      "method"  => "GET",
      "relative_url"  => "me"
    ],
    [
      "method"  => "GET",
      "relative_url"  => "me/picture?type=large&redirect=false"
    ] 
  ];
  $response = (new FacebookRequest($session, 'POST',
    '?batch='.urlencode(json_encode($params))))->execute();
  $objects = $response->getGraphObject();
} catch(FacebookRequestException $e) {
  // error handling
}   

Do not forget to urlencode your parameters, otherwise your API request might fail.

Limits

We currently limit the number of requests which can be in a batch to 50, but each call within the batch is counted separately for the purposes of calculating API call limits and resource limits. For example, a batch of 10 API calls will count as 10 calls and each call within the batch contributes to CPU resource limits in the same manner.