# Identify API in Mobile SDKs


This guide explains how to use the `identify` API in the RudderStack [Android (Kotlin)]({{< ref "sources/event-streams/sdks/kotlin-sdk/" >}}) and [iOS (Swift)]({{< ref "sources/event-streams/sdks/swift-sdk/" >}}) SDKs.

## Overview

The RudderStack Android (Kotlin) and iOS (Swift) SDKs provide an [`identify`]({{< ref "event-spec/standard-events/identify.md" >}}) API that lets you identify a user and associate them to their actions. It also lets you record any traits about them like their name, email, etc.

{{< info >}}
Once you make the identify call, the SDK persists the user information and passes it to the subsequent calls.
{{< /info >}}

## Android (Kotlin)

The `identify` method definition in the Android (Kotlin) SDK is as follows:

{{< tabs tabTotal="2" >}}
{{% tab tabName="Default invocation" %}}
```kotlin
analytics.identify(
    userId = "<userId>",
    traits = buildJsonObject {
        put("key", "value")
    },
    options = RudderOption(),
)
```

The corresponding Java snippet is shown below:

```java
HashMap<String, Object> traits = new HashMap<>();
traits.put("key", "value");

analytics.identify("<userId>", traits, new RudderOption());
```
{{% /tab %}}
{{% tab tabName="Alternate invocations" %}}
```kotlin
// Identify event with userId
analytics.identify(userId = "<userId>")

// Identify event with traits
analytics.identify(
    traits = buildJsonObject {
        put("key", "value")
    },
)

// Identify event with userId and traits
analytics.identify(
    userId = "<userId>",
    traits = buildJsonObject {
        put("key", "value")
    },
)

// Identify event with userId and options
analytics.identify(
    userId = "<userId>",
    options = RudderOption(
        customContext = buildJsonObject {
            put("key", "value")
        },
        integrations = buildJsonObject {
            put("Amplitude", true)
            put("INTERCOM", buildJsonObject {
                put("lookup", "field")
            })
        },
        externalIds = listOf(
            ExternalId(type = "<id_type>", id = "<value>"),
        ),
    ),
)

// Identify event with traits and options
analytics.identify(
    traits = buildJsonObject {
        put("key", "value")
    },
    options = RudderOption(
        customContext = buildJsonObject {
            put("key", "value")
        },
        integrations = buildJsonObject {
            put("Amplitude", true)
            put("INTERCOM", buildJsonObject {
                put("lookup", "field")
            })
        },
        externalIds = listOf(
            ExternalId(type = "<id_type>", id = "<value>"),
        ),
    ),
)
```
{{% /tab %}}
{{< /tabs >}}

### Method signature {#method-signature-kotlin}

The below table describes the `identify` method signature in detail:

| Field | Data type | <div style="width:350px">Description</div> |
| :----| :------| :-----|
| `userId` <br /><span style="color: #4D4DFF;font-size:12px;">Required, if `traits` is not present</span> | String | Unique user identifier. When provided, RudderStack prefers this field over `anonymousId` while sending data to the destinations. |
| `traits` <br /><span style="color: #4D4DFF;font-size:12px;">Required, if `userId` is not present</span> | Traits | Contains the user traits or the properties associated with `userId` such as `email`, `address`, etc. See [Identify traits]({{< ref "event-spec/standard-events/identify.md#identify-traits" >}}) for more information. <br /><br />Note that:<br /><br /><ul><li>RudderStack stores the traits as `context.traits` in the final event object.</li><li>The `traits` type in Java is `Map<String, Object>`.</li></ul> |
| `options` | RudderOption | Additional event options. |

### Example {#example-kotlin}

A sample `identify` event sent from the Android (Kotlin) SDK is shown below:

{{< tabs tabTotal="2" >}}
{{% tab tabName="Kotlin" %}}
```kotlin
analytics.identify(
    userId = "1hKOmRA4GRlm",
    traits = buildJsonObject {
        put("city", "New Orleans")
    },
    options = RudderOption(
        customContext = buildJsonObject {
            put("key", "value")
        },
        integrations = buildJsonObject {
            put("Amplitude", true)
            put("INTERCOM", buildJsonObject {
                put("lookup", "phone")
            })
        },
        externalIds = listOf(
            ExternalId(type = "brazeExternalId", id = "value1234"),
        ),
    ),
)
```
{{% /tab %}}
{{% tab tabName="Java" %}}
```java
HashMap<String, Object> traits = new HashMap<>();
traits.put("city", "New Orleans");

Map<String, Object> customContext = new HashMap<>();
customContext.put("key", "value");

Map<String, Object> nestedIntegrations = new HashMap<>();
nestedIntegrations.put("lookup", "phone");
Map<String, Object> integrations = new HashMap<>();
integrations.put("Amplitude", true);
integrations.put("INTERCOM", nestedIntegrations);

List<ExternalId> externalIds = new ArrayList<>();
externalIds.add(new ExternalId("brazeExternalId", "value1234"));

RudderOption option = new RudderOptionBuilder()
        .setIntegrations(integrations)
        .setExternalId(externalIds)
        .setCustomContext(customContext)
        .build();

analytics.identify("1hKOmRA4GRlm", traits, option);
```
{{% /tab %}}
{{< /tabs >}}

## iOS (Swift)

The `identify` method definition in the iOS (Swift) SDK is as follows:

{{< tabs tabTotal="2" >}}
{{% tab tabName="Default invocation" %}}
```swift
analytics.identify(
    userId: "User 1",
    traits: [
        "key-1": "value-1"
    ],
    options: RudderOption()
)
```

