Server-to-server events API

  • Developers

The Server-to-Server events API enables sending events that are not sent using the AppsFlyer SDK. For example, if you have both a web and mobile interface, you can record events from both mediums in AppsFlyer using the Server-to-Server events API. 

Server-to-Server events need to be prepared as follows:

See the examples below.

Method: POST

Header - "authentication"= {dev-key}

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

  "appsflyer_id": {AppsFlyer Device ID }, // 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 +0}, // 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.


  • Mandatory parameters: appsflyer_id (AppsFlyer Device id), eventName, eventValue and af_events_api
  • 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.
  • (Optional) EventValue can be with an empty value, i.e., "eventValue":"", (no space is needed)
  • (Optional)  IP address (ip) should be the IP of the mobile device (during the event occurrence)
  • (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.

Preparing data for parameters

Backend logic is required in order to obtain certain values for the parameters mentioned above. Below you can find the recommended flow for obtaining these values:

Mapping AppsFlyer ID with customer user ID

AppsFlyer ID is a mandatory parameter when sending server to server in-app events. To make it easier for you to know which user performed which event, implement the flow below:

  1. Set customer user ID when the user installs the app
  2. Download raw data report for installs through export data or pull API
  3. Get AppsFlyer ID by matching the customer user ID in your internal systems with the customer user ID in the raw data report.
    Note: you can get the AppsFlyer ID of your users from the AppsFlyer SDK integrated in your apps (Android / iOS)
  4. Map AppsFlyer ID to customer user ID in your internal (important for future use)

Once you map AppsFlyer ID with your internal customer user ID, you can easily know which user performed which event. You can then obtain the AppsFlyer ID and other values (event value, event currency, event time etc.) and send the server to server in-app event.

Timing the events

Server-to-server events can be sent in real time or with an event time stamp.

You can use the optional eventTime parameter to specify the time of the event occurrence (in UTC +0 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")

When sending events with timestamps, for these events to be recorded with their real-time stamps (when they actually took place), they must all be sent to AppsFlyer by 02:00 AM UTC +0 of the following day.

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

Event with timestamp sent before 2am  utc +0

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).

Event with timestamp sent after 2 am utc +0

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 is sent to the AppsFlyer server and not the time that the event occurred (4 May @ 09:00).

Event with future timestamps

Events sent with future timestamps are always recorded in AppsFlyer under the time they are sent to AppsFlyer, and not the event timestamp in the payload.

Timing events: visual timeline



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

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 12 found this helpful