# Data API 2.0

If, for some reason, you cannot use the devtodev SDK, or some events cannot be tracked on the client side, you can use the devtodev data API. Using the API, you can send a set of events that almost completely replicates the capabilities of the SDK. However, you will need to independently prepare data about the device/user and also independently track the start and duration of sessions.

## Request format

#### URL: <a href="#example-url" id="example-url"></a>

`https://api.devtodev.com/v2/analytics/report?appId=sampleApplicationId`

<table><thead><tr><th width="136.33333333333331">Field</th><th width="113">Required</th><th>Description</th></tr></thead><tbody><tr><td>appId</td><td>Yes</td><td>devtodev application ID</td></tr></tbody></table>

POST data is received by the server in compressed or text form, depending on the value of the "Content-type" field in the HTTP header.&#x20;

All the transferred data must be in UTF8 encoding.

The archive must contain JSON with one or more events for one or several users.&#x20;

The packet size cannot exceed 2 MB in its uncompressed state. Packages that exceed this size can't be processed.&#x20;

#### Headers: <a href="#example-headers" id="example-headers"></a>

<table><thead><tr><th width="155">Header</th><th width="83">Type</th><th width="104">Required</th><th>Description</th></tr></thead><tbody><tr><td>Content-type</td><td>String</td><td>Yes</td><td><p></p><p>The possible values for the "Content-type" field are:</p><ul><li><strong>application/json -</strong> for sending uncompressed JSON data</li><li><strong>application/zstd -</strong> for sending data compressed using <a href="http://facebook.github.io/zstd/">Facebook's standard algorithm</a></li><li><strong>application/gzip</strong> - for sending data compressed using gzip algorithms</li></ul></td></tr></tbody></table>

#### Example POST Data: <a href="#example-post-data" id="example-post-data"></a>

```json
{  
    "reports" : [
        {
            "deviceId" : "deviceId",
            "previousDeviceId" : "samplePreviousMainId",
            "userId" : "sampleUserId",
            "previousUserId" : "samplePreviousUserId",
            "devtodevId": 6123517,
            "packages" : [
                {
                    "language" : "en",
                    "country": "US",
                    "ip": "154.12.121.11",
                    "appVersion" : "1.0",
                    "appBuildVersion": "30",
                    "sdkVersion" : "2.0",
                    "sdkCodeVersion" : 20,
                    "bundle" : "com.example.application",
                    "installationSource" : "",
                    "engine": "Unity",
                    "events" : [
                        ... //see Events section
                    ]
                },
                {
                    ...
                }
            ]  
        },
        ...
    ]
}
```

&#x20;

The **`reports`** object contains:

<table><thead><tr><th width="179">Parameter</th><th width="120">Type</th><th width="194">Required</th><th>Description</th></tr></thead><tbody><tr><td>deviceId</td><td>String (64)</td><td>Yes</td><td>Current (actual) Device ID</td></tr><tr><td>previousDeviceId</td><td>String (64)</td><td>Should be sent if the Device ID is changed</td><td>Previous Device ID</td></tr><tr><td>userId</td><td>String (64)</td><td>When accounting by User ID</td><td>Current (actual) User ID</td></tr><tr><td>previousUserId</td><td>String (64)</td><td>Should be sent if the User ID is changed (renamed)</td><td>Previous User ID</td></tr><tr><td>devtodevId</td><td>Long</td><td>No</td><td>Numeric user/device account ID in the devtodev database. We recommend using this identifier if you are using SDK and API at the same time. <a href="../../integration-of-sdk-v2/setting-up-events/secondary-methods#getting-devtodev-id">Get this identifier on the SDK side</a>, save it on your server and use it to send data via API. Sending other identifiers is not necessary in this case.</td></tr><tr><td>packages</td><td>Array</td><td>Yes</td><td>Packets with events that happened to the user (see below)</td></tr></tbody></table>

Each packet consists of the following fields:

<table><thead><tr><th width="185">Parameter</th><th width="84">Type</th><th width="104">Required</th><th>Description</th></tr></thead><tbody><tr><td>platform</td><td>String</td><td>No</td><td><strong>Only required for</strong> <a href="../../getting-started/cross-platform-application"><strong>cross-platform type projects</strong></a><strong>.</strong> <br>Platfrom identifier (Settings -> SDK -> Integration -> Platform ID)</td></tr><tr><td>language</td><td>String (3)</td><td>Yes</td><td>User/device language (ISO 639-1, ISO 639-2, ISO 639-3)</td></tr><tr><td>country</td><td>String (2)</td><td>Yes</td><td>User/device country (ISO_3166-1_alpha-2). Only needed in the server-server protocol</td></tr><tr><td>ip</td><td>String (15)</td><td>No</td><td>The IP address of the device. Only needed in the server-server protocol. </td></tr><tr><td>appVersion</td><td>String (64)</td><td>No</td><td>App version</td></tr><tr><td>appBuildVersion</td><td>String</td><td>No</td><td>Application build version. A string value is used for compatibility across all platforms</td></tr><tr><td>sdkVersion</td><td>String</td><td>No</td><td>Version of the integrated SDK</td></tr><tr><td>bundle</td><td>String</td><td>No</td><td>Application bundle</td></tr><tr><td>engine</td><td>String</td><td>No</td><td>Application platform/engine (Native, Unity, Unreal, Air)</td></tr><tr><td>installationSource</td><td>String</td><td>No</td><td>Only for Android. The installer bundle is passed as the value. It determines where the application was installed from (apk, Google Play, Amazon, etc). Used to detect and prevent illegal apk installs</td></tr><tr><td>events</td><td>Array</td><td>Yes</td><td>Events in the order they are generated (details below)</td></tr></tbody></table>

