Server-to-server events API

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:

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


Parameter Name Type Description
appsflyer_id Mandatory Attributes the event to a media source and campaign.
eventName Mandatory Specifies the event name.
eventValue Recommended Exception: Parameter is mandatory in order to calculate revenue.
af_events_api Mandatory Value must be true.
idfa Recommended Exception: Parameter is mandatory in order to send in-app event postbacks to external partners.



Exception: Parameter is mandatory in order to send in-app event postbacks to external partners.

ip Recommended
  • IP address (ip) is the mobile device’s IP (during an event occurrence).
  • IP address determines the event country. If no IP address is specified, the country field shows N/A in the raw data.
customer_user_id Optional Customer user ID is used to associate in-app events with users in BI systems.


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 servers: 3 May @ 01:00

Event is recorded in the 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 servers: 4 May @ 09:00

Event is recorded in the 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, 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?