> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/mixpanel/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# User Profiles

> Manage user profile data and properties

# User Profiles

User profiles store persistent information about your users. Use the Engage API to create and update user profiles with various operations.

## Base URL

```
https://api.mixpanel.com/engage
```

## Authentication

User profile updates use your project token for authentication.

## Set Property

Set one or more properties on a user profile. Creates the profile if it doesn't exist, or updates existing properties.

<ParamField query="ip" type="string">
  If set to `1`, uses the request IP for geolocation
</ParamField>

<ParamField query="strict" type="string">
  Enable strict mode for validation
</ParamField>

<ParamField query="verbose" type="string">
  Return detailed response instead of `1` or `0`
</ParamField>

### Request Body

<ParamField body="$token" type="string" required>
  Your project token
</ParamField>

<ParamField body="$distinct_id" type="string" required>
  The unique identifier for the user
</ParamField>

<ParamField body="$set" type="object" required>
  Object containing property names and values to set
</ParamField>

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.mixpanel.com/engage \
    --data-urlencode data='[
      {
        "$token": "YOUR_PROJECT_TOKEN",
        "$distinct_id": "user123",
        "$set": {
          "$email": "user@example.com",
          "$name": "John Doe",
          "plan": "premium",
          "credits": 100
        }
      }
    ]'
  ```

  ```python Python theme={null}
  import requests

  data = [{
      "$token": "YOUR_PROJECT_TOKEN",
      "$distinct_id": "user123",
      "$set": {
          "$email": "user@example.com",
          "$name": "John Doe",
          "plan": "premium",
          "credits": 100
      }
  }]

  response = requests.post(
      'https://api.mixpanel.com/engage',
      data={'data': json.dumps(data)}
  )

  print(response.text)  # Returns 1 for success
  ```

  ```javascript JavaScript theme={null}
  const data = [{
    $token: 'YOUR_PROJECT_TOKEN',
    $distinct_id: 'user123',
    $set: {
      $email: 'user@example.com',
      $name: 'John Doe',
      plan: 'premium',
      credits: 100
    }
  }];

  fetch('https://api.mixpanel.com/engage', {
    method: 'POST',
    body: 'data=' + encodeURIComponent(JSON.stringify(data))
  });
  ```
</CodeGroup>

***

## Set Property Once

Set properties only if they don't already exist. Useful for properties like "First Login Date" or "Signup Source".

### Request Body

<ParamField body="$token" type="string" required>
  Your project token
</ParamField>

<ParamField body="$distinct_id" type="string" required>
  The unique identifier for the user
</ParamField>

<ParamField body="$set_once" type="object" required>
  Object containing properties to set only if they don't exist
</ParamField>

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.mixpanel.com/engage \
    --data-urlencode data='[
      {
        "$token": "YOUR_PROJECT_TOKEN",
        "$distinct_id": "user123",
        "$set_once": {
          "first_login": "2024-01-15",
          "signup_source": "google_ads",
          "referrer": "friend_user456"
        }
      }
    ]'
  ```

  ```python Python theme={null}
  data = [{
      "$token": "YOUR_PROJECT_TOKEN",
      "$distinct_id": "user123",
      "$set_once": {
          "first_login": "2024-01-15",
          "signup_source": "google_ads"
      }
  }]

  response = requests.post(
      'https://api.mixpanel.com/engage',
      data={'data': json.dumps(data)}
  )
  ```
</CodeGroup>

***

## Increment Numerical Property

Increment or decrement numerical properties. Use negative values to decrement.

### Request Body

<ParamField body="$token" type="string" required>
  Your project token
</ParamField>

<ParamField body="$distinct_id" type="string" required>
  The unique identifier for the user
</ParamField>

<ParamField body="$add" type="object" required>
  Object with property names and numerical values to add. Use negative values to subtract.