#### Response <a href="#response" id="response"></a>

The server responds with code 200 if everything is OK.

<table><thead><tr><th width="163">HTTP Code</th><th>State</th></tr></thead><tbody><tr><td>413</td><td>Incorrect size of the data packet (exceeds the maximum)</td></tr><tr><td>400</td><td>devtodev App ID is absent</td></tr><tr><td>401</td><td>Incorrect devtodev App ID</td></tr><tr><td>403</td><td>Administrative restrictions on data received from a client</td></tr><tr><td>400</td><td><p>The error of data unpacking</p><p><code>{</code></p><p><code>"error_message":"Wrong GZIP format"</code></p><p><code>}</code></p></td></tr><tr><td>400</td><td><p>The error of JSON format</p><p><code>{</code></p><p><code>"error_message":"Wrong JSON format"</code></p><p><code>}</code></p></td></tr><tr><td>200</td><td>OK. Data received</td></tr></tbody></table>

## Service Events <a href="#events" id="events"></a>

### Device Info <a href="#device-info" id="device-info"></a>

Contains information about the user's device.&#x20;

{% hint style="warning" %}
You must send the Device Info event as the first event when a new user is created. Without it, the user will not be registered in the system!&#x20;
{% endhint %}

It is also desirable to send this event at the beginning of each session.&#x20;

<table><thead><tr><th width="183">Parameter</th><th width="107">Platform</th><th width="104">Required</th><th width="89">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Any</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value "<strong>di</strong>"</td></tr><tr><td>timestamp</td><td>Any</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>osVersion</td><td>Any</td><td>No</td><td>String</td><td>Operating system version</td></tr><tr><td>os</td><td>Any</td><td>No</td><td>String</td><td>OS family name (Android, iOS, Mac, Windows…)</td></tr><tr><td>displayPpi</td><td>Any</td><td>No</td><td>Int</td><td>Screen pixel density</td></tr><tr><td>displayResolution</td><td>Any</td><td>No</td><td>String</td><td>Screen resolution in pixels, sent as "longSide"x"shortSide" ("1024x768")</td></tr><tr><td>displayDiagonal</td><td>Any</td><td>No</td><td>Double</td><td>Screen size (inches)</td></tr><tr><td>manufacturer</td><td>Android, iOS, Mac</td><td>No</td><td>String</td><td>Device manufacturer (Apple, Samsung)</td></tr><tr><td>model</td><td>Android, iOS, Mac</td><td>No</td><td>String</td><td>Device model. Value of the name (iOS), model (Android)</td></tr><tr><td>deviceType</td><td>Any</td><td>No</td><td>Int</td><td>Device Type:<br>0 - Unknown<br>1 - Phone<br>2 - Tablet<br>3 - Desktop<br>4 - Watch<br>5 - TV<br>6 - Simulator</td></tr><tr><td>timeZoneOffset</td><td>Any</td><td>No</td><td>Int</td><td>The UTC offset (or time offset) in seconds</td></tr><tr><td>rooted</td><td>Any</td><td>No</td><td>Int</td><td>Is the device rooted</td></tr><tr><td>isLimitAdTrackingEnabled</td><td>iOS, Android, Windows</td><td>No</td><td>Bool</td><td>Whether ad tracking restriction is enabled</td></tr><tr><td>userAgent</td><td>Any</td><td>No</td><td>String</td><td>User-Agent header</td></tr><tr><td>idfv</td><td>iOS, Mac</td><td>No</td><td>String</td><td>identifierForVendor</td></tr><tr><td>idfa</td><td>iOS, Mac</td><td>No</td><td>String</td><td>advertisingIdentifier</td></tr><tr><td>androidId</td><td>Android</td><td>No</td><td>String</td><td>Device SSAID. Not recommended for use</td></tr><tr><td>advertisingId</td><td>Android, Windows</td><td>No</td><td>String</td><td>Advertising ID</td></tr><tr><td>serialId</td><td>Android, Windows</td><td>No</td><td>String</td><td>Build.Serial (Android). Not recommended for use.</td></tr><tr><td>uuid</td><td><p>Android, Windows,</p><p>iOS,<br>macOS</p></td><td>No</td><td>String</td><td><p><a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a></p><p><a href="https://developer.apple.com/documentation/corefoundation/cfuuid?language=objc">CFUUID | Apple Developer Documentation</a></p></td></tr><tr><td>instanceId</td><td>Android</td><td>No</td><td>String</td><td>InstanceId.Get();</td></tr><tr><td>sandboxState</td><td>iOS</td><td>No</td><td>Int</td><td>Information about how the application is built: undefined (0) / sandbox (1) / production (2)</td></tr></tbody></table>

