Using the Server-Side API

Before implementing the API, make sure you have all the prerequisites listed on the main Server-Side API document. In this page, you learn to:

The Server-side API is based on Facebook's Marketing API, which was built on top of our Graph API. Marketing and Graph APIs have different version deprecation schedules. Our release cycle is aligned with the Graph API, so every version is supported for at least two years. This exception is only valid for Server-side.

Server-Side API: DocumentationParameters

Send requests

To send new events, make a POST request to this API's /events edge from this path: https://graph.facebook.com/{API_VERSION}/{PIXEL_ID}/events?access_token={TOKEN}. When you post to this edge, Facebook creates new server events.

curl -X POST \ -F 'data=[ { "event_name": "PageView", "event_time": 1593986342, "user_data": { "fbc": "fb.1.1554763741205.AbCdEfGhIjKlMnOpQrStUvWxYz1234567890", "fbp": "fb.1.1558571054389.1098115397", "em": "309a0a5c3e211326ae75ca18196d301a9bdbd1a882a4d2569511033da23f0abd" } } ]' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/v7.0/<PIXEL_ID>/events
'use strict'; const bizSdk = require('facebook-nodejs-business-sdk'); const ServerEvent = bizSdk.ServerEvent; const EventRequest = bizSdk.EventRequest; const UserData = bizSdk.UserData; const CustomData = bizSdk.CustomData; const Content = bizSdk.Content; const access_token = '<ACCESS_TOKEN>'; const pixel_id = '<ADS_PIXEL_ID>'; const api = bizSdk.FacebookAdsApi.init(access_token); let current_timestamp = Math.floor(new Date() / 1000); const userData = (new UserData()) .setEmail('joe@eg.com') .setFbp('fb.1.1558571054389.1098115397') .setFbc('fb.1.1554763741205.AbCdEfGhIjKlMnOpQrStUvWxYz1234567890'); const customData = (new CustomData()) .setCurrency('usd') .setValue(123.45); const serverEvent = (new ServerEvent()) .setEventName('Purchase') .setEventTime(current_timestamp) .setUserData(userData) .setCustomData(customData); const eventsData = [serverEvent]; const eventRequest = (new EventRequest(access_token, pixel_id)) .setEvents(eventsData); eventRequest.execute();
require __DIR__ . '/vendor/autoload.php'; use FacebookAds\Api; use FacebookAds\Logger\CurlLogger; use FacebookAds\Object\ServerSide\Event; use FacebookAds\Object\ServerSide\EventRequest; use FacebookAds\Object\ServerSide\UserData; use FacebookAds\Object\ServerSide\CustomData; $access_token = '<ACCESS_TOKEN>'; $pixel_id = '<ADS_PIXEL_ID>'; $api = Api::init(null, null, $access_token); $api->setLogger(new CurlLogger()); $user_data = (new UserData()) ->setFbc('fb.1.1554763741205.AbCdEfGhIjKlMnOpQrStUvWxYz1234567890') // It is recommended to send Client IP and User Agent for ServerSide API Events. ->setClientIpAddress($_SERVER['REMOTE_ADDR']) ->setClientUserAgent($_SERVER['HTTP_USER_AGENT']) ->setFbp('fb.1.1558571054389.1098115397') ->setEmail('joe@eg.com'); $custom_data = (new CustomData()) ->setCurrency('usd') ->setValue(123.45); $event = (new Event()) ->setEventName('Purchase') ->setEventTime(time()) ->setEventSourceUrl('http://jaspers-market.com/product/123') ->setUserData($user_data) ->setCustomData($custom_data); $events = array(); array_push($events, $event); $request = (new EventRequest($pixel_id)) ->setEvents($events); $response = $request->execute(); print_r($response);
import time from facebook_business.adobjects.serverside.event import Event from facebook_business.adobjects.serverside.event_request import EventRequest from facebook_business.adobjects.serverside.user_data import UserData from facebook_business.adobjects.serverside.custom_data import CustomData from facebook_business.api import FacebookAdsApi access_token = '<ACCESS_TOKEN>' pixel_id = 'ADS_PIXEL_ID>' FacebookAdsApi.init(access_token=access_token) user_data = UserData( email='joe@eg.com', fbc='fb.1.1554763741205.AbCdEfGhIjKlMnOpQrStUvWxYz1234567890', fbp='fb.1.1558571054389.1098115397' ) custom_data = CustomData( currency='usd', value=123.45 ) event = Event( event_name='Purchase', event_time=int(time.time()), user_data=user_data, custom_data=custom_data, ) events = [event] event_request = EventRequest( events=events, pixel_id=pixel_id) event_response = event_request.execute() print(event_response)
import com.facebook.ads.sdk.APIContext; import com.facebook.ads.sdk.APIException; import com.facebook.ads.sdk.serverside.Event; import com.facebook.ads.sdk.serverside.EventRequest; import com.facebook.ads.sdk.serverside.EventResponse; import com.facebook.ads.sdk.serverside.UserData; import com.facebook.ads.sdk.serverside.CustomData; public class ServerSideApiExample { public static final String ACCESS_TOKEN = "<ACCESS_TOKEN>"; public static final String PIXEL_ID = "<ADS_PIXEL_ID>"; public static void main(String[] args) { APIContext context = new APIContext(ACCESS_TOKEN).enableDebug(true); context.setLogger(System.out); UserData userData = new UserData() .fbc("fb.1.1554763741205.AbCdEfGhIjKlMnOpQrStUvWxYz1234567890") .fbp("fb.1.1558571054389.1098115397") .email("joe@eg.com"); CustomData customData = new CustomData() .currency("usd") .value(123.45F); Event pageViewEvent = new Event(); pageViewEvent.eventName("Purchase") .eventTime(System.currentTimeMillis() / 1000L) .userData(userData) .customData(customData); EventRequest eventRequest = new EventRequest(PIXEL_ID, context); eventRequest.addDataItem(pageViewEvent); try { EventResponse response = eventRequest.execute(); System.out.println(String.format("Standard API response : %s ", response)); } catch (APIException e) { e.printStackTrace(); } } }
require 'facebook_ads' access_token = '<ACCESS_TOKEN>' pixel_id = '<ADS_PIXEL_ID>' FacebookAds.configure do |config| config.access_token = access_token end user_data = FacebookAds::ServerSide::UserData.new( email: 'joe@eg.com', fbc: 'fb.1.1554763741205.AbCdEfGhIjKlMnOpQrStUvWxYz1234567890', fbp: 'fb.1.1558571054389.1098115397') custom_data = FacebookAds::ServerSide::CustomData.new( currency: 'usd', value: 123.45) event = FacebookAds::ServerSide::Event.new( event_name: 'Purchase', event_time: Time.now.to_i, user_data: user_data, custom_data: custom_data) request = FacebookAds::ServerSide::EventRequest.new( pixel_id: pixel_id, events: [event]) print request.execute

