Receiving API Updates in Real Time with Webhooks

The Graph API has a feature called Webhooks (formerly known as Real Time Updates) that enables apps to subscribe to changes in certain pieces of data and receive updates in real time. When a change occurs, an HTTP POST request will be sent to a callback URL belonging to that app. This makes apps more efficient, as they know exactly when a change has happened, and don't need to rely on continuous or even periodic Graph API requests when changes aren't happening.

Webhooks are lightweight - they only indicate that a particular field has changed, they do not include the new value of those fields. Also, updates are not sent for actions made by people who have disabled platform on their App Settings.

Creating and Updating Webhooks Subscriptions

There are two ways to create and update Webhooks subscriptions for your apps. You can interact with a list of your app's current Webhooks subscriptions on your app's settings page or the Webhooks section. To create a new subscription, you will need to supply a valid URL callback endpoint and a verification token. You can then select the fields for which you want to receive updates.

Additionally, webhooks subscriptions to payments objects can be managed directly on your app's Canvas Payments settings tab:

Webhooks subscriptions can also be created and modified via the /{app-id}/subscriptions Graph API edge. You can read the Graph API reference for this endpoint to see how it is used, but the basic operations are:

  • Add or modify a subscription.
  • List each of your existing subscriptions.
  • Delete subscriptions.

Valid Fields for Subscription

In addition to the subscriptions available for Payments developers there are subscriptions available on user, permissions and page Graph API objects. Some of these objects may require your app to be whitelisted by Facebook for access. page-related RTU objects will require that your app be installed on the page.

Page object subscriptions

  • affiliation
  • artists_we_like
  • attire
  • awards
  • band_interests
  • band_members
  • bio
  • birthday
  • booking_agent
  • built
  • category
  • checkins
  • company_overview
  • conversations
  • culinary_team
  • current_location
  • description
  • directed_by
  • email
  • features
  • feed
  • founded
  • general_info
  • general_manager
  • genre
  • hometown
  • hours
  • influences
  • leadgen
  • live_videos
  • location
  • members
  • mission
  • mpg
  • name
  • network
  • parking
  • payment_options
  • personal_info
  • personal_interests
  • phone
  • picture
  • plot_outline
  • press_contact
  • price_range
  • produced_by
  • productlists
  • products
  • public_transit
  • ratings
  • record_label
  • release_date
  • restaurant_services
  • restaurant_specialties
  • schedule
  • screenplay_by
  • season
  • starring
  • studio
  • videos
  • website

User object subscriptions

  • about
  • about_me
  • activities
  • affiliations
  • allowed_restrictions
  • birthday
  • birthday_date
  • books
  • checkin_deal_claims
  • contact_email
  • current_location
  • education
  • education_history
  • email
  • email_hashes
  • events
  • family
  • feed
  • first_name
  • friend_request
  • has_added_app
  • hometown
  • hometown_location
  • hs_info
  • interests
  • is_app_user
  • is_blocked
  • last_name
  • likes
  • link
  • live_videos
  • locale
  • location
  • meeting_for
  • meeting_sex
  • movies
  • music
  • name
  • notes_count
  • photos
  • pic
  • picture
  • pic_https
  • pic_with_logo
  • pic_big
  • pic_big_https
  • pic_big_with_logo
  • pic_small
  • pic_small_https
  • pic_small_with_logo
  • pic_square
  • pic_square_https
  • pic_square_with_logo
  • political_views
  • profile_blurb
  • profile_update_time
  • profile_url
  • proxied_email
  • quotes
  • relationship_status
  • religion
  • gender
  • sex
  • significant_other_id
  • statuses
  • timezone
  • television
  • tv
  • verified
  • videos
  • website
  • work
  • work_history
  • friends
  • platform
  • privacy
  • blocked
  • ip_optout
  • notifications
  • threads

Payments object subscriptions

  • actions
  • disputes

Permissions object

Setting Up your Callback URL

