> For the complete documentation index, see [llms.txt](https://help.branch.io/llms.txt).

# Attribution API Overview

## Overview

The Branch Attribution API offers developers a way to track `INSTALL`, `REINSTALL`, and `OPEN` events while also supplying a payload of attribution properties. This is something the Branch mobile SDKs do by default, but this API provides the option of sending this information server-side.

The response to a request sent to this API is deep link data.

**If you choose to use this API instead of tracking these events with a Branch SDK, be aware that session management becomes your responsibility**. You need to account for handling poor or no connectivity, persisting data locally, retrieving values like IP address, tracking downstream conversions, creating shareable deep links, and other possible challenges. To achieve feature parity with a Branch SDK, you would need to duplicate the code in the SDK.

For this reason, we **highly recommend that all apps use a** [**Branch SDK**](https://help.branch.io/developer-hub/native-sdks-overview.md) **when possible**.

### Limitations

By default, Branch rate limits non-referred `OPEN` events (that is, app sessions not sourced by a link) to **once every 4 hours per IP address**.

Rate limits vary by account. See [Branch pricing](https://www.branch.io/pricing/).

Sessions that exceed your rate limit still return deep link data in the network request, but the data does not appear in your Branch reports or exports.

Branch also returns `429` responses if your app starts sending requests for the same user in rapid succession. While this scenario does not mirror normal user behavior, you may run into it during your own testing. If this happens, wait a few minutes before resuming testing. You can also try changing the device metadata in your request.

### Try it!

Try out the Attribution API in your browser, using your Branch data:

[Request Open](https://help.branch.io/apidocs/attribution.md#requestOpen)

## Getting started

### Before you begin

To use the Attribution API, you first need to:

1. Create a [Branch account](https://dashboard.branch.io).
2. Make sure that your account has access to the `v1/open` API enabled.
3. [Configure](https://help.branch.io/account-hub/basic-link-configuration.md) Branch with default link redirects, your `app.link` domains, a URI scheme, and Universal Links.
4. Complete the "In-app setup" [section](https://help.branch.io/apidocs/attribution/overview.md#in-app-setup) of this guide for your relevant app(s).

### Authentication

For calls to the Attribution API, you need your Branch Key and Branch Secret.

**Legacy Branch**

To retrieve your credentials in the [legacy Branch experience](https://help.branch.io/marketer-hub/branch-dashboard-overview.md):

1. Navigate to the **Account → Settings → Profile** [tab](https://dashboard.branch.io/account-settings/profile).
2. Use the **copy icons** to copy your Branch Key and Branch Secret.

**New Branch**

To retrieve your credentials in the [new Branch experience](https://help.branch.io/account-hub/credentials-new.md):

1. Navigate to the **Configuration → Security & Access → Credentials** [tab](https://branchdocs.app.link/apis-to-credentials).
2. Use the **copy icons** to copy your Branch Key and Branch Secret.

Visit our [guide](https://help.branch.io/account-hub/credentials-new.md) to learn more about managing your Branch credentials.

## In-app setup

### iOS

#### Configuration

To configure your iOS app to use the Attribution API, you first need to:

1. Add your URI scheme to your `info.plist` [file](https://help.branch.io/developer-hub/ios-basic-integration.md#_4-configure-info-plist).
2. Add your Branch `app.link` and `alternate.app.link` domains to your project's [Associated Domains](https://help.branch.io/developer-hub/ios-basic-integration.md#_3-configure-associated-domains).

#### Collect launch data for request

To gather the launch data you need to make a request to the Attribution API, you can:

1. Retrieve the device ID ([IDFA](https://developer.apple.com/documentation/adsupport/asidentifiermanager/1614151-advertisingidentifier) or [IDFV](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor)) if available.
2. Retrieve the device's public IP address.
3. Retrieve the device's user agent string.
4. Examine your AppDelegate's `openURL()` [function](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623112-application?language=objc) for a URI.

   1. If a URI containing the query parameter `link_click_id` is present, then store that query parameter's value for use in the session's API network request.
   2. For example, if the URI `example://open?link_click_id=1234` opens the app, you need to retrieve the `1234` value.
5. Examine the AppDelegate's `continueUserActivity()` [function](https://developer.apple.com/documentation/uikit/inter-process_communication/allowing_apps_and_websites_to_link_to_your_content/handling_universal_links) for a `webpageURL` [value](https://developer.apple.com/documentation/foundation/nsuseractivity/1418086-webpageurl).

   1. The `webpageURL` value lives inside the `NSUserActivity` [parameter](https://developer.apple.com/documentation/foundation/nsuseractivity).
   2. If you find a URL, store the entire URL value for use in the session's API network request. This is true **regardless of whether it is a Branch Link**.

#### Optional: Support Apple Search Ads

For server-to-server integrations, you need to retrieve the new attribution token and send it to Branch on install as `apple_attribution_token`.

To retrieve the attribution token:

1. Import the `AdService.framework` into your project.
2. Request the attribution token, which should be available from Apple within 50ms:

   **Swift**

   ```swift
   func appleAttributionToken() -> String? {
       if #available(iOS 14.3, *) {
           return try? AAAttribution.attributionToken()
       }
       return nil
   }
   ```

   **Objective-C**

   ```objective-c
   + (NSString *)appleAttributionToken {
       #if !TARGET_OS_TV
       if (@available(iOS 14.3, *)) {
           NSError *error;
           NSString *appleAttributionToken = [AAAttribution attributionTokenWithError:&error];
           if (!error) {
               return appleAttributionToken;
           }
       }
       #endif
       return nil;
   }
   ```

3. Send the token to Branch for attribution within 24 hours, as that is the TTL for the token.

For more about retrieving the attribution token, visit Apple's [documentation](https://developer.apple.com/documentation/adservices/aaattribution?language=objc).

To learn more about Apple Search Ads, visit our [guide](https://help.branch.io/marketer-hub/category/apple-ads.md).

### Android

#### Configuration

1. Add your URI scheme to your `AndroidManifest.xml` [file](https://help.branch.io/developer-hub/android-basic-integration.md#_4-configure-app).
2. Also add your Branch `app.link` and `alternate.app.link` domains to your `AndroidManifest.xml` [file](https://help.branch.io/developer-hub/android-app-links.md#setup).

#### Collect launch data for request

To gather the launch data you need to make a request to the Attribution API, you can:

1. Retrieve the device ID ([GAID](https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient) or [Android_ID](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID)) if available.
2. Retrieve the device's public IP address.
3. Retrieve the device's user agent string.
4. Examine the [intent](https://developer.android.com/reference/android/app/Activity.html#getIntent()) that opened your `MainActivity` for a URI.

   1. If a URI containing the query parameter `link_click_id` is present, then store that query parameter's value for use in the session's API network request.
   2. For example, if the URI `example://open?link_click_id=1234` opens the app, you need to retrieve the `1234` value.
5. Examine the intent that opened your `MainActivity` for a web URL.

   1. If you find a URL, store the entire URL value for use in the session's API network request. This is true **regardless of whether it is a Branch Link**.

#### Optional: Support Google Play Install Referrer

Complete the steps below **only during** the `INSTALL` session:

1. Upon app launch, query the Google Play Install Referrer [library](https://developer.android.com/google/play/installreferrer/library#install-referrer) for the referrer URL, click timestamp, and install timestamp.
2. Examine the referrer URL for a `link_click_id` query parameter.

   1. If present, retrieve its value for use in the request's `link_identifier` parameter.
   2. This value might appear in the referrer URL as `&link_click_id=<>` or `&link_click_id-<>`. In either scenario, extract only the `<>` part.
3. Examine the referrer URL for a `google_search_install_referrer` query parameter.

   1. If present, retrieve its value for use in the request's `google_search_install_referrer` parameter.
   2. This value might appear in the referrer URL as `&google_search_install_referrer=<>` or `&google_search_install_referrer-<>`. In either scenario, extract only the `<>` part.

## Usage

The network request to the `v1/open` endpoint should occur once you've been notified that the user has successfully brought your app to the foreground.

Branch marks the beginning of an app lifecycle when your app is launched and brought to the foreground of the device. The launch can be from either a cold start or a transition from running in the background (present in the iOS or Android task manager) to the foreground.

On web, an open event is measured every time a webpage with the Branch Web SDK opens in a new tab or when a user clicks on a Branch Link and is redirected to a page with the Branch Web SDK. This is called a `web_session_start`.

> **Caution**
>
> To set the required X-IP-Override header, your **app ID needs to be added to our allowlist**. Reach out to [support@branch.io](mailto:support@branch.io) with your Branch app ID to have it added to the allowlist.

#### Request info

**Export request**

```http
POST /v1/open
Host: api2.branch.io
Content-Type: application/json
```

**Request headers**

| Header | Description | Required? |
| --- | --- | --- |
| `X-IP-Override` | The device's public IP address from your **app user's device**, not your server's IP address. | Yes |
| `content-type` | application/json | Yes |
| `accept` | application/json | Recommended |

**Request body parameters**

| Parameter | Type | Description | Required? |
| --- | --- | --- | --- |
| `branch_key` | String | The Branch Key of the relevant app, found in the Settings tab in [Branch](https://dashboard.branch.io/account-settings/profile). | **Required** on iOS & Android |
| `branch_secret` | String | The Branch Secret of the relevant app, found in the Settings tab in [Branch](https://dashboard.branch.io/account-settings/profile). | **Required** on iOS & Android |
| `server_to_server` | Bool | **Always** set this value to `true`. | **Required** on iOS & Android |
| `app_version` | String | The version of your app, such as `"1.12.4"`. | **Required** on iOS & Android |
| `os` | String | Choose either `Android` or `iOS`. | **Required** on iOS & Android |
| `os_version` | String | The device's OS version, such as `"14"` for Android or `"17.3.1"` for iOS.<br><br>This parameter cannot be blank, but the API accepts any string value, such as "`NA`". | **Required** on iOS & Android |
| `user_agent` | String | The user agent of the device. | **Required** on iOS & Android |
| `hardware_id` | String | For iOS, populate with the [IDFA](https://developer.apple.com/documentation/adsupport/asidentifiermanager/1614151-advertisingidentifier) if available. Otherwise, fall back to [IDFV](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor).<br><br>For Android, populate with the `ANDROID_ID` ([hardware ID](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID)). Otherwise, do not include in request. | **Required** on iOS |
| `hardware_id_type` | String | This value confirms whether the iOS ID in the `hardware_id` field is an IDFA or IDFV.<br><br>If `hardware_id` is not populated, do not include in request. | **Required** on iOS |
| `ios_vendor_id` | String | The [IDFV](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor), if available.<br><br>Otherwise, do not include in request. | **Required** on iOS |
| `google_advertising_id` | String | The [Google Advertising ID](https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient), if available.<br><br>Otherwise, do not include in request. | **Required** on Android |
| `advertising_ids` | Object | The set of advertising IDs, if available.<br><br>Otherwise, do not include in request.<br><br>Can include identifiers like OAID. | **Required** on Android |
| `is_hardware_id_real` | Boolean | Set this value to `false` if the `hardware_id` property cannot be populated.<br><br>Otherwise, default to `true`. | **Required** on iOS & Android |
| `ad_tracking_enabled` | Boolean | This value is used to determine whether the IDFA or GAID can be used for advertising purposes.<br><br>If Limit Ad Tracking should be enabled, do not include in the request. | **Required** on iOS & Android |
| `local_ip` | String | This is the device's local IP address, if one is available. Optional but highly recommended for improving attribution accuracy.<br><br>This is supplemental to the required `X-IP-Override` value in the header. | Recommended |
| `screen_height` | Int | Height of the device's screen. | Recommended |
| `screen_width` | Int | Width of the device's screen. | Recommended |
| `link_identifier` | String | When a URI opens the app, check for a `link_click_id` query parameter and populate the `link_identifier` parameter with that value.<br><br>The `link_click_id` may also be sourced from the [Google Install Referrer](https://developer.android.com/google/play/installreferrer/library). | Optional |
| `universal_link_url` | String | Populate this value with the Branch or non-Branch web URL that opened the app, if available.<br><br>Otherwise, do not include in request. | Optional, iOS only |
| `android_app_link_url` | String | Populate this value with the Branch or non-Branch web URL that opened the app, if available.<br><br>Otherwise, do not include in request. | Optional, Android only |
| `facebook_app_link_checked` | Boolean | Set to `false` to ensure Branch retrieves deep links from Facebook's deferred deep linking API.<br><br>This requires adding your Facebook App Secret to Branch. Learn more in our [guide](https://help.branch.io/marketer-hub/meta-app-install-ads.md#setup). | Optional |
| `install_referrer_extras` | String | Populate with the value of the full Android Play Store Install Referrer URL, if available.<br><br>Only include in the app's first session. | Optional, Android only |
| `google_search_install_referrer` | String | Populate with the value of the `google_search_install_referrer` query parameter on the `referrerUrl` from the [Google Install Referrer](https://developer.android.com/google/play/installreferrer/library), if available.<br><br>Only include in the app's first session. | Optional, Android only |
| `clicked_referrer_ts` | Long | The referrer click timestamp collected from the [Play Install Referrer library](https://developer.android.com/google/play/installreferrer/library), if available.<br><br>Only include in the app's first session. | Optional, Android only |
| `install_begin_ts` | Long | The install begin timestamp collected from the [Play Install Referrer library](https://developer.android.com/google/play/installreferrer/library), if available.<br><br>Only include in the app's first session. | Optional, Android only |
| `apple_attribution_token` | String | The attribution token used for Apple Search Ads. Used to call the Apple Search Ads Attribution API.<br><br>This token has a 24hr TTL, so it must be sent to Branch within that same time frame to be used for attribution. | Optional, iOS only |
| `search_ad_encoded` | String | The Base64-encoded string of the entire response from the [Apple Search Ads API](https://developer.apple.com/documentation/adservices/aaattribution?language=objc). | **Deprecated** |
| `first_session` | Boolean | If this parameter is set to `true`, Branch checks whether we have previously seen the user download the app. If we have seen the user before, we mark it as a `REINSTALL`. If we have not, we mark it as an `INSTALL`.<br><br>If this parameter is set to `false`, Branch counts the session as an `OPEN`. | Optional |
| `server_to_server_identity` | Boolean | Setting to `true` lets you set a `randomized_bundle_token` property (see below).<br><br>Do not set this property in the request if you don't plan to use this feature. | Optional |
| `randomized_bundle_token` | Boolean | If `server_to_server_identity` is set to `true`, Branch returns a new identity value in any request that does not set `randomized_bundle_token`.<br><br>After the first request, the property **must be hardcoded** with the `randomized_bundle_token` received in the first network response.<br><br>Failure to return this value in subsequent requests severely limits the ability to connect different events to a user. | Optional |
| `identity` | String | If `server_to_server_identity` is set to `true`, you can use this property to associate a custom user ID with Branch's anonymous ID.<br><br>You should never include personal information here, and all values should be encrypted before being passed to Branch. Learn more about [PII](https://help.branch.io/account-hub/best-practices-to-minimize-data-sent-to-branch.md#developer-identity). | Optional |
| `tracking_disabled` | Boolean | If set to `true`, Branch will not store any data from this app session.<br><br>The network response can still return deep link data for processing, but no information will be stored afterward. | Optional |
| `disable_ad_network_callouts` | Boolean | If set to `true`, you can use Branch to selectively remove sessions with this flag from being sent to ad networks. Learn more about [filtering ad network data](https://help.branch.io/developer-hub/filtering-ad-network-data.md). | Optional |
| `local_url` | String | Populate with a Branch web URL that is present on the Clipboard on first open, if available.<br><br>Otherwise, do not include with request. | Optional, iOS only ([NativeLink](https://www.branch.io/resources/blog/nativelink-solution-to-challenges-caused-by-ios-15/)) |
| `referrer_gclid` | String | Populate with the value of `gclid` from Android Play Store Install Referrer URL.<br><br>Used for tracking downstream events on Google AdWords when the user opts out on Android 12+ devices.<br><br>If missing, do not include in request. | Optional, Android only |
| `gbraid` | String | Populate with the value of `gbraid` from the referring URL/URI for the app session.<br><br>Used for tracking downstream events on Google AdWords when users are opted out of ATT.<br><br>If missing, do not include in request. | Optional, iOS only |
| `custom_param_1` | String | A custom parameter slot you can attach to your `OPEN`, `INSTALL`, or other Branch Event metadata.<br><br>Use it to visualize and analyze Branch aggregate data in Branch reports and exports. | No |
| `custom_param_2` | String | A custom parameter slot you can attach to your `OPEN`, `INSTALL`, or other Branch Event metadata.<br><br>Use it to visualize and analyze Branch aggregate data in Branch reports and exports. | No |
| `custom_param_3` | String | A custom parameter slot you can attach to your `OPEN`, `INSTALL`, or other Branch Event metadata.<br><br>Use it to visualize and analyze Branch aggregate data in Branch reports and exports. | No |
| `dma_eea` | Bool | Whether European regulations, including the DMA, apply to this user and conversion.<br><br>Set to `true` if the user is **included** in European Union regulations. For example, if the user is located within the EEA, they are within the scope of the DMA.<br><br>Set to `false` if the user is considered **excluded** from European Union regulations. | **Required** if EU regulations apply to this user<br><br>**Warning**: Failure to include user consent signals may result in attribution or campaign performance degradation |
| `dma_ad_personalization` | Bool | Whether the end user has granted or denied ads personalization consent.<br><br>Set to `true` if the user has **granted** consent for ads personalization.<br><br>Set to `false` when the user has **denied** consent for ads personalization. | **Required** if `dma_eea` is set to `true` (that is, EU regulations apply to this user)<br><br>**Warning**: Failure to include user consent signals may result in attribution or campaign performance degradation |
| `dma_ad_user_data` | Bool | Whether the end user has granted or denied consent for 3P transmission of user-level data for ads.<br><br>Set to `true` if the user has **granted** consent for 3P transmission of user-level data for ads.<br><br>Set to `false` if the user has **denied** consent for 3P transmission of user-level data for ads. | **Required** if `dma_eea` is set to `true` (that is, EU regulations apply to this user)<br><br>**Warning**: Failure to include user consent signals may result in attribution or campaign performance degradation |

#### Response info

When you make a request to the Attribution API, Branch can attribute the app session to a deep link click.

Regardless of whether the session is attributed, the API always returns a `200` response with some contextual data included in the JSON payload.

If the session was attributed to a deep link click, this payload includes the link's deep link data. You can use this data in your in-app logic and to execute your deep linking user experience.

**Response body parameters**

Below is a partial list of the possible values you may receive in a response:

| Parameter | Description |
| --- | --- |
| `randomized_bundle_token` | If you set `server_to_server_identity` to `true` in your request, you must ensure the value returned here is used in the `randomized_bundle_token` property of all requests moving forward for that device. |
| `+clicked_branch_link` | This tells you if the current app session was sourced via a Branch Link.<br><br>You can use this as a conditional trigger that dictates whether you use Branch-specific routing logic or other deep link routing logic.<br><br>This value is nested within the `data` object in the response. |
| `+non_branch_link` | If a non-Branch deep link opened your app (that is, a Universal Link), you can retrieve that link from this key.<br><br>This value is nested within the `data` object in the response. |
| `+is_first_session` | This is `true` if Branch has never seen this app installed on the user's device before.<br><br>This value is nested within the `data` object in the response. |
| `+match_guaranteed` | This is `true` if Branch was able to match the app session to the browser click with 100% certainty.<br><br>You can use this as a conditional trigger for use cases where you have zero risk threshold for a false positive. You should **not** use this in most instances.<br><br>Not applicable to SAN-attributed installs.<br><br>This value is nested within the `data` object in the response. |
| `$canonical_url` | This contains a web URL that you can use for deep link routing. If your app was already set up to route off Universal Links or Android App Links, you can pass this value into that pre-existing routing logic.<br><br>This value is nested within the `data` object in the response. |
| `$deeplink_path` | This contains a URI relative path that you can use for deep link routing. If your app was already set up to route off URI schemes, you can pass this value into that pre-existing routing logic.<br><br>This value is nested within the `data` object in the response. |

#### Examples

**Example requests**

**cURL (iOS)**

```curl
curl -v -d '{
    "branch_key": "key_live_xxx",
    "branch_secret": "secret_live_xxx",
    "server_to_server": true,
    "app_version": "1.12.4",
    "os": "iOS",
    "os_version": "10.0",
    "model": "iPhone",
    "screen_height": 2208,
    "screen_width": 1242,
    "facebook_app_link_checked": false,
    "user_agent": "{FULL_USER_AGENT_HERE}",
    "hardware_id": "000AAAA-0A0A-000AAA-AAAA000",
    "hardware_id_type": "idfa",
    "ios_vendor_id": "000AAAA-0A0A-000AAA-AAAA000",
    "is_hardware_id_real": true,
    "ad_tracking_enabled": true,
    "custom_param_1": "Parameter 1",
    "custom_param_2": "Parameter 2",
    "custom_param_3": "Parameter 3",
    "dma_eea": true,
    "dma_ad_personalization": true,
    "dma_ad_user_data": true
}' "https://api2.branch.io/v1/open" -H "X-IP-Override: 1.2.3.4"
```

**cURL (Android)**

```curl
curl -v -d '{
    "branch_key": "key_live_xxx",
    "branch_secret": "secret_live_xxx",
    "server_to_server": true,
    "app_version": "1.12.4",
    "os": "Android",
    "os_version": 26,
    "model": "SM-G960U1",
    "screen_height": 2076,
    "screen_width": 1080,
    "facebook_app_link_checked": false,
    "user_agent": "{FULL_USER_AGENT_HERE}",
    "hardware_id": "00aa0a000a0a0",
    "google_advertising_id": "000AAAA-0A0A-000AAA-AAAA000",
    "advertising_ids": {
        "oaid": "000AAAA-0A0A-000AAA-AAAA000"
    },
    "google_search_install_referrer": "referrer_value_here",
    "clicked_referrer_ts": 1574699946,
    "install_begin_ts": 1574699955,
    "is_hardware_id_real": true,
    "ad_tracking_enabled": true,
    "custom_param_1": "Parameter 1",
    "custom_param_2": "Parameter 2",
    "custom_param_3": "Parameter 3",
    "dma_eea": true,
    "dma_ad_personalization": true,
    "dma_ad_user_data": true
}' "https://api2.branch.io/v1/open" -H "X-IP-Override: 1.2.3.4"
```

**Example responses**

Organic response:

```json
{
  "session_id": "xxxx",
  "randomized_device_token": "xxxx",
  "link": "https://bnc.lt/j/adsf",
  "data": "{\"+clicked_branch_link\":false,\"+is_first_session\":false}"
}
```

Organic response with `sever_to_server_identity` set to `true` in the request:

```json
{
  "session_id": "xxxx",
  "randomized_bundle_token": "xxxx",
  "identity": "xxxx",
  "randomized_device_token": "xxxx",
  "link": "https://bnc.lt/j/adsf",
  "data": "{\"+clicked_branch_link\":false,\"+is_first_session\":false}"
}
```

Response when a session was started by a non-Branch deep link:

```json
{
  "session_id": "823602214081710808",
  "data": "{\"+non_branch_link\":\"https://branch.io/\",\"+clicked_branch_link\":false,\"+is_first_session\":false}",
  "randomized_device_token": "823601870295755491"
}
```

Response when a session was started by a Branch Link:

```json
{
  "randomized_device_token": "823600311503935224",
  "link": "https://example.app.link/X7OsnWv9TF",
  "session_id": "429691081177874743",
  "data": "{
    "$canonical_url": "https://example.com/home?utm_campaign=test",
    "$desktop_url": "http://example.com/home",
    "$og_description": "My Content Description",
    "$og_image_url": "http://lorempixel.com/200/200/",
    "$og_title": "46D6D28E-0390-40E4-A856-BD74F34D24C8",
    "+click_timestamp": 1503684563,
    "+clicked_branch_link": true,
    "+is_first_session": false,
    "+match_guaranteed": true,
    "custom_param_1": "blue",
    "dma_eea": true,
    "dma_ad_personalization": true,
    "dma_ad_user_data": true,
    "~campaign": "new launch",
    "~channel": "facebook",
    "~creation_source": 3,
    "~feature": "sharing",
    "~id": 429691043152332059,
    "~referring_link": "https://example.app.link/X7OsnWv9TF",
    "~stage": "new person",
    "~tags": ["one","two"]
  }"
}
```

## Track downstream events

Every time you call the `v1/open` Attribution API endpoint, the API tracks an `INSTALL`, `REINSTALL`, or `OPEN` event.

To track other events, you need to use the relevant API instructions for the type of event you want to track:

- [Commerce Events](https://help.branch.io/developer-hub/track-branch-events.md#track-commerce-events) (such as `PURCHASE` and `ADD_TO_CART`)
- [Content Events](https://help.branch.io/developer-hub/track-branch-events.md#track-content-events) (such as `SEARCH` and `VIEW_ITEM`)
- [Lifecycle Events](https://help.branch.io/developer-hub/track-branch-events.md#track-lifecycle-events) (such as `SUBSCRIBE` or `LOGIN`)
- [Custom Events](https://help.branch.io/developer-hub/track-branch-events.md#track-custom-events) (all other events you want to track)

When tracking these downstream conversion events, address the following items:

1. If you make a request from the device, Branch automatically retrieves the IP address from the request. If you make the request from a server, you must set the user's IP address via the `X-IP-Override` header.
2. Set the device's user agent in the `user_data.user_agent` request body parameter.
3. For events that occur in your iOS app, populate the device ID with the [IDFA](https://developer.apple.com/documentation/adsupport/asidentifiermanager/1614151-advertisingidentifier) (or fall back to the [IDFV](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor)). For Android apps, populate the device ID with the [GAID](https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient) (or fall back to [android_id](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID)).
4. For events that occur in your web app, retrieve a browser fingerprint via the [Branch Web SDK](https://help.branch.io/developer-hub/web-full-reference.md). Include this in the event call.
5. Populate the `developer_identity` property whenever a persistent user ID is available. View our [guide](https://help.branch.io/account-hub/best-practices-to-minimize-data-sent-to-branch.md#developer-identity) on best practices for user IDs.