Example

```json
{
	"code": "di",
	"timestamp": 1694783505123,
	"osVersion": "10.2.2",
	"os": "iOS",
	"displayPpi": 401,
	"displayResolution": "1920x1080",
	"dispalyDiagonal": "5.5",
	"manufacturer": "Apple",
	"model": "iPhone8,2",
	"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12",
	"timeZoneOffset": 7200,
	"idfv": "30FE1CE1-1125-4657-97B0-638744C3C6D1",
	"idfa": "0A60DCF2-3186-4801-9192-D8CFA995DD6D"
}
```

### Session Start <a href="#session-start" id="session-start"></a>

Sends information about the start of a new session.&#x20;

{% hint style="info" %}
In order to [track sessions](https://docs.devtodev.com/integration/integration-of-sdk-v2/setting-up-events/track-sessions) fully, you also need to send a [User Engagement](#user-engagement) event.
{% endhint %}

<table><thead><tr><th width="142">Parameter</th><th width="106">Required</th><th width="83">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value "<strong>ss"</strong></td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date of the new session start. Unix timestamp in milliseconds</td></tr><tr><td>level</td><td>Yes</td><td>Int</td><td>User (player) level at the time the event was generated</td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current session. This is a kind of key by which you can link all user events that occurred during one session. This can be a session start timestamp, or you can use some custom numeric ID, or the user's session sequence number if you have that data.</td></tr></tbody></table>

Example

```json
{
    "code": "ss",
    "timestamp": 1694783505123,
    "level": 1
}
```

### User Engagement <a href="#user-engagement" id="user-engagement"></a>

Sends information about the duration of user activity. This can be either the full length of the session or a part of the user's session while the application was in focus.

<table><thead><tr><th width="139">Parameter</th><th width="106">Required</th><th width="91">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value "<strong>ue"</strong></td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>level</td><td>Yes</td><td>Int</td><td>User (player) level at the time the event was generated</td></tr><tr><td>length</td><td>Yes</td><td>Int</td><td>Full session duration or a part of a user session in seconds</td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

Example

```json
{
    "code": "ue",
    "timestamp": 1694783735122,
    "level": 1,
    "length": 230,
    "sessionId": 1694783505123
}
```

### Setting User Tracking Status (GDPR) <a href="#setting-user-tracking-status-gdpr" id="setting-user-tracking-status-gdpr"></a>

This event denies/allows tracking of user data and also implements the right to be forgotten in accordance with the requirements of the GDPR.

A developer must use this event in case a user doesn’t want their data to be sent and processed in the devtodev system.

When calling the event with the parameter "trackingAllowed"*: false*, it is a command to the server to delete all user’s personal data that has been collected by devtodev from this app and a command to block the collection of any data of this user in future.

The user will remain in the devtodev system only as an impersonal unit in the previously aggregated metrics.

If it is set to “***true***”, tracking can be enabled again. In this case, the user will be considered new.

<table><thead><tr><th width="173">Parameter</th><th width="107">Required</th><th width="92">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"ts"</strong></td></tr><tr><td>trackingAllowed</td><td>Yes</td><td>Bool</td><td>Enable (true) or disable (false) user tracking</td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr></tbody></table>

Example

```json
{
    "code": "ts",
    "trackingAllowed": false,
    "timestamp": 1694783565763
}
```

### Alive <a href="#alive" id="alive"></a>

Service event. Not obligatory. Ping event for the server. It is required to correctly display a player online if more than 5 minutes have passed since his last sent event.

<table><thead><tr><th width="139">Parameter</th><th width="104">Required</th><th width="88">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"al"</strong></td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

Example

```json
{
    "code": "al",
    "timestamp": 1694783607178
}
```

## User properties <a href="#a-d-impression" id="a-d-impression"></a>

### People

Each devtodev project can have **up to 30 custom user properties.**

{% hint style="warning" %}
Attention! We strongly recommend that you do not use these properties to transfer and store data that fits the definition of [personal data](https://gdpr-info.eu/issues/personal-data/)!
{% endhint %}

<table><thead><tr><th width="135">Parameter</th><th width="107">Required</th><th width="129">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"pl"</strong></td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>level</td><td>Yes</td><td>Int</td><td>User (player) level at the time the event was generated</td></tr><tr><td>parameters</td><td>Yes</td><td>Object&#x3C;Key, Value></td><td><p>User characteristics in key-value format. May contain predefined (tester, cheater, name, email, phone, photo, gender, age) and custom user propery names.</p><p>User custom property values can be a number, a string (up to 500 symbols), or a boolean value</p></td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

Predefined user properties (in addition to 30 custom user properties).

<table><thead><tr><th width="132">Property</th><th width="112">Required</th><th width="128">Type</th><th>Description</th></tr></thead><tbody><tr><td>tester</td><td>No</td><td>bool</td><td>Set true if user is a tester. This user's data will not be used to calculate metrics.</td></tr><tr><td>cheater</td><td>No</td><td>bool</td><td>Set true if user is a cheater. This user's data will not be used to calculate metrics.</td></tr></tbody></table>

{% hint style="warning" %}
If you need to exclude cheaters/testers transactions from statistics, go to **Users & Segments** section in devtodev interface and [mark the user](https://docs.devtodev.com/reports-and-functionality/project-related-reports-and-fuctionality/users#mark-as-cheater-or-tester) manually. \
When you mark the user in devtodev interface, the system removes their transactions for the last 7 days the reports and recalculates the metrics.&#x20;
{% endhint %}

Example

```json
{
	"code": "pl",
	"timestamp": 1694783511089,
	"sessionId": 1694783505123,
	"level": 2,
	"parameters": {
		"name": "John Doe",
		"cheater": false,
		"age": 21
	}
}
```

## Basic Events <a href="#currency-accrual" id="currency-accrual"></a>

### Custom Event <a href="#custom-event" id="custom-event"></a>

If you want to track non-basic events (below), you can create custom events of your own. How you are going to apply them, depends solely on you.

{% hint style="info" %}
devtodev supports not more than 300 custom event names in a single project. Events that exceed the limit of custom event names will be discarded. Try to integrate the tracked actions by type to the event name level, and move the characteristic tags to the parameters.

*For example, if you need to track purchases of “Paper” and “Pen” items, you don’t need to create two events with the names “Paper Purchase” and “Pen Purchase”. Instead. create a single “Purchase” event and add an “Item” parameter with the appropriate value of “Paper” or “Pen”. This way, you can use just one event to track many items.*

For a string parameter, you can use no more than 50,000 unique values ​​for the entire history of events. If the number of unique values exceeds the limit, the parameter gets locked by the system and is discarded from the received data. Therefore, we don’t recommend using highly variable parameters like user IDs or time as string values ​​(moreover, they are automatically added to the event).

We strongly recommend that you do not change the data type passed in the same parameter. If you change the data type in a parameter, it will be duplicated with the same name, which may cause issues while processing reports.
{% endhint %}

{% hint style="warning" %}
We strongly recommend that you do not use custom event properties to transfer and store data that fits the definition of [personal data](https://gdpr-info.eu/issues/personal-data/)!
{% endhint %}

<table><thead><tr><th width="143">Parameter</th><th width="108">Required</th><th width="128">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"ce"</strong></td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>level</td><td>Yes</td><td>Int</td><td>User (player) level at the time the event was generated</td></tr><tr><td>name</td><td>Yes</td><td>String (72)</td><td>Custom event name</td></tr><tr><td>parameters</td><td>No</td><td>Object&#x3C;Key (32),Value></td><td>Custom event parameters</td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

Example&#x20;

```json
{
	"code": "ce",
	"timestamp": 1694783521034,
	"sessionId": 1694783505123,
	"level": 2,
	"name": "eventName",
	"parameters": {
		"intParameter": 134,
		"stringParameter": "hello",  //255 symbols max
		"doubleParameter": 12.98
	}
}
```

### Real Payment  <a href="#real-currency-payment" id="real-currency-payment"></a>

To track payments in a real currency, dispatch this event right after the system validates that the payment went through successfully. The event is fundamental and mandatory for all the app metrics related to monetization.

{% hint style="info" %}
By default (easy to change in the app’s settings), the devtodev server invalidates transactions with previously-used identifiers. Additionally, the server performs identifier checks based on their outer appearance in order to avoid obvious fraud.
{% endhint %}

<table><thead><tr><th width="159">Parameter</th><th width="104">Required</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"rp"</strong></td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>level</td><td>Yes</td><td>Int</td><td>User (player) level at the time the event was generated</td></tr><tr><td>productId</td><td>Yes</td><td>String (255)</td><td>Product name. We recommend using the product SKU</td></tr><tr><td>orderId</td><td>Yes</td><td>String (64)</td><td>Unique transaction ID</td></tr><tr><td>price</td><td>Yes</td><td>Double</td><td>Price in user currency</td></tr><tr><td>currencyCode</td><td>Yes</td><td>String (3)</td><td>ISO 4217 alphabetic code of the user's currency</td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

Example

```json
{
	"code": "rp",
	"timestamp": 1694783605101,
	"sessionId": 1694783505123,
	"level": 2,
	"productId": "starter_pack",
	"orderId": "GPA.100054271428",
	"price": 19.99,
	"currencyCode": "USD"
}
```

### Onboarding (tutorial)

Tracks the progress of the user's initial training (tutorial). The event is used to build a funnel through which users go through learning stages (steps). Each step is represented by an integer greater than 0.\
If you plan to add additional intermediate learning steps, you can number the steps initially, for example, in increments of 10.\
Additionally, three constants are used to describe the start of training, successful completion of training, and skipping the entire training process.

Recommended sequence for dispatching events:

1. Training started (**-1**).
2. Sequential sending of events at the entrance to the next learning step (**1...N**).
3. Completion of training after passing the last step of training (**-2**).

The tutorial skip logic assumes that a single event with a value of **0** is sent, replacing the entire sequence described above.

<table><thead><tr><th width="131">Parameter</th><th width="105">Required</th><th width="88">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"tr"</strong></td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>level</td><td>Yes</td><td>Int</td><td>User (player) level at the time the event was generated</td></tr><tr><td>step</td><td>Yes</td><td>Int</td><td>Tutorial step number or predefined values (0, -1, -2 see above)</td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

Example

```json
{
	"code": "tr",
	"timestamp": 1694783715371,
	"sessionId": 1694783505123,
	"level": 2,
	"step": -1
}
```

### Virtual Currency Payment  <a href="#virtual-currency-payment" id="virtual-currency-payment"></a>

This event is for games only.

Pass this event after every purchase if you want to track in-app (virtual) currency spends and items’ popularity. You can apply this event to both games and any apps with virtual currency.

<table><thead><tr><th width="182">Parameter</th><th width="104">Required</th><th width="147">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"vp"</strong> ("ip" in the previous version of the API)</td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>level</td><td>Yes</td><td>Int</td><td>User (player) level at the time the event was generated</td></tr><tr><td>purchaseAmount</td><td>Yes</td><td>Int</td><td>Number of items purchased</td></tr><tr><td>purchasePrice</td><td>Yes</td><td>Object&#x3C;String (24), Number></td><td>Currency and price of the purchased items (or currencies, if there are multiple)</td></tr><tr><td>purchaseType</td><td>Yes</td><td>String (96)</td><td>The group to which the item belongs</td></tr><tr><td>purchaseId</td><td>Yes</td><td>String (32)</td><td>Item ID or name</td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

Example

```json
{
	"code": "vp",
	"timestamp": 1694783555833,
	"sessionId": 1694783505123,
	"level": 2,
	"purchaseId": "house_327",
	"purchaseAmount": 2,
	"purchasePrice": {
		"coins": 500,
		"wood": 2
	},
	"purchaseType": "buildings"
}
```

### Currency Accrual <a href="#currency-accrual" id="currency-accrual"></a>

This event is for games only.

The event involves the accumulation of in-game currency or resources. It contains data on the amount of in-game currency earned or purchased by the user. It is highly undesirable to send this data transactionally. Instead, please send aggregated data for a specific period, such as 5-10 minutes. Additionally, the accumulation of data must be interrupted, and an event should be sent if the user's level has changed.

{% hint style="warning" %}
Attention! The total number of tracked unique resources (virtual currencies) cannot exceed 30 items throughout the project's lifespan.
{% endhint %}

Furthermore, apart from grouping by type (earned/purchased), there is also a grouping by the source of income.

<table><thead><tr><th width="132">Parameter</th><th width="150">Required</th><th width="185">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"ca"</strong></td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>level</td><td>Yes</td><td>Int</td><td>User (player) level at the time the event was generated</td></tr><tr><td>bought</td><td>Yes<br>one or both (bought and earned)</td><td>Object&#x3C;String, Object&#x3C;String (24), Number>></td><td>Resources of the type "bought" (purchased) aggregated over a specific period by source and resource name</td></tr><tr><td>earned</td><td>Yes<br>one or both (bought and earned)</td><td>Object&#x3C;String, Object&#x3C;String (24), Number>></td><td>Resources of type "earned" aggregated over a specific period by source and resource name</td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

```json
{
	"code": "ca",
	"timestamp": 1694783625364,
	"sessionId": 1694783505123,
	"level": 2,
	"bought": {
		"sourceA": {
			"resource1": 1231,
			"resource2": 1231
		},
		"sourceB": {
			"resource1": 12,
			"resource2": 31
		},
		"sourceC": {
			"resource2": 40,
			"resource1": 10
		}
	},
	"earned": {
		"sourceA": {
			"resource1": 1231,
			"resource2": 1231
		},
		"sourceD": {
			"resource1": 1231,
			"resource2": 1231
		}
	}
}
```

### Current Balance

This event is for games only.

This event is used to generate a preset game report called Economy Balance (currency balance with grouping by days). This report shows the approximate amount of virtual currency on users' hands, which is useful for planning and checking the results of campaigns aimed at removing excess virtual currency from the application.

{% hint style="warning" %}
This event should not be sent more than once per day for a user.
{% endhint %}

<table><thead><tr><th width="159">Parameter</th><th width="102">Required</th><th width="153">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"cb"</strong></td></tr><tr><td>balance</td><td>Yes</td><td>Object&#x3C;String(24),Number></td><td>User's balances of virtual currencies or resources at the time the event was generated</td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>level</td><td>Yes</td><td>Int</td><td>User (player) level at the time the event was generated</td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

Example

```json
{
	"code": "cb",
	"timestamp": 1694783615284,
	"sessionId": 1694783505123,
	"level": 2,
	"balance": {
		"money1": 123,
		"money2": 11
	}
}
```

### Level Up <a href="#level-up" id="level-up"></a>

This event is for games only.

Leveling up the user (player). The event is triggered when the user reaches a new level. In addition o the achieved level number, you can also include data on the balance of virtual currencies or resources at the time the new level was reached, as well as the total amount of currencies or resources spent, earned and purchased by the user during the previous level progression.

{% hint style="warning" %}
Attention! The total number of tracked unique resources (virtual currencies) cannot exceed 30 items throughout the entire life of the project.
{% endhint %}

<table><thead><tr><th width="135">Parameter</th><th width="106">Required</th><th width="152">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"lu"</strong></td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>level</td><td>Yes</td><td>Int</td><td>User (player) level achieved by the user</td></tr><tr><td>balance</td><td>No</td><td>Object&#x3C;String (24), Number></td><td>User's balances of virtual currencies or resources at the time of leveling up</td></tr><tr><td>spent</td><td>No</td><td>Object&#x3C;String (24), Number></td><td><p>Total expenses of resources (virtual currency) by the user during level progression</p><p>In the SDK, this data is aggregated from virtual currency payment events</p></td></tr><tr><td>earned</td><td>No</td><td>Object&#x3C;String (24), Number></td><td><p>The total amount of resources (virtual currency) earned by the user during level progression</p><p>In the SDK, this data is aggregated from CurrencyAccrual events with the "earned" type</p></td></tr><tr><td>bought</td><td>No</td><td>Object&#x3C;String (24), Number></td><td><p>The total number of resources (virtual currency) purchased by the user for real currency during level progression</p><p>In the SDK, data is aggregated from the CurrencyAccrual events with the "bought" type</p></td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

Example

```json
{
	"code": "lu",
	"timestamp": 1694783675815,
	"sessionId": 1694783505123,
	"level": 2,
	"balance": {
		"money1": 123,
		"money2": 11
	},
	"spent": {
		"money1": 12,
		"money2": 2,
		"wood": 12
	},
	"earned": {
		"crystals": 5
	},
	"bought": {
		"wood": 200
	}
}
```

### Progression Event <a href="#progression-event" id="progression-event"></a>

This event is for games only.

First of all, the progression event is used in games with short (within one game session) areas/game levels, for example, match 3 games. You can use the event to collect data on how well or how fast users complete levels, how difficult it is for them, how many resources they gained or spent, and other relevant parameters.

<table><thead><tr><th width="135">Parameter</th><th width="107">Required</th><th width="179">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"pe"</strong></td></tr><tr><td>timestap</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>level</td><td>Yes</td><td>Int</td><td>User (player) level at the time the event was generated</td></tr><tr><td>parameters</td><td>Yes</td><td>Object</td><td>Event parameters. See below</td></tr><tr><td>spent</td><td>No</td><td>Object&#x3C;String (24), Number></td><td>Resources consumed during an area completion</td></tr><tr><td>earned</td><td>No</td><td>Object&#x3C;String (24), Number></td><td>Resources earned during an area completion.</td></tr><tr><td>name</td><td>Yes</td><td>String (40)</td><td>The name of the event. It is usually the number or the name of the area/location/level.</td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

parameters object:

<table><thead><tr><th width="132">Parameter</th><th width="110">Required</th><th width="120">Type</th><th>Description</th></tr></thead><tbody><tr><td>difficulty</td><td>No</td><td>Int</td><td>An optional difficulty value</td></tr><tr><td>source</td><td>No</td><td>String (40)</td><td>The name of the previous progression event used for connecting events together. E.g. a previous area visited by the player</td></tr><tr><td>success</td><td>Yes</td><td>Bool</td><td>The completion event result: “true” if successful, “false” if unsuccessful/lost</td></tr><tr><td>duration</td><td>Yes</td><td>Long</td><td>Time in seconds taken to complete the area</td></tr></tbody></table>

Example

```json
{
	"code": "pe",
	"timestamp": 1694783885625,
	"sessionId": 1694783505123,
	"level": 2,
	"name": "MyAwesomeLocation",
	"parameters": {
		"source": "location1",
		"difficulty": 1,
		"success": true,
		"duration": 180
	},
	"spent": {
		"money1": 12,
		"money2": 2,
		"wood": 12
	},
	"earned": {
		"money1": 8,
		"money2": 2,
		"stone": 1
	}
}
```

All events generated during the passage of the location are recommended to be marked with the key "inProgress," the value of which indicates the name of the location (Progression event name).

Example

```json
{
	"code": "rp",
	"timestamp": 1694783895114,
	"sessionId": 1694783505123,
	"level": 2,
	"productId": "starter_pack",
	"orderId": "GPA.100054271428",
	"price": 19.99,
	"currencyCode": "USD",
	"inProgress": ["MyAwesomeLocation"]
}
```

## Secondary Events <a href="#a-d-impression" id="a-d-impression"></a>

### Referral <a href="#referral" id="referral"></a>

Tracking the source of the application installation. Sent once per user. Does not need to be sent if ad trackers such as AppsFlyer are integrated in the project settings or the devtodev custom postback API is used.

<table><thead><tr><th width="134">Parameter</th><th width="106">Required</th><th width="89">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"rf"</strong></td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>source</td><td>No</td><td>String</td><td>Ad network name</td></tr><tr><td>campaign</td><td>No</td><td>String</td><td>Ad campaign name</td></tr><tr><td>content</td><td>No</td><td>String</td><td>Campaign content (for example, for A/B testing of site elements or contextual ads)</td></tr><tr><td>medium</td><td>No</td><td>String</td><td>Traffic type</td></tr><tr><td>term</td><td>No</td><td>String</td><td>Campaign search term (for example, PPC keywords)</td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

Example

```json
{
	"code": "rf",
	"timestamp": 1694783915948,
	"sessionId": 1694783505123,
	"source": "google",
	"campaign": "christmas",
	"content": "sale for ducks",
	"medium": "traff",
	"term": "a,b,c,d,e"
}
```

### Ad Impression <a href="#a-d-impression" id="a-d-impression"></a>

The event is used for individual tracking of ad revenue on user devices. This method is used if there are CPI data available on the client device (they can be obtained from the ad network SDK).

{% hint style="info" %}
Do not apply this event if you use ad networks that utilize the server-server protocol for sending ad revenue data (ironSource, AppLovin MAX, and Fyber networks) and you already set up this method of data collection because if you use both data sources, your revenue data may be duplicated.
{% endhint %}

<table><thead><tr><th width="140">Parameter</th><th width="105">Required</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"adrv"</strong></td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>source</td><td>No</td><td>String (100)</td><td>Impression data source name</td></tr><tr><td>ad_network</td><td>Yes</td><td>String (100)</td><td>The name of the ad network that delivered the impression</td></tr><tr><td>placement</td><td>No</td><td>String (100)</td><td>Placement of the banner</td></tr><tr><td>ad_unit</td><td>No</td><td>String (100)</td><td>Banner title</td></tr><tr><td>revenue</td><td>Yes</td><td>Double</td><td>Reward for displaying a banner in USD</td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

Example

```json
{
	"code": "adrv",
	"timestamp": 1694783775187,
	"sessionId": 1694783505123,
	"source": "IronSource",
	"ad_network": "Facebook",
	"placement": "End of the round",
	"ad_unit": "TestAdUnit",
	"revenue": 0.3434
}
```

### Social Connect <a href="#social-connect" id="social-connect"></a>

The event tracks the user's connection to a social network. It is sent at the moment when the application receives information about the successful authorization of the user on the social network.

<table><thead><tr><th width="163">Parameter</th><th width="111">Required</th><th width="86">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"sc"</strong></td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>level</td><td>Yes</td><td>Int</td><td>User (player) level at the time the event was generated</td></tr><tr><td>socialNetwork</td><td>Yes</td><td>String</td><td>Code or name of the social network. May contain predefined values (see below)</td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

Example

```json
{
	"code": "sc",
	"timestamp": 1694783815155,
	"sessionId": 1694783505123,
	"level": 2,
	"socialNetwork": "fb"
}
```

**Preset social network codes**

<table><thead><tr><th width="193">Social Network</th><th>Code</th></tr></thead><tbody><tr><td>Vkontakte</td><td>vk</td></tr><tr><td>Twitter</td><td>tw</td></tr><tr><td>Facebook</td><td>fb</td></tr><tr><td>Google Plus</td><td>gp</td></tr><tr><td>WhatsApp</td><td>wp</td></tr><tr><td>Viber</td><td>vb</td></tr><tr><td>Evernote</td><td>en</td></tr><tr><td>Google Mail</td><td>gm</td></tr><tr><td>LinkedIn</td><td>in</td></tr><tr><td>Pinterest</td><td>pi</td></tr><tr><td>Qzone</td><td>qq</td></tr><tr><td>Reddit</td><td>rt</td></tr><tr><td>Renren</td><td>rr</td></tr><tr><td>Tumblr</td><td>tb</td></tr></tbody></table>

### Social Post <a href="#social-post" id="social-post"></a>

The event tracks the user's posts on the social network. It is dispatched when a success report is received from the network, if possible.

<table><thead><tr><th width="165">Parameter</th><th width="107">Required</th><th width="89">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>Yes</td><td>String</td><td>The unique ID of the event. Takes the value <strong>"sp"</strong></td></tr><tr><td>timestamp</td><td>Yes</td><td>Long</td><td>The date the event was generated. Unix timestamp in milliseconds</td></tr><tr><td>level</td><td>Yes</td><td>Int</td><td>User (player) level at the time the event was generated</td></tr><tr><td>socialNetwork</td><td>Yes</td><td>String</td><td>Code or name of the social network. May contain predefined values (see above)</td></tr><tr><td>postReason</td><td>Yes</td><td>String</td><td>Reason for posting</td></tr><tr><td>sessionId</td><td>No</td><td>Long</td><td>The ID of the current <a href="#session-start">session</a></td></tr></tbody></table>

Example

```json
{
	"code": "sp",
	"timestamp": 1694783905478,
	"sessionId": 1694783505123,
	"level": 2,
	"socialNetwork": "fb",
	"postReason": "quest_completed"
}
```

## Example <a href="#real-currency-payment" id="real-currency-payment"></a>

An example of a package describing a single session of a single user.

{% hint style="info" %}
Note: devtodev does not accept data that is older than 7 days and data that is more than 3 hours in the future. If you want to use this example, you will need to edit the **`timestamp`** parameters.
{% endhint %}

{% code fullWidth="true" %}

```json
{
	"reports": [{
		"deviceId": "0A60DCF2-3186-4801-9192-D8CFA995DD6D",
		"userId": "u_100500",
		"packages": [{
			"language": "en",
			"country": "US",
			"appVersion": "1.0",
			"events": [{
					"code": "di",
					"osVersion": "10.2.2",
					"os": "iOS",
					"displayPpi": 401,
					"displayResolution": "1920x1080",
					"dispalyDiagonal": "5.5",
					"manufacturer": "Apple",
					"model": "iPhone8,2",
					"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12",
					"timeZoneOffset": 7200,
					"idfv": "30FE1CE1-1125-4657-97B0-638744C3C6D1",
					"idfa": "0A60DCF2-3186-4801-9192-D8CFA995DD6D",
					"timestamp": 1694783505122
				}, {
					"code": "ss",
					"timestamp": 1694783505123,
					"level": 1
				}, {
					"code": "pl",
					"timestamp": 1694783511089,
					"sessionId": 1694783505123,
					"level": 1,
					"parameters": {
						"name": "John Doe",
						"cheater": false,
						"age": 21
					}
				}, {
					"code": "tr",
					"timestamp": 1694783715371,
					"sessionId": 1694783505123,
					"level": 1,
					"step": -1
				}, {
					"code": "tr",
					"timestamp": 1694783725344,
					"sessionId": 1694783505123,
					"level": 1,
					"step": 1
				}, {
					"code": "lu",
					"timestamp": 1694783736345,
					"sessionId": 1694783505123,
					"level": 2,
					"balance": {
						"money1": 123,
						"money2": 11
					}
				}, {
					"code": "tr",
					"timestamp": 1694783741456,
					"sessionId": 1694783505123,
					"level": 2,
					"step": 2
				}, {
					"code": "tr",
					"timestamp": 1694783752425,
					"sessionId": 1694783505123,
					"level": 2,
					"step": -2
				}, {
					"code": "ce",
					"timestamp": 1694783773675,
					"sessionId": 1694783505123,
					"level": 2,
					"name": "eventName",
					"parameters": {
						"intParameter": 134,
						"stringParameter": "hello",
						"doubleParameter": 12.98
					}
				},
				{
					"code": "rp",
					"timestamp": 1694783798278,
					"sessionId": 1694783505123,
					"level": 2,
					"productId": "com.example.application.starterpack",
					"orderId": "280001601071201",
					"price": 19.99,
					"currencyCode": "USD"

				}, {
					"code": "ue",
					"timestamp": 1694783898278,
					"level": 2,
					"length": 393,
					"sessionId": 1694783505123
				}
			]
		}]
	}]
}
```

{% endcode %}