First you'll need to prepare the page that will act as your callback URL. This URL will need to be accessible by Facebook servers, and be able to receive both the POST data that is sent when an update happens, but also accept GET requests in order to verify subscriptions.

New Webhook subscriptions must use a secure HTTPS callback URL as of v2.5. With the next version of the Graph API we will stop sending updates to non-HTTPS callback URLs.

If you need more information about setting up HTTPS for your callback URL, check out the Getting Started guide from Let's Encrypt and the SSL Certificate Installation instructions from Digicert.

This URL should always return a 200 OK HTTP response when invoked by Facebook.

Handling Verification Requests

When you add a new subscription, or modify an existing one, Facebook servers will make a GET request to your callback URL in order to verify the validity of the callback server. A query string will be appended to this URL with the following parameters:

  • hub.mode - The string "subscribe" is passed in this parameter
  • hub.challenge - A random string
  • hub.verify_token - The verify_token value you specified when you created the subscription

When your server receives one of these requests, it needs to:

  • Verify the hub.verify_token matches the one you supplied when creating the subscription. This is a security check so that your server knows the request is being made by Facebook and relates to the subscription you just configured. This value is only passed on the initial API call to APP_ID/subscriptions.
  • Render a response to the GET request that includes only the hub.challenge value. This confirms that this server is configured to accept callbacks, and is used for security verification on Facebook's side.

Note that PHP will convert . in the parameter names to _.

Receiving Updates

Once a subscription is successfully created, Facebook will make an HTTP POST request to your callback URL every time that there are changes (to the chosen fields or edges).

The request will have content type of application/json and the body will contain the following fields:

Name Description Type

object

Indicates the object type that this update applies to.

enum{user, page, permissions, payments}

entry

The list of changes. Multiple changes from different objects that are of the same type are batched together.

object[]

entry.id

The ID of the object that has changed.

string

entry.changed_fields

An array of the fields which have changed to trigger this update.

string[]

entry.changes

An array of the actual changes which triggered this update. This is only returned for page subscriptions, in place of changed_fields.

object[]

entry.time

When the update was sent.

timestamp

The HTTP request will contain an X-Hub-Signature header which contains the SHA1 signature of the request payload, using the app secret as the key, and prefixed with sha1=. Your callback endpoint can verify this signature to validate the integrity and origin of the payload

Please note that the calculation is made on the escaped unicode version of the payload, with lower case hex digits. If you just calculate against the decoded bytes, you will end up with a different signature. For example, the string äöå should be escaped to \u00e4\u00f6\u00e5.

Changes are aggregated and sent in batch at most once every 5 seconds, or when the number of unsent changes exceeds 1000. Your server should be able to handle this level of load.

Real Time Updates for Payments are not batched. You will get a new update every single time someone makes a transaction, files a dispute or when a transaction is updated.

If any update sent to your server fails, Facebook will retry again immediately, and then a few more times with decreasing frequency over the next 24 hours. Updates that your server fails to accept after 24 hours will be dropped. Your server should handle deduplication of updates that may result from multiple attempts.

Sample Clients

A few sample clients are available on GitHub.

Actions and Result Sets

Actions that trigger updates for your subscriptions vary by the node you subscribe to. Result sets returned as part of a webhook update also vary in JSON structure - fields returned depend on the node you subscribe to. We recommend the following approach when you set up a webhook subscription:

  • Set up a webhook subscription for an endpoint
  • Perform an action to trigger the subscription
  • Examine the result object returned for your subscription

Fields and result structure webhooks are subject to change. Please follow the approach above during testing and development before you use a subscription in production.

Whitelisting Facebook Server IPs

If your server is behind a firewall, you may need to whitelist Facebook server IPs to ensure we can send updates to your callback URLs.

Run this command to get a current list of Facebook server IP addresses:

whois -h whois.radb.net -- '-i origin AS32934' | grep ^route  

It will return a list of IP addresses that change often:

# For example only - over 100 in total
31.13.24.0/21 
66.220.144.0/20    
2401:db00::/32  
2620:0:1c00::/40  
2a03:2880::/32