Attach your generated secure access token using the access_token query parameter to the request.

You can also use Graph API Explorer to POST to the endpoint:

An example request body looks like this:

{ "data": [ { "event_name": "Purchase", "event_time": 1593985742, "event_id": "event.id.123", "event_source_url": "http:\/\/jaspers-market.com\/product\/123", "user_data": { "client_ip_address": "192.19.9.9", "client_user_agent": "test ua", "em": "309a0a5c3e211326ae75ca18196d301a9bdbd1a882a4d2569511033da23f0abd", "fbc": "fb.1.1554763741205.AbCdEfGhIjKlMnOpQrStUvWxYz1234567890", "fbp": "fb.1.1558571054389.1098115397" }, "custom_data": { "value": 100.2, "currency": "USD", "content_ids": [ "product.id.123" ], "content_type": "product" }, "opt_out": false }, { "event_name": "Purchase", "event_time": 1593985742, "user_data": { "client_ip_address": "192.88.9.9", "client_user_agent": "test ua2" }, "custom_data": { "value": 50.5, "currency": "USD" }, "opt_out": true } ] }

Swagger

You can use open source code-generator Swagger to generate client side API code for our server-side API. The generated code handles the API calls, exception handling, and retries.

To use Swagger, you need Java (version 7 or higher). Learn more about our Swagger API integration.

Dropped Events

Network errors or malformed requests may cause events to be dropped.

Upload Time versus Event Transaction Time

event_time is the event transaction time. It should be sent as a Unix timestamp in seconds indicating when the actual event occurred. The specified time may be earlier than the time you send the event to Facebook. This is to enable batch processing and server performance optimization.

