---
openapi: 3.0.3
info:
  title: Braze REST API – Identify users
  description: |
    Identify an alias-only, email-only, or phone-only profile by associating it
    with an `external_id`.

    One of `aliases_to_identify`, `emails_to_identify`, or
    `phone_numbers_to_identify` is required in each request.
  version: 1.0.0
  contact:
    name: Braze Support
    url: https://www.braze.com/docs/braze_support/
  license:
    name: Braze Documentation
    url: https://www.braze.com/docs/api/home/
servers:
  - url: https://rest.iad-01.braze.com
    description: US-01
  - url: https://rest.iad-02.braze.com
    description: US-02
  - url: https://rest.iad-03.braze.com
    description: US-03
  - url: https://rest.iad-04.braze.com
    description: US-04
  - url: https://rest.iad-05.braze.com
    description: US-05
  - url: https://rest.iad-06.braze.com
    description: US-06
  - url: https://rest.iad-07.braze.com
    description: US-07
  - url: https://rest.iad-08.braze.com
    description: US-08
  - url: https://rest.us-10.braze.com
    description: US-10
  - url: https://rest.fra-01.braze.eu
    description: EU-01
  - url: https://rest.fra-02.braze.eu
    description: EU-02
  - url: https://rest.au-01.braze.com
    description: AU-01
  - url: https://rest.id-01.braze.com
    description: ID-01
  - url: https://rest.jp-01.braze.com
    description: JP-01
  - url: https://rest.kr-01.braze.com
    description: KR-01
tags:
  - name: User data
    description: Identify, track, and manage your users.
security:
  - BearerAuth: []