{{< warning >}}
Make sure to include the `import RudderStackAnalytics` statement before making the call.
{{< /warning >}}

The corresponding Objective-C snippet is shown below:

```objectivec
[analytics identify:@"User 1"
          traits:@{
              @"key-1": @"value-1"
          }
          options:[[RSSOptionBuilder new] build]];
```

{{< info >}}
`RSSOptionBuilder` is an Objective-C–only helper class. It uses the builder pattern to create an `RSSOption` instance and lets you set custom context, configure integrations, and attach external IDs in a structured way.
{{< /info >}}

{{% /tab %}}
{{% tab tabName="Alternate invocations" %}}
```swift
// Identify event with userId
analytics.identify(userId: "User 1")

// Identify event with traits
analytics.identify(
    traits: [
        "key-1": "value-1"
    ]
)

// Identify event with userId and traits
analytics.identify(
    userId: "User 1",
    traits: [
        "key-1": "value-1"
    ]
)

// Identify event with userId and options
analytics.identify(
    userId: "User 1",
    options: RudderOption(
        integrations: [
            "Amplitude": true,
            "INTERCOM": [
                "lookup": "phone"
            ]
        ],
        customContext: [
            "key-1": "value-1"
        ],
        externalIds: [
            ExternalId(type: "brazeExternalId", id: "value1234")
        ]
    )
)

// Identify event with traits and options
analytics.identify(
    traits: [
        "key-1": "value-1"
    ],
    options: RudderOption(
        integrations: [
            "Amplitude": true,
            "INTERCOM": [
                "lookup": "phone"
            ]
        ],
        customContext: [
            "key-1": "value-1"
        ],
        externalIds: [
            ExternalId(type: "brazeExternalId", id: "value1234")
        ]
    )
)
```

The corresponding Objective-C snippet is shown below:

```objectivec
// Identify event with userId
[analytics identify:@"User 1"];

// Identify event with traits
[analytics identifyWithTraits:@{
              @"key-1": @"value-1"
          }];

// Identify event with userId and traits
[analytics identify:@"User 1"
          traits:@{
              @"key-1": @"value-1"
          }];

// Identify event with userId and options
RSSOptionBuilder *optionBuilder = [[RSSOptionBuilder alloc] init];

[optionBuilder setCustomContext:@{
    @"key-1": @"value-1"
}];

[optionBuilder setIntegrations:@{
    @"Amplitude": @YES,
    @"INTERCOM": @{
        @"lookup": @"phone"
    }
}];

[optionBuilder setExternalIds:@[
    [[RSSExternalId alloc] initWithType:@"brazeExternalId" id:@"value1234"]
]];

[analytics identify:@"User 1"
          options:[optionBuilder build]];

// Identify event with traits and options
[analytics identifyWithTraits:@{
              @"key-1": @"value-1"
          }
          options:[optionBuilder build]];
```

{{% /tab %}}
{{< /tabs >}}

### Method signature {#method-signature-swift}

The below table describes the `identify` method signature in detail:

| Field | Data type | <div style="width:350px">Description</div> |
| :----| :------| :-----|
| `userId` <br /><span style="color: #4D4DFF;font-size:12px;">Required, if `traits` is not present</span> | String | Unique user identifier. When provided, RudderStack prefers this field over `anonymousId` while sending data to the destinations. |
| `traits` <br /><span style="color: #4D4DFF;font-size:12px;">Required, if `userId` is not present</span> | Properties | Contains the user traits or the properties associated with `userId` such as `email`, `address`, etc. See [Identify traits]({{< ref "event-spec/standard-events/identify.md#identify-traits" >}}) for more information. |
| `options` | RudderOption | Additional event options. |

### Example {#example-swift}

A sample `identify` event sent from the Swift SDK is shown below:

{{< tabs tabTotal="2" >}}
{{% tab tabName="Swift" %}}
```swift
analytics.identify(
    userId: "User 1",
    traits: [
        "key-1": "value-1"
    ],
    options: RudderOption(
        integrations: [
            "Amplitude": true,
            "INTERCOM": [
                "lookup": "phone"
            ]
        ],
        customContext: [
            "key-1": "value-1"
        ],
        externalIds: [
            ExternalId(type: "brazeExternalId", id: "value1234")
        ]
    )
)
```
{{% /tab %}}
{{% tab tabName="Objective-C" %}}
```objectivec
RSSOptionBuilder *optionBuilder = [[RSSOptionBuilder alloc] init];

[optionBuilder setCustomContext:@{
    @"key-1": @"value-1"
}];

[optionBuilder setIntegrations:@{
    @"Amplitude": @YES,
    @"INTERCOM": @{
        @"lookup": @"phone"
    }
}];

[optionBuilder setExternalIds:@[
    [[RSSExternalId alloc] initWithType:@"brazeExternalId" id:@"value1234"]
]];

[analytics identify:@"User 1"
          traits:@{
              @"key-1": @"value-1"
          }
          options:[optionBuilder build]];
```
{{% /tab %}}
{{< /tabs >}}

## Implicit `reset` when existing `userId` changes

When you call `identify` with a `userId` that differs from the currently persisted `userId`, the SDK internally calls [`reset()`]({{< ref "sources/event-streams/sdks/mobile-sdk-apis/reset.md" >}}) before updating the user identity — this clears the previous user data and refreshes the session.

Calling `identify` on an anonymous user (no prior `userId`) **does not** trigger a reset.

See the [`reset` API documentation]({{< ref "sources/event-streams/sdks/mobile-sdk-apis/reset.md#implicit-reset-via-identify" >}}) for more information on the implicit reset behavior and how you can preserve specific data during a user switch.

<br />

