Server-to-server events API

At a glance: Use the Server-to-Server (S2S) events API to send events that occur outside of your app.  For example, if you have both a web and mobile interface, you can record events from the web interface using S2S and events from the mobile using the SDK.

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

  • Content-Type: Set as application/json.
  • URL endpoint:{app_id}
    • Android example:
    • iOS example:
      Note: The app ID is the app's itunes ID. Ensure that the App ID in iOS contains a leading id before the ID. Failure to do so results in a valid 200 OK return code but the event is not registered.
    • Windows example:
      Note: The app ID is the app's ID on Microsoft App Store.
  • Maximum size of the JSON payload: 1K 
  • The JSON payload must be passed as a string and the event value must be stringified.
  • The JSON payload must include 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 the examples below.

Method: POST

Header - "authentication"= {dev-key}

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

iOSAndroid & Windows
  "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.


  • Prepare the API message using the parameters listed here. 
  • Ensure that you send all the mandatory parameters and at least one advertising (device) parameter.
  • You may be unable to send the advertising identifier for good reason. For example,  the user enabled limited ad tracking (LAT). 
  • Failing to send an advertising ID/device identifier can cause attribution failure,  meaning that AppsFlyer can't attribute the event.
    • This occurs, for example, if the install record no longer exists due to data retention policies of integrated partners. 
    • The device identifier parameter is not mandatory, you can elect not to send any device identifier but take into consideration the consequences.
  • If you timestamp events usingeventTime, the events must arrive at AppsFlyer before 02:00 UTC of the next day. Late arrivals are timestamped by AppsFlyer using the time of arrival. For example, if the event took place on Monday, it must arrive by no later than Tuesday 02:00 UTC. 
Parameter Name Mandatory Description
appsflyer_id Yes

The unique identifier generated by AppsFlyer when the app launches for the first time. 

Example: "appsflyer_id": "1415211453000-6513894"

You must send one advertising ID (see the note above in this regard)

Available on ioS devices


Available on Android devices having Google Play Services (aka GAID)

oaid Available on Android devices supporting OAID

 Available from Amazon devices.

imei The IMEI is a physical device identifier as opposed to other identifiers which are logical
ip No

The mobile device's IP address during the event occurrence.

If sent, the IP address is used to populate geo fields.

If not sent, AppsFlyer populates the IP address and geo fields using the values from the install attribution event. 

Example: "ip": "

af_events_api Yes

Set to "true" always.

Example: "af_events_api" :"true"

customer_user_id No

Customer user ID, a unique user identifier set by the app owner.

Example: "customer_user_id": "my_customer_number1234" 

eventName Yes

Specifies the event name.

Example: "eventName": "af_purchase"

eventValue Yes - not enforced

Specifies the event attributes

If you send an event without a value then send: "eventValue":""

Event values need to be sent without additional symbols or formatting.

A decimal comma can be used. Negative values should be preceded by a - 

Example: "eventValue": "{ \"af_revenue\": \"6\", \"af_content_type\": \"wallets\", \"af_content_id\": \"15854\", \"af_quantity\" :\"1\" }"

app_version_name No

A string containing the app version

eventTime No

S2S events can be sent in real-time or with an event timestamp.

Default: If noeventTimeis sent then the event is timestamped using the time of arrival of the HTTP message.

Set by you:

Format: string yyyy-mm-dd hh:mm:ss.sss the time needs to be in UTC timezone.

Example: "2014-05-15 12:17:01.123" means 17:01 UTC time. 

Close of day: If you implement eventTime the event must be received be AppsFlyer by no later 02:00 of the following day. Meaning, if the event took place on Monday at 17:00 UTC it must reach the servers by no later than Tuesday 02:00 UTC. 

Events received after close of day are stamped with the time of arrival. 

Events having a future time, meaning after the arrival time, are stamped with the arrival time. 


Times are in UTC

An event is sent with eventTime = Monday 21:00.

Time of arrival Time recorded Remark
Tuesday 01:00 Monday 21:00  
Wednesday 09:00  Wednesday 09:00 Use eventTime default value, meaning arrival time
eventCurrency No

3 character ISO 4217 currency code.

Default: USD 

Example: "eventCurrency": "ZAR"

Server to server event paramters

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.


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, optimization 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. The ID can be obtained as follows:


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?