paths:
  /users/identify:
    post:
      summary: Identify users
      description: |
        Associates anonymous profiles with identified profiles using an
        `external_id`. Requires a REST API key with the `users.identify`
        permission.

        ## Prerequisites

        To use this endpoint, you'll need an [API key]({{site.baseurl}}/api/basics) with the `users.identify` permission.

        ## Rate limit

        We apply a shared rate limit of 20,000 requests per minute to this endpoint. This rate limit is shared with the `/users/delete`, `/users/alias/new`, `/users/merge`, and `/users/alias/update` endpoints, as documented in [API rate limits]({{site.baseurl}}/api/api_limits/).

        ## Request body

        ```
        Content-Type: application/json
        Authorization: Bearer YOUR_REST_API_KEY
        ```

        ```json
        {
           "aliases_to_identify" : (required, array of alias to identify objects),
           "emails_to_identify": (optional, array of alias to identify objects) User emails to identify,
           "phone_numbers_to_identify": (optional, array of alias to identify objects) User phone numbers to identify,
        },
        ```

        ## Request parameters

        You can add up to 50 user aliases per request. You can associate multiple additional user aliases with a single `external_id`.

        **Important:**
        One of the following is required: `aliases_to_identify`, `emails_to_identify`, or `phone_numbers_to_identify` per request. For example, you can use this endpoint to identify users by email by using `emails_to_identify` in your request.

        | Parameter                   | Required | Data Type                           | Description                                                                                                                                                                 |
        |-----------------------------|----------|-------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
        | `aliases_to_identify`       | Required | Array of aliases to identify object | See [alias to identify object]({{site.baseurl}}/api/objects_filters/aliases_to_identify) and [user alias object]({{site.baseurl}}/api/objects_filters/user_alias_object). |
        | `emails_to_identify`        | Required | Array of aliases to identify object | Required if `email` is specified as the identifier. Email addresses to identify users. See [Identifying users by email](#identifying-users-by-email-addresses-and-phone-numbers).                                                                                                              |
        | `phone_numbers_to_identify` | Required | Array of aliases to identify object | Phone numbers to identify users.                                                                                                                                            |

        ### Identifying users by email addresses and phone numbers

        If an email address or phone number is specified as an identifier, you must also include `prioritization` in the identifier.

        The `prioritization` must be an array specifying which user to merge if there are multiple users found. `prioritization` is an ordered array, meaning if more than one user matches from a prioritization, then merging does not occur.

        The allowed values for the array are:

        - `identified`
        - `unidentified`
        - `most_recently_updated` (refers to prioritizing the most recently updated user)
        - `least_recently_updated` (refers to prioritizing the least recently updated user)

        Only one of the following options may exist in the prioritization array at a time:

        - `identified` refers to prioritizing a user with an `external_id`
        - `unidentified` refers to prioritizing a user without an `external_id`

        **Note:**
        A merge does not occur if the email address or phone number matches multiple users. This includes cases where one of those users has the same `external_id` as the one specified in the request. In these cases, the endpoint returns `"message": "success"`, but the user profiles are not combined. To avoid this, verify that the email address or phone number is associated only with unidentified users before calling this endpoint.

        ## Example request

        ```
        curl --location --request POST 'https://rest.iad-01.braze.com/users/identify' \
        --header 'Content-Type: application/json' \
        --header 'Authorization: Bearer YOUR_REST_API_KEY' \
        --data-raw '{
          "aliases_to_identify": [
            {
              "external_id": "external_identifier",
              "user_alias": {
                  "alias_name": "example_alias",
                  "alias_label": "example_label"
              }
            }
          ],
          "emails_to_identify": [
            {
              "external_id": "external_identifier_2",
              "email": "john.smith@example.com",
              "prioritization": ["unidentified", "most_recently_updated"]
            }
          ]
        }'
        ```

        ### Case sensitivity

        The `alias_name` field is case-sensitive. A request that returns a `201` status code only confirms the request syntax was valid—it does not confirm the alias was matched. If the capitalization of `alias_name` in your request doesn't exactly match the alias stored on the user profile, the operation will silently fail and the `external_id` won't be assigned. For example, if the stored alias is `JimJones@example.com`, a request with `jimjones@example.com` will return success but produce no result.

        **Tip:**
        For more information on `alias_name` and `alias_label`, check out our [user aliases]({{site.baseurl}}/user_guide/data/unification/user_data/user_profile_lifecycle) documentation.

        ### Why does my identify request return success but the profile did not merge?

        `201 Created` with `message: success` means Braze accepted the request. It does not guarantee that every alias or email in the payload matched an existing profile—case mismatches on `alias_name`, duplicate profiles, or Braze prioritization rules can result in no visible merge even though the call succeeded. Verify that `alias_name` casing exactly matches stored values, check for duplicate profiles with [`/users/merge`]({{site.baseurl}}/api/endpoints/user_data/post_users_merge/), and review [`prioritization`](#identifying-users-by-email-addresses-and-phone-numbers) when using `emails_to_identify`.

        ## Response

        ```json
        {
            "aliases_processed": 1,
            "message": "success"
        }
        ```

        ## How it works

        Calling `/users/identify` combines a user profile that is identified by an alias (alias-only profile), email address (email-only profile), or phone number (phone number-only profile) with a user profile that has an `external_id` (identified profile), then removes the alias-only profile.

        Identifying a user requires an `external_id` to be included in the following objects:

        - `aliases_to_identify`
        - `emails_to_identify`
        - `phone_numbers_to_identify`

        If there isn't a user with that `external_id`, the `external_id` is added to the aliased user's record, and the user is considered identified. Users can have only one alias for a specific label. If a user already exists with the `external_id` and has an existing alias with the same label as the alias-only profile, then the user profiles are not combined.

        **Tip:**
        To prevent unexpected loss of data when identifying users, we highly recommend that you first refer to [data collection best practices]({{site.baseurl}}/collection_best_practices) to learn about capturing user data when alias-only user information is already present.

        ### Merging behavior

        By default, this endpoint merges the following list of fields found **exclusively** on the anonymous user to the identified user.

        - First name
        - Last name
        - Email
        - Gender
        - Date of birth
        - Phone number
        - Time zone
        - Home city
        - Country
        - Language
        - Session count (the sum of sessions from both profiles)
        - Date of first session (Braze picks the earlier date of the two dates)
        - Date of last session (Braze picks the later date of the two dates)
        - Custom attributes
        - Custom event and purchase event data
        - Custom event and purchase event properties for "X times in Y days" segmentation (where X<=50 and Y<=30)
        - Segmentable custom events summary
          - Event count (the sum from both profiles)
          - Event first occurred (Braze picks the earlier date of the two dates)
          - Event last occurred (Braze picks the later date of the two dates)
        - In-app purchase total in cents (the sum from both profiles)
        - Total number of purchases (the sum from both profiles)
        - Date of first purchase (Braze picks the earlier date of the two dates)
        - Date of last purchase (Braze picks the later date of the two dates)
        - App summaries
        - Last_X_at fields (Braze updates the fields if the orphaned profile fields are more recent)
        - Campaign summaries (Braze picks the most recent date fields)
        - Workflow summaries (Braze picks the most recent date fields)
        - Message and message engagement history
        - Custom event and purchase event count and first date and last date timestamps
          - These merged fields update "for X events in Y days" filters. For purchase events, these filters include "number of purchases in Y days" and "money spent in last Y days".
        - Session data if the app exists on both user profiles
          - For example, if our target user doesn't have an app summary for "ABCApp" but our original user does, the target user has the "ABCApp" app summary on their profile after the merge.

        ## Response status codes

        The following table lists the responses for this endpoint, the error message you may receive, and how to resolve it.

        | Status code | Meaning | Error message | How to resolve |
        | --- | --- | --- | --- |
        | `201 Created` | The request succeeded and the users were identified. | `success` | No action needed. |
        | `400 Bad Request` | No identify input was provided. | `No data received for 'aliases_to_identify', 'emails_to_identify', or 'phone_numbers_to_identify' (at least one required)` | Include at least one of `aliases_to_identify`, `emails_to_identify`, or `phone_numbers_to_identify`. |
        | `400 Bad Request` | An identify input isn't an array. | `If using 'aliases_to_identify', 'emails_to_identify', or 'phone_numbers_to_identify', they must be arrays` | Pass each identify input as an array. |
        | `400 Bad Request` | More than 50 users were provided. | `At most 50 total users can be identified at once` | Identify 50 or fewer users per request. |
        | `401 Unauthorized` | The REST API key is missing, malformed, or sent to the wrong REST endpoint. | `Invalid API key` | Send the key as `Authorization: Bearer YOUR_REST_API_KEY` to the correct [REST endpoint]({{site.baseurl}}/api/basics/#endpoints). For more causes, see [Errors and responses]({{site.baseurl}}/api/errors/#fatal-errors). |
        | `403 Access Denied` | The REST API key doesn't have the required permission. | `Access Denied` | Use a REST API key that has the `users.identify` permission. |
        | `429 Rate Limited` | You exceeded the rate limit for this endpoint. | `Over rate limit` | Slow your request rate and retry with exponential backoff. See [API rate limits]({{site.baseurl}}/api/api_limits/). |
        | `5XX Internal Server Error` | An unexpected error occurred on the Braze server. | `Internal Server Error` | Retry with exponential backoff. If the error persists, contact [Support]({{site.baseurl}}/braze_support/). |
      operationId: identifyUsers
      tags:
        - User data
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IdentifyUsersRequest'
            examples:
              aliases:
                summary: Identify by alias
                value:
                  aliases_to_identify:
                    - external_id: user_123
                      user_alias:
                        alias_name: anonymous_abc
                        alias_label: temporary_id
              emails:
                summary: Identify by email
                value:
                  emails_to_identify:
                    - external_id: user_456
                      email: jane.doe@example.com
                      prioritization:
                        - unidentified
                        - most_recently_updated
      responses:
        "201":
          description: Request accepted and queued for processing.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IdentifyUsersResponse'
              examples:
                success:
                  value:
                    aliases_processed: 1
                    message: success
        "400":
          description: Invalid request body.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                invalid_request:
                  value:
                    message: "One of aliases_to_identify, emails_to_identify, or phone_numbers_to_identify is required"
        "401":
          description: Unauthorized - API key is missing, invalid, or lacks `users.identify`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                unauthorized:
                  value:
                    message: invalid_api_key
        "429":
          description: Rate limit exceeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                rate_limited:
                  value:
                    message: rate_limited
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: REST API key
      description: |
        REST API keys are created in the Braze dashboard at **Settings -> APIs and
        Identifiers -> API Keys**. The key must include `users.identify`.
  schemas:
    UserAlias:
      type: object
      required: [alias_name, alias_label]
      properties:
        alias_name:
          type: string
        alias_label:
          type: string
    IdentifyAlias:
      type: object
      required: [external_id, user_alias]
      properties:
        external_id:
          type: string
        user_alias:
          $ref: '#/components/schemas/UserAlias'
    IdentifyEmail:
      type: object
      required: [external_id, email, prioritization]
      properties:
        external_id:
          type: string
        email:
          type: string
          format: email
        prioritization:
          type: array
          items:
            type: string
            enum: [identified, unidentified, most_recently_updated, least_recently_updated]
    IdentifyPhone:
      type: object
      required: [external_id, phone_number, prioritization]
      properties:
        external_id:
          type: string
        phone_number:
          type: string
        prioritization:
          type: array
          items:
            type: string
            enum: [identified, unidentified, most_recently_updated, least_recently_updated]
    IdentifyUsersRequest:
      type: object
      properties:
        aliases_to_identify:
          type: array
          maxItems: 50
          items:
            $ref: '#/components/schemas/IdentifyAlias'
        emails_to_identify:
          type: array
          maxItems: 50
          items:
            $ref: '#/components/schemas/IdentifyEmail'
        phone_numbers_to_identify:
          type: array
          maxItems: 50
          items:
            $ref: '#/components/schemas/IdentifyPhone'
    IdentifyUsersResponse:
      type: object
      properties:
        aliases_processed:
          type: integer
        message:
          type: string
          example: success
    ErrorResponse:
      type: object
      properties:
        message:
          type: string
        errors:
          type: array
          items:
            type: string
