Server-to-Server Events API

  • Developers


The purpose of this API is to allow you to send events which occur outside the mobile app, directly to the AppsFlyer server.  For example, if you have both a web and mobile interface, you can record all events from both mediums in AppsFlyer. 


The Content Type must be set as application/json.


Android example:

iOS example

It is important to pay extra attention that the App ID on iOS contains the leading "id" before the ID, otherwise the request ends with HTTPS 200 OK, but the event is not registered.


The maximum size of the JSON payload should not exceed 1K.

The JSON payload must be passed as a string and the event value must be stringified.

Make sure that the JSON payload includes the parameter "af_events_api" :"true"
This parameter ensures that the event is structured as a rich event to enable automatic mapping of the event values to various partners.

See examples below.

Method: POST

Header - "authentication"= {dev-key}

The dev key is found in Dashboard >> App Settings >> Dev Key

iOS Android
    "appsflyer_id": {This is a mandatory field, AppsFlyer Device ID must be used },  // e.g. 1415211453000-6513894
    "customer_user_id": {customer_user_id}, // Customer User ID optional parameter
    "eventName": {The event name}, // e.g. "af_purchase"
    "eventValue": {A JSON containing a rich in-app event value - must be stringfied},


    "eventCurrency": {Event currency}, // e.g "USD"
    "ip": {device IP},
    "eventTime": {Event timestamp in UTC}, // e.g  "2014-05-15 12:17:00.000"
    "af_events_api" :"true"


All Reserved Character ( must be percent-encoded before the URI is formed.


  1. Mandatory parametersappsflyer_id (AppsFlyer Device id), eventName, eventValue and af_events_api
  2. Highly recommended parameters: idfa for iOS and advertising_id for Android.
    If you wish to map your in-app events from organic users with external partners, these parameters are MANDATORY. 
  3. Optional - eventValue can be with an empty value, i.e., "eventValue":"", (no space is needed)
  4. Optional - IP address (ip) should be the IP of the mobile device (during the event occurrence)
  5. Optional - The customer user ID field (customer_user_id) is a user identifier parameter, mapped to the Customer User ID field in the Raw Reports. The Customer User ID SDK API attaches this value automatically to all SDK originated in-app events. Make sure to include this field will ALL your S2S events to enjoy the same functionality.

Timing the Events

Server-to-server events can be sent in real time or in batch mode


Batch mode does not mean sending the joined payload of all events in a single request. What batch mode means is that different S2S requests are sent in bulk. Each request should have its own payload.

If you send more than one event in the JSON payload, the server returns error code 400 with the error message "Payload is missing or failed to parse".

You can use the optional eventTime parameter to specify the time of the event occurrence (in UTC timezone). If the parameter is not included in the message, AppsFlyer uses the timestamp from the HTTPS message received. 

eventTime format is: "yyyy-MM-dd HH:mm:ss.SSS" (e.g. "2014-05-15 12:17:00.000")  

In batch mode, for events to be recorded with their real-time stamps, they must all be sent to AppsFlyer by 02:00 AM (UTC) of the following day.   


The maximum number of S2S requests is 60K per minute or 1K per second. Contact your Customer Success Manager if your requirements are different.

Events with past timestamps, which are not sent by 2:00 AM, are recorded under the time that they were sent.

Example 1

Event Triggered: 2 May @ 22:00

Event Sent to AppsFlyer's servers: 3 May @ 01:00

Event is recorded in AppsFlyer's platform under the real time that the event occurred (2 May @ 22:00).

Example 2
Event Triggered: 2 May @ 22:00

Event Sent to AppsFlyer's servers: 4 May @ 09:00

Event is recorded in AppsFlyer's platform at the time it was sent to the AppsFlyer server and not the time that the event occurred (4 May @ 09:00).

Service Return Codes

OK when the request has been processed by the AppsFlyer system.
unauthorized when the key provided in the authentication header is not the dev-key for this app.
Bad request when the request failed at least one of the validation criteria
Internal server error this indicates a server error

If your servers are protected by a firewall you will need to white list the incoming responses from AWS IP address Ranges to receive the return messages.

Request Body Example

    "appsflyer_id": "1415211453000-6513894",
	"advertising_id": "38412345-8cf0-aa78-b23e-10b96e40000d",
	"eventName": "af_purchase",
		\"af_revenue\": \"6\",
		\"af_content_type\": \"wallets\",
		\"af_content_id\": \"15854\",
		\"af_quantity\" :\"1\"
	"eventCurrency": "USD",
	"ip": "",
	"eventTime": "2014-05-15 12:17:00.000",
	"af_events_api" :"true"

In this case, AppsFlyer receives an S2S in-app event which represents a purchase event with revenue, as well as additional properties such as content type etc.

Special Cases

Sending Negative Revenue

If you want to send an event with negative revenue (for events such as cancelled purchase or refund), you can specify negative value in the revenue parameter. For example:

    "appsflyer_id": "1415211453000-6513894",
	"advertising_id": "38412345-8cf0-aa78-b23e-10b96e40000d",
	"eventName": "cancel_purchase",
		\"af_revenue\": \"-6\",
		\"af_content_type\": \"wallets\",
		\"af_content_id\": \"15854\",
		\"af_quantity\" :\"1\"
	"eventCurrency": "USD",
	"ip": "",
	"eventTime": "2014-05-15 12:17:00.000",
	"af_events_api" :"true"

Sending Events Without Event Value

If you want to send events without event value, simply pass an empty string to event value: "event_value":""

AppsFlyer is then able, according to the advertiser's configuration, to send such rich in-app events to media sources for advanced targeting, optimisation and audience creation purposes.

Fetching the AppsFlyer Device ID

appsflyer_id is a mandatory parameter in server-to-server event messages. AppsFlyer uses this parameter to attribute the event to the original device and to the attributed media source. 

There are several ways of obtaining this ID.

  1. From the mobile device using AppsFlyer's SDK API (Android / iOS)
  2. Via the Pull or Push API (click on link for more information about Push API or Pull API)
  3. Export the raw data installation report


When testing S2S messages, if you're using raw data or push or pull APIs, look for the record with media source "s2s_test". This is your test device and its AppsFlyer Device ID is the ID you need.

Difference Between Organic and Non-Organic

When you send S2S in-app events, AppsFlyer automatically associates additional data with the events. The additional data comes from the install event that precedes the in-app events. 

What this means is that some data that AppsFlyer associates with non-organic S2S in-app events, is not associated with organic S2S in-app events.


For example, if you compare raw data reports of non-organic and organic S2S in-app events, non-organic events contain data that organic in-app events do not.

Non-organic in-app events contain data about the media source, campaign, attributed touch type and attributed touch time.

Organic in-app events, on the other hand, follow an organic install. Organic install do not have data related to campaign, media sources or attributed touch type and time. 

Was this article helpful?
4 out of 10 found this helpful