event_time can be up to 7 days before you send an event to Facebook. If any event_time in data is greater than 7 days in the past, we return an error for the entire request and process no events.

Batch Requests

You can send up to 1,000 events in data. However, for optimal performance, we recommend you send events as soon as they occur and ideally within an hour of the event occurring. If any event you send in a batch is invalid, we reject the entire batch.

Hashing

Please check our User Data parameters page to see which parameters should be hashed before they are sent to Facebook. If you are using one of our Business SDKs, the hashing is done for you by the SDK.

Server-Side Parameters

Verify Events

After you send your events, confirm that we have received them in the overview and breakdown views:

  • Go to Business Manager > Pixels.
  • Click on the pixel corresponding to the PIXEL_ID in your POST request.

Overview

  • Change the View tab from All to Server. You see the number of events you have successfully sent.

Breakdown

  • Change the higher level Overview tab from Overview to Breakdown. You see the breakdown of the events that you have successfully sent.
  • Dropped events will not show up in the "Server Events Received" column.

After you start sending events, you should be able to verify them within 20 minutes. Now you can start sending events from your server.

Test Events Tool

You can verify that your server events are received correctly by Facebook by using the Test Events feature in Events Manager. To find the tool, go to Events Manager > Data Sources > Your Pixel > Test Events > Server.

The Test Events tool will generate a test ID. Send the test ID as a test_event_code parameter to start seeing event activity appear in the Test Events window. Events sent with test_event_code are not dropped.

Here's an example of how the request should be structured:

{ "data": [ { "event_name": "ViewContent", "event_time": 1593985742, "event_id": "event.id.123", "event_source_url": "http:\/\/jaspers-market.com", "user_data": { "client_ip_address": "1.2.3.4", "client_user_agent": "test user agent" } } ], "test_event_code": "TEST123" }

Here's an example of how the request will appear in Graph API Explorer.

Your server events will appear in the Test Events window once the request is sent.

Data Processing Options For Server-Side API and Offline Conversions API

For these two APIs, implement data processing options by adding data_processing_options, data_processing_options_country, and data_processing_options_state inside each event within the data parameter of your events.

To explicitly not enable Limited Data Use (LDU) mode, specify an empty array for each event:
{
    "data": [
        {
            "event_name": "Purchase",
            "event_time": <EVENT_TIME>,
            "user_data": {
                "em": "<EMAIL>"
            },
            "custom_data": {
                "currency": "<CURRENCY>",
                "value": "<VALUE>"
            },
            "data_processing_options": []
        }
    ]
}
To enable LDU and specify user geography:
{
    "data": [
        {
            "event_name": "Purchase",
            "event_time": <EVENT_TIME>,
            "user_data": {
                "em": "<EMAIL>"
            },
            "custom_data": {
                "currency": "<CURRENCY>",
                "value": "<VALUE>"
            },
            "data_processing_options": ["LDU"],
            "data_processing_options_country": 1,
            "data_processing_options_state": 1000
        }
    ]
}
To enable LDU with geolocation (this works for Server-side API provided client IP address is provided):
{
    "data": [
        {
            "event_name": "Purchase",
            "event_time": <EVENT_TIME>,
            "user_data": {
                "em": "<EMAIL>",
                "client_ip_address": "256.256.256.256"
            },
            "custom_data": {
                "currency": "<CURRENCY>",
                "value": "<VALUE>"
            },
            "data_processing_options": ["LDU"],
            "data_processing_options_country": 0,
            "data_processing_options_state": 0
        }
    ]
}

Manual Upload UI

The Offline Conversions API offers the option to manually upload your events from a .csv file. In this case, add Data Processing Options, Data Processing Country, and Data Processing State as columns inside your file. More information about this can be found in the upload user interface.

Offline Conversions Automated Uploader


Learn more about Data Processing Options.

API Limits

The Marketing API has its own rate-limiting logic and is excluded from all the Graph API rate limitations. So if you make a Marketing API call, it won't be calculated into the Graph API throttling.

There is no specific rate limit for Server-Side API. Server-Side calls are counted as Marketing API calls. The only limitation is that you can send us up to 1,000 events at a time. See Send Requests for more information.

Marketing API Rate Limiting