</ParamField>

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.mixpanel.com/engage \
    --data-urlencode data='[
      {
        "$token": "YOUR_PROJECT_TOKEN",
        "$distinct_id": "user123",
        "$add": {
          "login_count": 1,
          "credits": 50,
          "failed_attempts": -1
        }
      }
    ]'
  ```

  ```python Python theme={null}
  data = [{
      "$token": "YOUR_PROJECT_TOKEN",
      "$distinct_id": "user123",
      "$add": {
          "login_count": 1,
          "credits": 50,
          "points_spent": -100
      }
  }]

  response = requests.post(
      'https://api.mixpanel.com/engage',
      data={'data': json.dumps(data)}
  )
  ```
</CodeGroup>

<Note>
  If the property doesn't exist, it will be created and set to the specified value (adding to 0).
</Note>

***

## Union To List Property

Add values to a list property, ensuring each value appears only once.

### Request Body

<ParamField body="$token" type="string" required>
  Your project token
</ParamField>

<ParamField body="$distinct_id" type="string" required>
  The unique identifier for the user
</ParamField>

<ParamField body="$union" type="object" required>
  Object with property names and arrays of values to add
</ParamField>

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.mixpanel.com/engage \
    --data-urlencode data='[
      {
        "$token": "YOUR_PROJECT_TOKEN",
        "$distinct_id": "user123",
        "$union": {
          "favorite_genres": ["action", "comedy"],
          "visited_pages": ["homepage", "pricing"],
          "used_features": ["export", "analytics"]
        }
      }
    ]'
  ```

  ```python Python theme={null}
  data = [{
      "$token": "YOUR_PROJECT_TOKEN",
      "$distinct_id": "user123",
      "$union": {
          "favorite_genres": ["action", "comedy"],
          "visited_pages": ["homepage", "pricing"]
      }
  }]

  response = requests.post(
      'https://api.mixpanel.com/engage',
      data={'data': json.dumps(data)}
  )
  ```
</CodeGroup>

***

## Append to List Property

Append values to a list property. Unlike union, this allows duplicate values.

### Request Body

<ParamField body="$token" type="string" required>
  Your project token
</ParamField>

<ParamField body="$distinct_id" type="string" required>
  The unique identifier for the user
</ParamField>

<ParamField body="$append" type="object" required>
  Object with property names and values to append
</ParamField>

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.mixpanel.com/engage \
    --data-urlencode data='[
      {
        "$token": "YOUR_PROJECT_TOKEN",
        "$distinct_id": "user123",
        "$append": {
          "purchase_history": {"item": "Premium Plan", "date": "2024-01-15"},
          "activity_log": "Logged in from mobile"
        }
      }
    ]'
  ```

  ```python Python theme={null}
  data = [{
      "$token": "YOUR_PROJECT_TOKEN",
      "$distinct_id": "user123",
      "$append": {
          "purchase_history": {
              "item": "Premium Plan",
              "amount": 29.99,
              "date": "2024-01-15"
          }
      }
  }]

  response = requests.post(
      'https://api.mixpanel.com/engage',
      data={'data': json.dumps(data)}
  )
  ```
</CodeGroup>

***

## Remove from List Property

Remove specific values from a list property.

### Request Body

<ParamField body="$token" type="string" required>
  Your project token
</ParamField>

<ParamField body="$distinct_id" type="string" required>
  The unique identifier for the user
</ParamField>

<ParamField body="$remove" type="object" required>
  Object with property names and values to remove
</ParamField>

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.mixpanel.com/engage \
    --data-urlencode data='[
      {
        "$token": "YOUR_PROJECT_TOKEN",
        "$distinct_id": "user123",
        "$remove": {
          "favorite_genres": "horror",
          "interests": "deprecated_feature"
        }
      }
    ]'
  ```

  ```python Python theme={null}
  data = [{
      "$token": "YOUR_PROJECT_TOKEN",
      "$distinct_id": "user123",
      "$remove": {
          "favorite_genres": "horror",
          "blocked_users": "user456"
      }
  }]

  response = requests.post(
      'https://api.mixpanel.com/engage',
      data={'data': json.dumps(data)}
  )
  ```
</CodeGroup>

***

## Delete Property

Permanently remove properties from a user profile.

### Request Body

<ParamField body="$token" type="string" required>
  Your project token
</ParamField>

<ParamField body="$distinct_id" type="string" required>
  The unique identifier for the user
</ParamField>

<ParamField body="$unset" type="array" required>
  Array of property names to delete
</ParamField>

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.mixpanel.com/engage \
    --data-urlencode data='[
      {
        "$token": "YOUR_PROJECT_TOKEN",
        "$distinct_id": "user123",
        "$unset": ["temp_token", "session_id", "cache_data"]
      }
    ]'
  ```

  ```python Python theme={null}
  data = [{
      "$token": "YOUR_PROJECT_TOKEN",
      "$distinct_id": "user123",
      "$unset": ["temp_token", "session_id"]
  }]

  response = requests.post(
      'https://api.mixpanel.com/engage',
      data={'data': json.dumps(data)}
  )
  ```
</CodeGroup>

***

## Delete Profile

Permanently delete a user profile and all its properties.

### Request Body

<ParamField body="$token" type="string" required>
  Your project token
</ParamField>

<ParamField body="$distinct_id" type="string" required>
  The unique identifier for the user
</ParamField>

<ParamField body="$delete" type="string" required>
  Set to empty string or null (value is ignored)
</ParamField>

<ParamField body="$ignore_alias" type="boolean">
  Set to `true` to delete only this specific distinct\_id without following alias chains
</ParamField>

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.mixpanel.com/engage \
    --data-urlencode data='[
      {
        "$token": "YOUR_PROJECT_TOKEN",
        "$distinct_id": "user123",
        "$delete": "",
        "$ignore_alias": false
      }
    ]'
  ```

  ```python Python theme={null}
  data = [{
      "$token": "YOUR_PROJECT_TOKEN",
      "$distinct_id": "user123",
      "$delete": "",
      "$ignore_alias": False
  }]

  response = requests.post(
      'https://api.mixpanel.com/engage',
      data={'data': json.dumps(data)}
  )
  ```
</CodeGroup>

<Warning>
  Deleting a profile is permanent and cannot be undone. Use with caution.
</Warning>

***

## Batch Update

Send multiple profile updates in a single request. You can mix different operations.

### Example

<CodeGroup>
  ```python Python theme={null}
  data = [
      {
          "$token": "YOUR_PROJECT_TOKEN",
          "$distinct_id": "user123",
          "$set": {"$email": "user1@example.com"}
      },
      {
          "$token": "YOUR_PROJECT_TOKEN",
          "$distinct_id": "user456",
          "$add": {"login_count": 1}
      },
      {
          "$token": "YOUR_PROJECT_TOKEN",
          "$distinct_id": "user789",
          "$unset": ["temp_data"]
      }
  ]

  response = requests.post(
      'https://api.mixpanel.com/engage',
      data={'data': json.dumps(data)}
  )
  ```
</CodeGroup>

## Reserved Properties

Mixpanel reserves certain property names (prefixed with `$`) for special purposes:

| Property      | Description                               |
| ------------- | ----------------------------------------- |
| `$email`      | User's email address                      |
| `$name`       | User's full name                          |
| `$first_name` | User's first name                         |
| `$last_name`  | User's last name                          |
| `$phone`      | User's phone number                       |
| `$avatar`     | URL to user's avatar image                |
| `$created`    | Profile creation time (set automatically) |
| `$last_seen`  | Last activity time (set automatically)    |

<Note>
  You can use custom properties alongside reserved properties. Just avoid using the `$` prefix for your custom properties.
</Note>

## Best Practices

<AccordionGroup>
  <Accordion title="Use $set_once for immutable properties">
    Properties like signup date or first referrer should use `$set_once` to prevent overwriting:

    ```python theme={null}
    "$set_once": {
        "signup_date": "2024-01-15",
        "first_referrer": "google.com"
    }
    ```
  </Accordion>

  <Accordion title="Batch profile updates">
    Update multiple profiles in a single request for better performance:

    ```python theme={null}
    updates = []
    for user in users:
        updates.append(create_profile_update(user))

    # Send in batches of 2000
    ```
  </Accordion>

  <Accordion title="Use appropriate data types">
    * Numbers for metrics: `"credits": 100`
    * Strings for categories: `"plan": "premium"`
    * Lists for collections: `"interests": ["tech", "gaming"]`
    * ISO dates for timestamps: `"last_purchase": "2024-01-15T10:30:00Z"`
  </Accordion>

  <Accordion title="Keep list properties manageable">
    Avoid storing thousands of items in list properties. Consider:

    * Using counts instead of full lists
    * Storing only recent items
    * Moving historical data to events
  </Accordion>
</AccordionGroup>
